Commit ed19fba6 authored by Ben Schumacher's avatar Ben Schumacher
Browse files

[MM-21703] Send telemetry for all Marketplace plugins (#14846)

parent 594544f7
......@@ -10,6 +10,7 @@ import (
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/services/marketplace"
"github.com/mattermost/mattermost-server/v5/store"
rudder "github.com/rudderlabs/analytics-go"
)
......@@ -649,58 +650,7 @@ func (s *Server) trackConfig() {
"trace": *cfg.ElasticsearchSettings.Trace,
})
pluginConfigData := map[string]interface{}{
"enable_antivirus": pluginActivated(cfg.PluginSettings.PluginStates, "antivirus"),
"enable_autolink": pluginActivated(cfg.PluginSettings.PluginStates, "mattermost-autolink"),
"enable_aws_sns": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.aws-sns"),
"enable_confluence": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.confluence"),
"enable_custom_user_attributes": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.custom-attributes"),
"enable_github": pluginActivated(cfg.PluginSettings.PluginStates, "github"),
"enable_gitlab": pluginActivated(cfg.PluginSettings.PluginStates, "com.github.manland.mattermost-plugin-gitlab"),
"enable_jenkins": pluginActivated(cfg.PluginSettings.PluginStates, "jenkins"),
"enable_jira": pluginActivated(cfg.PluginSettings.PluginStates, "jira"),
"enable_jitsi": pluginActivated(cfg.PluginSettings.PluginStates, "jitsi"),
"enable_mscalendar": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.mscalendar"),
"enable_nps": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.nps"),
"enable_skype4business": pluginActivated(cfg.PluginSettings.PluginStates, "skype4business"),
"enable_todo": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.plugin-todo"),
"enable_webex": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.webex"),
"enable_welcome_bot": pluginActivated(cfg.PluginSettings.PluginStates, "com.mattermost.welcomebot"),
"enable_zoom": pluginActivated(cfg.PluginSettings.PluginStates, "zoom"),
"enable_nps_survey": pluginSetting(&cfg.PluginSettings, "com.mattermost.nps", "enablesurvey", true),
"enable": *cfg.PluginSettings.Enable,
"enable_uploads": *cfg.PluginSettings.EnableUploads,
"allow_insecure_download_url": *cfg.PluginSettings.AllowInsecureDownloadUrl,
"enable_health_check": *cfg.PluginSettings.EnableHealthCheck,
"enable_marketplace": *cfg.PluginSettings.EnableMarketplace,
"require_pluginSignature": *cfg.PluginSettings.RequirePluginSignature,
"enable_remote_marketplace": *cfg.PluginSettings.EnableRemoteMarketplace,
"automatic_prepackaged_plugins": *cfg.PluginSettings.AutomaticPrepackagedPlugins,
"is_default_marketplace_url": isDefault(*cfg.PluginSettings.MarketplaceUrl, model.PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL),
"signature_public_key_files": len(cfg.PluginSettings.SignaturePublicKeyFiles),
}
pluginsEnvironment := s.GetPluginsEnvironment()
if pluginsEnvironment != nil {
if plugins, appErr := pluginsEnvironment.Available(); appErr != nil {
mlog.Error("Unable to add plugin versions to diagnostics", mlog.Err(appErr))
} else {
pluginConfigData["version_antivirus"] = pluginVersion(plugins, "antivirus")
pluginConfigData["version_autolink"] = pluginVersion(plugins, "mattermost-autolink")
pluginConfigData["version_aws_sns"] = pluginVersion(plugins, "com.mattermost.aws-sns")
pluginConfigData["version_custom_user_attributes"] = pluginVersion(plugins, "com.mattermost.custom-attributes")
pluginConfigData["version_github"] = pluginVersion(plugins, "github")
pluginConfigData["version_gitlab"] = pluginVersion(plugins, "com.github.manland.mattermost-plugin-gitlab")
pluginConfigData["version_jenkins"] = pluginVersion(plugins, "jenkins")
pluginConfigData["version_jira"] = pluginVersion(plugins, "jira")
pluginConfigData["version_nps"] = pluginVersion(plugins, "com.mattermost.nps")
pluginConfigData["version_webex"] = pluginVersion(plugins, "com.mattermost.webex")
pluginConfigData["version_welcome_bot"] = pluginVersion(plugins, "com.mattermost.welcomebot")
pluginConfigData["version_zoom"] = pluginVersion(plugins, "zoom")
}
}
s.SendDiagnostic(TRACK_CONFIG_PLUGIN, pluginConfigData)
s.trackPluginConfig(cfg, model.PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL)
s.SendDiagnostic(TRACK_CONFIG_DATA_RETENTION, map[string]interface{}{
"enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion,
......@@ -1107,3 +1057,108 @@ func (s *Server) trackWarnMetrics() {
}
}
}
func (s *Server) trackPluginConfig(cfg *model.Config, marketplaceURL string) {
pluginConfigData := map[string]interface{}{
"enable_nps_survey": pluginSetting(&cfg.PluginSettings, "com.mattermost.nps", "enablesurvey", true),
"enable": *cfg.PluginSettings.Enable,
"enable_uploads": *cfg.PluginSettings.EnableUploads,
"allow_insecure_download_url": *cfg.PluginSettings.AllowInsecureDownloadUrl,
"enable_health_check": *cfg.PluginSettings.EnableHealthCheck,
"enable_marketplace": *cfg.PluginSettings.EnableMarketplace,
"require_pluginSignature": *cfg.PluginSettings.RequirePluginSignature,
"enable_remote_marketplace": *cfg.PluginSettings.EnableRemoteMarketplace,
"automatic_prepackaged_plugins": *cfg.PluginSettings.AutomaticPrepackagedPlugins,
"is_default_marketplace_url": isDefault(*cfg.PluginSettings.MarketplaceUrl, model.PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL),
"signature_public_key_files": len(cfg.PluginSettings.SignaturePublicKeyFiles),
}
// knownPluginIDs lists all known plugin IDs in the Marketplace
knownPluginIDs := []string{
"antivirus",
"com.github.manland.mattermost-plugin-gitlab",
"com.github.moussetc.mattermost.plugin.giphy",
"com.github.phillipahereza.mattermost-plugin-digitalocean",
"com.mattermost.aws-sns",
"com.mattermost.confluence",
"com.mattermost.custom-attributes",
"com.mattermost.mscalendar",
"com.mattermost.nps",
"com.mattermost.plugin-incident-response",
"com.mattermost.plugin-todo",
"com.mattermost.webex",
"com.mattermost.welcomebot",
"github",
"jenkins",
"jira",
"jitsi",
"mattermost-autolink",
"memes",
"skype4business",
"zoom",
}
marketplacePlugins, err := s.getAllMarketplaceplugins(marketplaceURL)
if err != nil {
mlog.Info("Failed to fetch marketplace plugins for telemetry. Using predefined list.", mlog.Err(err))
for _, id := range knownPluginIDs {
pluginConfigData["enable_"+id] = pluginActivated(cfg.PluginSettings.PluginStates, id)
}
} else {
for _, p := range marketplacePlugins {
id := p.Manifest.Id
pluginConfigData["enable_"+id] = pluginActivated(cfg.PluginSettings.PluginStates, id)
}
}
pluginsEnvironment := s.GetPluginsEnvironment()
if pluginsEnvironment != nil {
if plugins, appErr := pluginsEnvironment.Available(); appErr != nil {
mlog.Error("Unable to add plugin versions to diagnostics", mlog.Err(appErr))
} else {
// If marketplace request failed, use predefined list
if marketplacePlugins == nil {
for _, id := range knownPluginIDs {
pluginConfigData["version_"+id] = pluginActivated(cfg.PluginSettings.PluginStates, id)
}
} else {
for _, p := range marketplacePlugins {
id := p.Manifest.Id
pluginConfigData["version_"+id] = pluginVersion(plugins, id)
}
}
}
}
s.SendDiagnostic(TRACK_CONFIG_PLUGIN, pluginConfigData)
}
func (s *Server) getAllMarketplaceplugins(marketplaceURL string) ([]*model.BaseMarketplacePlugin, error) {
marketplaceClient, err := marketplace.NewClient(
marketplaceURL,
s.HTTPService,
)
if err != nil {
return nil, err
}
// Fetch all plugins from marketplace.
filter := &model.MarketplacePluginFilter{
PerPage: -1,
ServerVersion: model.CurrentVersion,
}
license := s.License()
if license != nil && *license.Features.EnterprisePlugins {
filter.EnterprisePlugins = true
}
if model.BuildEnterpriseReady == "true" {
filter.BuildEnterpriseReady = true
}
return marketplaceClient.GetPlugins(filter)
}
......@@ -73,17 +73,19 @@ func TestRudderDiagnostics(t *testing.T) {
})
defer th.TearDown()
type batch struct {
MessageId string
UserId string
Event string
Timestamp time.Time
Properties map[string]interface{}
}
type payload struct {
MessageId string
SentAt time.Time
Batch []struct {
MessageId string
UserId string
Event string
Timestamp time.Time
Properties map[string]interface{}
}
Context struct {
Batch []batch
Context struct {
Library struct {
Name string
Version string
......@@ -104,6 +106,21 @@ func TestRudderDiagnostics(t *testing.T) {
}))
defer server.Close()
marketplaceServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.WriteHeader(http.StatusOK)
json, err := json.Marshal([]*model.MarketplacePlugin{{
BaseMarketplacePlugin: &model.BaseMarketplacePlugin{
Manifest: &model.Manifest{
Id: "testplugin",
},
},
}})
require.NoError(t, err)
res.Write(json)
}))
defer func() { marketplaceServer.Close() }()
diagnosticID := "test-diagnostic-id-12345"
th.App.SetDiagnosticId(diagnosticID)
th.Server.initDiagnostics(server.URL)
......@@ -140,6 +157,19 @@ func TestRudderDiagnostics(t *testing.T) {
}
}
collectBatches := func(info *[]batch) {
t.Helper()
for {
select {
case result := <-data:
assertPayload(t, result, "", nil)
*info = append(*info, result.Batch[0])
case <-time.After(time.Second * 1):
return
}
}
}
// Should send a client identify message
select {
case identifyMessage := <-data:
......@@ -245,6 +275,42 @@ func TestRudderDiagnostics(t *testing.T) {
}
})
t.Run("Diagnostics for Marketplace plugins is returned", func(t *testing.T) {
th.App.Srv().trackPluginConfig(th.App.Srv().Config(), marketplaceServer.URL)
var batches []batch
collectBatches(&batches)
for _, b := range batches {
if b.Event == TRACK_CONFIG_PLUGIN {
assert.Contains(t, b.Properties, "enable_testplugin")
assert.Contains(t, b.Properties, "version_testplugin")
// Confirm known plugins are not present
assert.NotContains(t, b.Properties, "enable_jira")
assert.NotContains(t, b.Properties, "version_jira")
}
}
})
t.Run("Diagnostics for known plugins is returned, if request to Marketplace fails", func(t *testing.T) {
th.App.Srv().trackPluginConfig(th.App.Srv().Config(), "http://some.random.invalid.url")
var batches []batch
collectBatches(&batches)
for _, b := range batches {
if b.Event == TRACK_CONFIG_PLUGIN {
assert.NotContains(t, b.Properties, "enable_testplugin")
assert.NotContains(t, b.Properties, "version_testplugin")
// Confirm known plugins are present
assert.Contains(t, b.Properties, "enable_jira")
assert.Contains(t, b.Properties, "version_jira")
}
}
})
t.Run("SendDailyDiagnosticsNoRudderKey", func(t *testing.T) {
th.App.Srv().SendDailyDiagnostics()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment