github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+incompatible/app/diagnostics.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"encoding/json"
     8  	"log"
     9  	"os"
    10  	"runtime"
    11  	"sync/atomic"
    12  
    13  	"github.com/mattermost/mattermost-server/model"
    14  	"github.com/mattermost/mattermost-server/utils"
    15  	"github.com/segmentio/analytics-go"
    16  )
    17  
    18  const (
    19  	SEGMENT_KEY = "fwb7VPbFeQ7SKp3wHm1RzFUuXZudqVok"
    20  
    21  	TRACK_CONFIG_SERVICE        = "config_service"
    22  	TRACK_CONFIG_TEAM           = "config_team"
    23  	TRACK_CONFIG_CLIENT_REQ     = "config_client_requirements"
    24  	TRACK_CONFIG_SQL            = "config_sql"
    25  	TRACK_CONFIG_LOG            = "config_log"
    26  	TRACK_CONFIG_FILE           = "config_file"
    27  	TRACK_CONFIG_RATE           = "config_rate"
    28  	TRACK_CONFIG_EMAIL          = "config_email"
    29  	TRACK_CONFIG_PRIVACY        = "config_privacy"
    30  	TRACK_CONFIG_THEME          = "config_theme"
    31  	TRACK_CONFIG_OAUTH          = "config_oauth"
    32  	TRACK_CONFIG_LDAP           = "config_ldap"
    33  	TRACK_CONFIG_COMPLIANCE     = "config_compliance"
    34  	TRACK_CONFIG_LOCALIZATION   = "config_localization"
    35  	TRACK_CONFIG_SAML           = "config_saml"
    36  	TRACK_CONFIG_PASSWORD       = "config_password"
    37  	TRACK_CONFIG_CLUSTER        = "config_cluster"
    38  	TRACK_CONFIG_METRICS        = "config_metrics"
    39  	TRACK_CONFIG_WEBRTC         = "config_webrtc"
    40  	TRACK_CONFIG_SUPPORT        = "config_support"
    41  	TRACK_CONFIG_NATIVEAPP      = "config_nativeapp"
    42  	TRACK_CONFIG_ANALYTICS      = "config_analytics"
    43  	TRACK_CONFIG_ANNOUNCEMENT   = "config_announcement"
    44  	TRACK_CONFIG_ELASTICSEARCH  = "config_elasticsearch"
    45  	TRACK_CONFIG_PLUGIN         = "config_plugin"
    46  	TRACK_CONFIG_DATA_RETENTION = "config_data_retention"
    47  	TRACK_CONFIG_MESSAGE_EXPORT = "config_message_export"
    48  
    49  	TRACK_ACTIVITY = "activity"
    50  	TRACK_LICENSE  = "license"
    51  	TRACK_SERVER   = "server"
    52  	TRACK_PLUGINS  = "plugins"
    53  )
    54  
    55  var client *analytics.Client
    56  
    57  func (a *App) SendDailyDiagnostics() {
    58  	if *a.Config().LogSettings.EnableDiagnostics && a.IsLeader() {
    59  		a.initDiagnostics("")
    60  		a.trackActivity()
    61  		a.trackConfig()
    62  		a.trackLicense()
    63  		a.trackPlugins()
    64  		a.trackServer()
    65  	}
    66  }
    67  
    68  func (a *App) initDiagnostics(endpoint string) {
    69  	if client == nil {
    70  		client = analytics.New(SEGMENT_KEY)
    71  		// For testing
    72  		if endpoint != "" {
    73  			client.Endpoint = endpoint
    74  			client.Verbose = true
    75  			client.Size = 1
    76  			client.Logger = log.New(os.Stdout, "segment ", log.LstdFlags)
    77  		}
    78  		client.Identify(&analytics.Identify{
    79  			UserId: a.DiagnosticId(),
    80  		})
    81  	}
    82  }
    83  
    84  func (a *App) SendDiagnostic(event string, properties map[string]interface{}) {
    85  	client.Track(&analytics.Track{
    86  		Event:      event,
    87  		UserId:     a.DiagnosticId(),
    88  		Properties: properties,
    89  	})
    90  }
    91  
    92  func isDefault(setting interface{}, defaultValue interface{}) bool {
    93  	return setting == defaultValue
    94  }
    95  
    96  func pluginSetting(pluginSettings *model.PluginSettings, plugin, key string, defaultValue interface{}) interface{} {
    97  	settings, ok := pluginSettings.Plugins[plugin]
    98  	if !ok {
    99  		return defaultValue
   100  	}
   101  	var m map[string]interface{}
   102  	if b, err := json.Marshal(settings); err != nil {
   103  		return defaultValue
   104  	} else {
   105  		json.Unmarshal(b, &m)
   106  	}
   107  	if value, ok := m[key]; ok {
   108  		return value
   109  	}
   110  	return defaultValue
   111  }
   112  
   113  func pluginActivated(pluginStates map[string]*model.PluginState, pluginId string) bool {
   114  	state, ok := pluginStates[pluginId]
   115  	if !ok {
   116  		return false
   117  	}
   118  	return state.Enable
   119  }
   120  
   121  func (a *App) trackActivity() {
   122  	var userCount int64
   123  	var activeUserCount int64
   124  	var inactiveUserCount int64
   125  	var teamCount int64
   126  	var publicChannelCount int64
   127  	var privateChannelCount int64
   128  	var directChannelCount int64
   129  	var deletedPublicChannelCount int64
   130  	var deletedPrivateChannelCount int64
   131  	var postsCount int64
   132  
   133  	if ucr := <-a.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
   134  		userCount = ucr.Data.(int64)
   135  	}
   136  
   137  	if ucr := <-a.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
   138  		activeUserCount = ucr.Data.(int64)
   139  	}
   140  
   141  	if iucr := <-a.Srv.Store.Status().GetTotalActiveUsersCount(); iucr.Err == nil {
   142  		inactiveUserCount = iucr.Data.(int64)
   143  	}
   144  
   145  	if tcr := <-a.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
   146  		teamCount = tcr.Data.(int64)
   147  	}
   148  
   149  	if ucc := <-a.Srv.Store.Channel().AnalyticsTypeCount("", "O"); ucc.Err == nil {
   150  		publicChannelCount = ucc.Data.(int64)
   151  	}
   152  
   153  	if pcc := <-a.Srv.Store.Channel().AnalyticsTypeCount("", "P"); pcc.Err == nil {
   154  		privateChannelCount = pcc.Data.(int64)
   155  	}
   156  
   157  	if dcc := <-a.Srv.Store.Channel().AnalyticsTypeCount("", "D"); dcc.Err == nil {
   158  		directChannelCount = dcc.Data.(int64)
   159  	}
   160  
   161  	if duccr := <-a.Srv.Store.Channel().AnalyticsDeletedTypeCount("", "O"); duccr.Err == nil {
   162  		deletedPublicChannelCount = duccr.Data.(int64)
   163  	}
   164  
   165  	if dpccr := <-a.Srv.Store.Channel().AnalyticsDeletedTypeCount("", "P"); dpccr.Err == nil {
   166  		deletedPrivateChannelCount = dpccr.Data.(int64)
   167  	}
   168  
   169  	if pcr := <-a.Srv.Store.Post().AnalyticsPostCount("", false, false); pcr.Err == nil {
   170  		postsCount = pcr.Data.(int64)
   171  	}
   172  
   173  	a.SendDiagnostic(TRACK_ACTIVITY, map[string]interface{}{
   174  		"registered_users":          userCount,
   175  		"active_users":              activeUserCount,
   176  		"registered_inactive_users": inactiveUserCount,
   177  		"teams":                     teamCount,
   178  		"public_channels":           publicChannelCount,
   179  		"private_channels":          privateChannelCount,
   180  		"direct_message_channels":   directChannelCount,
   181  		"public_channels_deleted":   deletedPublicChannelCount,
   182  		"private_channels_deleted":  deletedPrivateChannelCount,
   183  		"posts":                     postsCount,
   184  		"used_apiv3":                atomic.LoadInt32(model.UsedApiV3) == 1,
   185  	})
   186  
   187  	atomic.StoreInt32(model.UsedApiV3, 0)
   188  }
   189  
   190  func (a *App) trackConfig() {
   191  	cfg := a.Config()
   192  	a.SendDiagnostic(TRACK_CONFIG_SERVICE, map[string]interface{}{
   193  		"web_server_mode":                                         *cfg.ServiceSettings.WebserverMode,
   194  		"enable_security_fix_alert":                               *cfg.ServiceSettings.EnableSecurityFixAlert,
   195  		"enable_insecure_outgoing_connections":                    *cfg.ServiceSettings.EnableInsecureOutgoingConnections,
   196  		"enable_incoming_webhooks":                                cfg.ServiceSettings.EnableIncomingWebhooks,
   197  		"enable_outgoing_webhooks":                                cfg.ServiceSettings.EnableOutgoingWebhooks,
   198  		"enable_commands":                                         *cfg.ServiceSettings.EnableCommands,
   199  		"enable_only_admin_integrations":                          *cfg.ServiceSettings.EnableOnlyAdminIntegrations,
   200  		"enable_post_username_override":                           cfg.ServiceSettings.EnablePostUsernameOverride,
   201  		"enable_post_icon_override":                               cfg.ServiceSettings.EnablePostIconOverride,
   202  		"enable_apiv3":                                            *cfg.ServiceSettings.EnableAPIv3,
   203  		"enable_user_access_tokens":                               *cfg.ServiceSettings.EnableUserAccessTokens,
   204  		"enable_custom_emoji":                                     *cfg.ServiceSettings.EnableCustomEmoji,
   205  		"enable_emoji_picker":                                     *cfg.ServiceSettings.EnableEmojiPicker,
   206  		"experimental_enable_authentication_transfer":             *cfg.ServiceSettings.ExperimentalEnableAuthenticationTransfer,
   207  		"restrict_custom_emoji_creation":                          *cfg.ServiceSettings.RestrictCustomEmojiCreation,
   208  		"enable_testing":                                          cfg.ServiceSettings.EnableTesting,
   209  		"enable_developer":                                        *cfg.ServiceSettings.EnableDeveloper,
   210  		"enable_multifactor_authentication":                       *cfg.ServiceSettings.EnableMultifactorAuthentication,
   211  		"enforce_multifactor_authentication":                      *cfg.ServiceSettings.EnforceMultifactorAuthentication,
   212  		"enable_oauth_service_provider":                           cfg.ServiceSettings.EnableOAuthServiceProvider,
   213  		"connection_security":                                     *cfg.ServiceSettings.ConnectionSecurity,
   214  		"uses_letsencrypt":                                        *cfg.ServiceSettings.UseLetsEncrypt,
   215  		"forward_80_to_443":                                       *cfg.ServiceSettings.Forward80To443,
   216  		"maximum_login_attempts":                                  *cfg.ServiceSettings.MaximumLoginAttempts,
   217  		"session_length_web_in_days":                              *cfg.ServiceSettings.SessionLengthWebInDays,
   218  		"session_length_mobile_in_days":                           *cfg.ServiceSettings.SessionLengthMobileInDays,
   219  		"session_length_sso_in_days":                              *cfg.ServiceSettings.SessionLengthSSOInDays,
   220  		"session_cache_in_minutes":                                *cfg.ServiceSettings.SessionCacheInMinutes,
   221  		"session_idle_timeout_in_minutes":                         *cfg.ServiceSettings.SessionIdleTimeoutInMinutes,
   222  		"isdefault_site_url":                                      isDefault(*cfg.ServiceSettings.SiteURL, model.SERVICE_SETTINGS_DEFAULT_SITE_URL),
   223  		"isdefault_tls_cert_file":                                 isDefault(*cfg.ServiceSettings.TLSCertFile, model.SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE),
   224  		"isdefault_tls_key_file":                                  isDefault(*cfg.ServiceSettings.TLSKeyFile, model.SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE),
   225  		"isdefault_read_timeout":                                  isDefault(*cfg.ServiceSettings.ReadTimeout, model.SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT),
   226  		"isdefault_write_timeout":                                 isDefault(*cfg.ServiceSettings.WriteTimeout, model.SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT),
   227  		"isdefault_google_developer_key":                          isDefault(cfg.ServiceSettings.GoogleDeveloperKey, ""),
   228  		"isdefault_allow_cors_from":                               isDefault(*cfg.ServiceSettings.AllowCorsFrom, model.SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM),
   229  		"isdefault_allowed_untrusted_internal_connections":        isDefault(*cfg.ServiceSettings.AllowedUntrustedInternalConnections, ""),
   230  		"restrict_post_delete":                                    *cfg.ServiceSettings.RestrictPostDelete,
   231  		"allow_edit_post":                                         *cfg.ServiceSettings.AllowEditPost,
   232  		"post_edit_time_limit":                                    *cfg.ServiceSettings.PostEditTimeLimit,
   233  		"enable_user_typing_messages":                             *cfg.ServiceSettings.EnableUserTypingMessages,
   234  		"enable_channel_viewed_messages":                          *cfg.ServiceSettings.EnableChannelViewedMessages,
   235  		"time_between_user_typing_updates_milliseconds":           *cfg.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds,
   236  		"cluster_log_timeout_milliseconds":                        *cfg.ServiceSettings.ClusterLogTimeoutMilliseconds,
   237  		"enable_post_search":                                      *cfg.ServiceSettings.EnablePostSearch,
   238  		"enable_user_statuses":                                    *cfg.ServiceSettings.EnableUserStatuses,
   239  		"close_unused_direct_messages":                            *cfg.ServiceSettings.CloseUnusedDirectMessages,
   240  		"enable_preview_features":                                 *cfg.ServiceSettings.EnablePreviewFeatures,
   241  		"enable_tutorial":                                         *cfg.ServiceSettings.EnableTutorial,
   242  		"experimental_enable_default_channel_leave_join_messages": *cfg.ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages,
   243  		"experimental_group_unread_channels":                      *cfg.ServiceSettings.ExperimentalGroupUnreadChannels,
   244  	})
   245  
   246  	a.SendDiagnostic(TRACK_CONFIG_TEAM, map[string]interface{}{
   247  		"enable_user_creation":                    cfg.TeamSettings.EnableUserCreation,
   248  		"enable_team_creation":                    cfg.TeamSettings.EnableTeamCreation,
   249  		"restrict_team_invite":                    *cfg.TeamSettings.RestrictTeamInvite,
   250  		"restrict_public_channel_creation":        *cfg.TeamSettings.RestrictPublicChannelCreation,
   251  		"restrict_private_channel_creation":       *cfg.TeamSettings.RestrictPrivateChannelCreation,
   252  		"restrict_public_channel_management":      *cfg.TeamSettings.RestrictPublicChannelManagement,
   253  		"restrict_private_channel_management":     *cfg.TeamSettings.RestrictPrivateChannelManagement,
   254  		"restrict_public_channel_deletion":        *cfg.TeamSettings.RestrictPublicChannelDeletion,
   255  		"restrict_private_channel_deletion":       *cfg.TeamSettings.RestrictPrivateChannelDeletion,
   256  		"enable_open_server":                      *cfg.TeamSettings.EnableOpenServer,
   257  		"enable_custom_brand":                     *cfg.TeamSettings.EnableCustomBrand,
   258  		"restrict_direct_message":                 *cfg.TeamSettings.RestrictDirectMessage,
   259  		"max_notifications_per_channel":           *cfg.TeamSettings.MaxNotificationsPerChannel,
   260  		"enable_confirm_notifications_to_channel": *cfg.TeamSettings.EnableConfirmNotificationsToChannel,
   261  		"max_users_per_team":                      *cfg.TeamSettings.MaxUsersPerTeam,
   262  		"max_channels_per_team":                   *cfg.TeamSettings.MaxChannelsPerTeam,
   263  		"teammate_name_display":                   *cfg.TeamSettings.TeammateNameDisplay,
   264  		"isdefault_site_name":                     isDefault(cfg.TeamSettings.SiteName, "Mattermost"),
   265  		"isdefault_custom_brand_text":             isDefault(*cfg.TeamSettings.CustomBrandText, model.TEAM_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT),
   266  		"isdefault_custom_description_text":       isDefault(*cfg.TeamSettings.CustomDescriptionText, model.TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT),
   267  		"isdefault_user_status_away_timeout":      isDefault(*cfg.TeamSettings.UserStatusAwayTimeout, model.TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT),
   268  		"restrict_private_channel_manage_members": *cfg.TeamSettings.RestrictPrivateChannelManageMembers,
   269  		"enable_X_to_leave_channels_from_LHS":     *cfg.TeamSettings.EnableXToLeaveChannelsFromLHS,
   270  		"experimental_town_square_is_read_only":   *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly,
   271  		"experimental_primary_team":               isDefault(*cfg.TeamSettings.ExperimentalPrimaryTeam, ""),
   272  	})
   273  
   274  	a.SendDiagnostic(TRACK_CONFIG_CLIENT_REQ, map[string]interface{}{
   275  		"android_latest_version": cfg.ClientRequirements.AndroidLatestVersion,
   276  		"android_min_version":    cfg.ClientRequirements.AndroidMinVersion,
   277  		"desktop_latest_version": cfg.ClientRequirements.DesktopLatestVersion,
   278  		"desktop_min_version":    cfg.ClientRequirements.DesktopMinVersion,
   279  		"ios_latest_version":     cfg.ClientRequirements.IosLatestVersion,
   280  		"ios_min_version":        cfg.ClientRequirements.IosMinVersion,
   281  	})
   282  
   283  	a.SendDiagnostic(TRACK_CONFIG_SQL, map[string]interface{}{
   284  		"driver_name":                 *cfg.SqlSettings.DriverName,
   285  		"trace":                       cfg.SqlSettings.Trace,
   286  		"max_idle_conns":              *cfg.SqlSettings.MaxIdleConns,
   287  		"max_open_conns":              *cfg.SqlSettings.MaxOpenConns,
   288  		"data_source_replicas":        len(cfg.SqlSettings.DataSourceReplicas),
   289  		"data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas),
   290  		"query_timeout":               *cfg.SqlSettings.QueryTimeout,
   291  	})
   292  
   293  	a.SendDiagnostic(TRACK_CONFIG_LOG, map[string]interface{}{
   294  		"enable_console":           cfg.LogSettings.EnableConsole,
   295  		"console_level":            cfg.LogSettings.ConsoleLevel,
   296  		"enable_file":              cfg.LogSettings.EnableFile,
   297  		"file_level":               cfg.LogSettings.FileLevel,
   298  		"enable_webhook_debugging": cfg.LogSettings.EnableWebhookDebugging,
   299  		"isdefault_file_format":    isDefault(cfg.LogSettings.FileFormat, ""),
   300  		"isdefault_file_location":  isDefault(cfg.LogSettings.FileLocation, ""),
   301  	})
   302  
   303  	a.SendDiagnostic(TRACK_CONFIG_PASSWORD, map[string]interface{}{
   304  		"minimum_length": *cfg.PasswordSettings.MinimumLength,
   305  		"lowercase":      *cfg.PasswordSettings.Lowercase,
   306  		"number":         *cfg.PasswordSettings.Number,
   307  		"uppercase":      *cfg.PasswordSettings.Uppercase,
   308  		"symbol":         *cfg.PasswordSettings.Symbol,
   309  	})
   310  
   311  	a.SendDiagnostic(TRACK_CONFIG_FILE, map[string]interface{}{
   312  		"enable_public_links":     cfg.FileSettings.EnablePublicLink,
   313  		"driver_name":             *cfg.FileSettings.DriverName,
   314  		"amazon_s3_ssl":           *cfg.FileSettings.AmazonS3SSL,
   315  		"amazon_s3_sse":           *cfg.FileSettings.AmazonS3SSE,
   316  		"amazon_s3_signv2":        *cfg.FileSettings.AmazonS3SignV2,
   317  		"amazon_s3_trace":         *cfg.FileSettings.AmazonS3Trace,
   318  		"max_file_size":           *cfg.FileSettings.MaxFileSize,
   319  		"enable_file_attachments": *cfg.FileSettings.EnableFileAttachments,
   320  		"enable_mobile_upload":    *cfg.FileSettings.EnableMobileUpload,
   321  		"enable_mobile_download":  *cfg.FileSettings.EnableMobileDownload,
   322  	})
   323  
   324  	a.SendDiagnostic(TRACK_CONFIG_EMAIL, map[string]interface{}{
   325  		"enable_sign_up_with_email":            cfg.EmailSettings.EnableSignUpWithEmail,
   326  		"enable_sign_in_with_email":            *cfg.EmailSettings.EnableSignInWithEmail,
   327  		"enable_sign_in_with_username":         *cfg.EmailSettings.EnableSignInWithUsername,
   328  		"require_email_verification":           cfg.EmailSettings.RequireEmailVerification,
   329  		"send_email_notifications":             cfg.EmailSettings.SendEmailNotifications,
   330  		"use_channel_in_email_notifications":   *cfg.EmailSettings.UseChannelInEmailNotifications,
   331  		"email_notification_contents_type":     *cfg.EmailSettings.EmailNotificationContentsType,
   332  		"enable_smtp_auth":                     *cfg.EmailSettings.EnableSMTPAuth,
   333  		"connection_security":                  cfg.EmailSettings.ConnectionSecurity,
   334  		"send_push_notifications":              *cfg.EmailSettings.SendPushNotifications,
   335  		"push_notification_contents":           *cfg.EmailSettings.PushNotificationContents,
   336  		"enable_email_batching":                *cfg.EmailSettings.EnableEmailBatching,
   337  		"email_batching_buffer_size":           *cfg.EmailSettings.EmailBatchingBufferSize,
   338  		"email_batching_interval":              *cfg.EmailSettings.EmailBatchingInterval,
   339  		"isdefault_feedback_name":              isDefault(cfg.EmailSettings.FeedbackName, ""),
   340  		"isdefault_feedback_email":             isDefault(cfg.EmailSettings.FeedbackEmail, ""),
   341  		"isdefault_feedback_organization":      isDefault(*cfg.EmailSettings.FeedbackOrganization, model.EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION),
   342  		"skip_server_certificate_verification": *cfg.EmailSettings.SkipServerCertificateVerification,
   343  		"isdefault_login_button_color":         isDefault(*cfg.EmailSettings.LoginButtonColor, ""),
   344  		"isdefault_login_button_border_color":  isDefault(*cfg.EmailSettings.LoginButtonBorderColor, ""),
   345  		"isdefault_login_button_text_color":    isDefault(*cfg.EmailSettings.LoginButtonTextColor, ""),
   346  	})
   347  
   348  	a.SendDiagnostic(TRACK_CONFIG_RATE, map[string]interface{}{
   349  		"enable_rate_limiter":      *cfg.RateLimitSettings.Enable,
   350  		"vary_by_remote_address":   cfg.RateLimitSettings.VaryByRemoteAddr,
   351  		"per_sec":                  *cfg.RateLimitSettings.PerSec,
   352  		"max_burst":                *cfg.RateLimitSettings.MaxBurst,
   353  		"memory_store_size":        *cfg.RateLimitSettings.MemoryStoreSize,
   354  		"isdefault_vary_by_header": isDefault(cfg.RateLimitSettings.VaryByHeader, ""),
   355  	})
   356  
   357  	a.SendDiagnostic(TRACK_CONFIG_PRIVACY, map[string]interface{}{
   358  		"show_email_address": cfg.PrivacySettings.ShowEmailAddress,
   359  		"show_full_name":     cfg.PrivacySettings.ShowFullName,
   360  	})
   361  
   362  	a.SendDiagnostic(TRACK_CONFIG_THEME, map[string]interface{}{
   363  		"enable_theme_selection":  *cfg.ThemeSettings.EnableThemeSelection,
   364  		"isdefault_default_theme": isDefault(*cfg.ThemeSettings.DefaultTheme, model.TEAM_SETTINGS_DEFAULT_TEAM_TEXT),
   365  		"allow_custom_themes":     *cfg.ThemeSettings.AllowCustomThemes,
   366  		"allowed_themes":          len(cfg.ThemeSettings.AllowedThemes),
   367  	})
   368  
   369  	a.SendDiagnostic(TRACK_CONFIG_OAUTH, map[string]interface{}{
   370  		"enable_gitlab":    cfg.GitLabSettings.Enable,
   371  		"enable_google":    cfg.GoogleSettings.Enable,
   372  		"enable_office365": cfg.Office365Settings.Enable,
   373  	})
   374  
   375  	a.SendDiagnostic(TRACK_CONFIG_SUPPORT, map[string]interface{}{
   376  		"isdefault_terms_of_service_link": isDefault(*cfg.SupportSettings.TermsOfServiceLink, model.SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK),
   377  		"isdefault_privacy_policy_link":   isDefault(*cfg.SupportSettings.PrivacyPolicyLink, model.SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK),
   378  		"isdefault_about_link":            isDefault(*cfg.SupportSettings.AboutLink, model.SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK),
   379  		"isdefault_help_link":             isDefault(*cfg.SupportSettings.HelpLink, model.SUPPORT_SETTINGS_DEFAULT_HELP_LINK),
   380  		"isdefault_report_a_problem_link": isDefault(*cfg.SupportSettings.ReportAProblemLink, model.SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK),
   381  		"isdefault_support_email":         isDefault(*cfg.SupportSettings.SupportEmail, model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL),
   382  	})
   383  
   384  	a.SendDiagnostic(TRACK_CONFIG_LDAP, map[string]interface{}{
   385  		"enable":                              *cfg.LdapSettings.Enable,
   386  		"enable_sync":                         *cfg.LdapSettings.EnableSync,
   387  		"connection_security":                 *cfg.LdapSettings.ConnectionSecurity,
   388  		"skip_certificate_verification":       *cfg.LdapSettings.SkipCertificateVerification,
   389  		"sync_interval_minutes":               *cfg.LdapSettings.SyncIntervalMinutes,
   390  		"query_timeout":                       *cfg.LdapSettings.QueryTimeout,
   391  		"max_page_size":                       *cfg.LdapSettings.MaxPageSize,
   392  		"isdefault_first_name_attribute":      isDefault(*cfg.LdapSettings.FirstNameAttribute, model.LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE),
   393  		"isdefault_last_name_attribute":       isDefault(*cfg.LdapSettings.LastNameAttribute, model.LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE),
   394  		"isdefault_email_attribute":           isDefault(*cfg.LdapSettings.EmailAttribute, model.LDAP_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE),
   395  		"isdefault_username_attribute":        isDefault(*cfg.LdapSettings.UsernameAttribute, model.LDAP_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE),
   396  		"isdefault_nickname_attribute":        isDefault(*cfg.LdapSettings.NicknameAttribute, model.LDAP_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE),
   397  		"isdefault_id_attribute":              isDefault(*cfg.LdapSettings.IdAttribute, model.LDAP_SETTINGS_DEFAULT_ID_ATTRIBUTE),
   398  		"isdefault_position_attribute":        isDefault(*cfg.LdapSettings.PositionAttribute, model.LDAP_SETTINGS_DEFAULT_POSITION_ATTRIBUTE),
   399  		"isdefault_login_field_name":          isDefault(*cfg.LdapSettings.LoginFieldName, model.LDAP_SETTINGS_DEFAULT_LOGIN_FIELD_NAME),
   400  		"isdefault_login_button_color":        isDefault(*cfg.LdapSettings.LoginButtonColor, ""),
   401  		"isdefault_login_button_border_color": isDefault(*cfg.LdapSettings.LoginButtonBorderColor, ""),
   402  		"isdefault_login_button_text_color":   isDefault(*cfg.LdapSettings.LoginButtonTextColor, ""),
   403  	})
   404  
   405  	a.SendDiagnostic(TRACK_CONFIG_COMPLIANCE, map[string]interface{}{
   406  		"enable":       *cfg.ComplianceSettings.Enable,
   407  		"enable_daily": *cfg.ComplianceSettings.EnableDaily,
   408  	})
   409  
   410  	a.SendDiagnostic(TRACK_CONFIG_LOCALIZATION, map[string]interface{}{
   411  		"default_server_locale": *cfg.LocalizationSettings.DefaultServerLocale,
   412  		"default_client_locale": *cfg.LocalizationSettings.DefaultClientLocale,
   413  		"available_locales":     *cfg.LocalizationSettings.AvailableLocales,
   414  	})
   415  
   416  	a.SendDiagnostic(TRACK_CONFIG_SAML, map[string]interface{}{
   417  		"enable":                              *cfg.SamlSettings.Enable,
   418  		"enable_sync_with_ldap":               *cfg.SamlSettings.EnableSyncWithLdap,
   419  		"verify":                              *cfg.SamlSettings.Verify,
   420  		"encrypt":                             *cfg.SamlSettings.Encrypt,
   421  		"isdefault_first_name_attribute":      isDefault(*cfg.SamlSettings.FirstNameAttribute, model.SAML_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE),
   422  		"isdefault_last_name_attribute":       isDefault(*cfg.SamlSettings.LastNameAttribute, model.SAML_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE),
   423  		"isdefault_email_attribute":           isDefault(*cfg.SamlSettings.EmailAttribute, model.SAML_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE),
   424  		"isdefault_username_attribute":        isDefault(*cfg.SamlSettings.UsernameAttribute, model.SAML_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE),
   425  		"isdefault_nickname_attribute":        isDefault(*cfg.SamlSettings.NicknameAttribute, model.SAML_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE),
   426  		"isdefault_locale_attribute":          isDefault(*cfg.SamlSettings.LocaleAttribute, model.SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE),
   427  		"isdefault_position_attribute":        isDefault(*cfg.SamlSettings.PositionAttribute, model.SAML_SETTINGS_DEFAULT_POSITION_ATTRIBUTE),
   428  		"isdefault_login_button_text":         isDefault(*cfg.SamlSettings.LoginButtonText, model.USER_AUTH_SERVICE_SAML_TEXT),
   429  		"isdefault_login_button_color":        isDefault(*cfg.SamlSettings.LoginButtonColor, ""),
   430  		"isdefault_login_button_border_color": isDefault(*cfg.SamlSettings.LoginButtonBorderColor, ""),
   431  		"isdefault_login_button_text_color":   isDefault(*cfg.SamlSettings.LoginButtonTextColor, ""),
   432  	})
   433  
   434  	a.SendDiagnostic(TRACK_CONFIG_CLUSTER, map[string]interface{}{
   435  		"enable":                  *cfg.ClusterSettings.Enable,
   436  		"use_ip_address":          *cfg.ClusterSettings.UseIpAddress,
   437  		"use_experimental_gossip": *cfg.ClusterSettings.UseExperimentalGossip,
   438  		"read_only_config":        *cfg.ClusterSettings.ReadOnlyConfig,
   439  	})
   440  
   441  	a.SendDiagnostic(TRACK_CONFIG_METRICS, map[string]interface{}{
   442  		"enable":             *cfg.MetricsSettings.Enable,
   443  		"block_profile_rate": *cfg.MetricsSettings.BlockProfileRate,
   444  	})
   445  
   446  	a.SendDiagnostic(TRACK_CONFIG_NATIVEAPP, map[string]interface{}{
   447  		"isdefault_app_download_link":         isDefault(*cfg.NativeAppSettings.AppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK),
   448  		"isdefault_android_app_download_link": isDefault(*cfg.NativeAppSettings.AndroidAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK),
   449  		"isdefault_iosapp_download_link":      isDefault(*cfg.NativeAppSettings.IosAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK),
   450  	})
   451  
   452  	a.SendDiagnostic(TRACK_CONFIG_WEBRTC, map[string]interface{}{
   453  		"enable":             *cfg.WebrtcSettings.Enable,
   454  		"isdefault_stun_uri": isDefault(*cfg.WebrtcSettings.StunURI, model.WEBRTC_SETTINGS_DEFAULT_STUN_URI),
   455  		"isdefault_turn_uri": isDefault(*cfg.WebrtcSettings.TurnURI, model.WEBRTC_SETTINGS_DEFAULT_TURN_URI),
   456  	})
   457  
   458  	a.SendDiagnostic(TRACK_CONFIG_ANALYTICS, map[string]interface{}{
   459  		"isdefault_max_users_for_statistics": isDefault(*cfg.AnalyticsSettings.MaxUsersForStatistics, model.ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS),
   460  	})
   461  
   462  	a.SendDiagnostic(TRACK_CONFIG_ANNOUNCEMENT, map[string]interface{}{
   463  		"enable_banner":               *cfg.AnnouncementSettings.EnableBanner,
   464  		"isdefault_banner_color":      isDefault(*cfg.AnnouncementSettings.BannerColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR),
   465  		"isdefault_banner_text_color": isDefault(*cfg.AnnouncementSettings.BannerTextColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR),
   466  		"allow_banner_dismissal":      *cfg.AnnouncementSettings.AllowBannerDismissal,
   467  	})
   468  
   469  	a.SendDiagnostic(TRACK_CONFIG_ELASTICSEARCH, map[string]interface{}{
   470  		"isdefault_connection_url":          isDefault(*cfg.ElasticsearchSettings.ConnectionUrl, model.ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL),
   471  		"isdefault_username":                isDefault(*cfg.ElasticsearchSettings.Username, model.ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME),
   472  		"isdefault_password":                isDefault(*cfg.ElasticsearchSettings.Password, model.ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD),
   473  		"enable_indexing":                   *cfg.ElasticsearchSettings.EnableIndexing,
   474  		"enable_searching":                  *cfg.ElasticsearchSettings.EnableSearching,
   475  		"sniff":                             *cfg.ElasticsearchSettings.Sniff,
   476  		"post_index_replicas":               *cfg.ElasticsearchSettings.PostIndexReplicas,
   477  		"post_index_shards":                 *cfg.ElasticsearchSettings.PostIndexShards,
   478  		"isdefault_index_prefix":            isDefault(*cfg.ElasticsearchSettings.IndexPrefix, model.ELASTICSEARCH_SETTINGS_DEFAULT_INDEX_PREFIX),
   479  		"live_indexing_batch_size":          *cfg.ElasticsearchSettings.LiveIndexingBatchSize,
   480  		"bulk_indexing_time_window_seconds": *cfg.ElasticsearchSettings.BulkIndexingTimeWindowSeconds,
   481  		"request_timeout_seconds":           *cfg.ElasticsearchSettings.RequestTimeoutSeconds,
   482  	})
   483  
   484  	a.SendDiagnostic(TRACK_CONFIG_PLUGIN, map[string]interface{}{
   485  		"enable_jira":    pluginSetting(&cfg.PluginSettings, "jira", "enabled", false),
   486  		"enable_zoom":    pluginActivated(cfg.PluginSettings.PluginStates, "zoom"),
   487  		"enable":         *cfg.PluginSettings.Enable,
   488  		"enable_uploads": *cfg.PluginSettings.EnableUploads,
   489  	})
   490  
   491  	a.SendDiagnostic(TRACK_CONFIG_DATA_RETENTION, map[string]interface{}{
   492  		"enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion,
   493  		"enable_file_deletion":    *cfg.DataRetentionSettings.EnableFileDeletion,
   494  		"message_retention_days":  *cfg.DataRetentionSettings.MessageRetentionDays,
   495  		"file_retention_days":     *cfg.DataRetentionSettings.FileRetentionDays,
   496  		"deletion_job_start_time": *cfg.DataRetentionSettings.DeletionJobStartTime,
   497  	})
   498  
   499  	a.SendDiagnostic(TRACK_CONFIG_MESSAGE_EXPORT, map[string]interface{}{
   500  		"enable_message_export":         *cfg.MessageExportSettings.EnableExport,
   501  		"daily_run_time":                *cfg.MessageExportSettings.DailyRunTime,
   502  		"default_export_from_timestamp": *cfg.MessageExportSettings.ExportFromTimestamp,
   503  		"batch_size":                    *cfg.MessageExportSettings.BatchSize,
   504  	})
   505  }
   506  
   507  func (a *App) trackLicense() {
   508  	if utils.IsLicensed() {
   509  		data := map[string]interface{}{
   510  			"customer_id": utils.License().Customer.Id,
   511  			"license_id":  utils.License().Id,
   512  			"issued":      utils.License().IssuedAt,
   513  			"start":       utils.License().StartsAt,
   514  			"expire":      utils.License().ExpiresAt,
   515  			"users":       *utils.License().Features.Users,
   516  		}
   517  
   518  		features := utils.License().Features.ToMap()
   519  		for featureName, featureValue := range features {
   520  			data["feature_"+featureName] = featureValue
   521  		}
   522  
   523  		a.SendDiagnostic(TRACK_LICENSE, data)
   524  	}
   525  }
   526  
   527  func (a *App) trackPlugins() {
   528  	if *a.Config().PluginSettings.Enable {
   529  		totalActiveCount := -1 // -1 to indicate disabled or error
   530  		webappActiveCount := 0
   531  		backendActiveCount := 0
   532  		totalInactiveCount := -1 // -1 to indicate disabled or error
   533  		webappInactiveCount := 0
   534  		backendInactiveCount := 0
   535  		settingsCount := 0
   536  
   537  		plugins, _ := a.GetPlugins()
   538  
   539  		if plugins != nil {
   540  			totalActiveCount = len(plugins.Active)
   541  
   542  			for _, plugin := range plugins.Active {
   543  				if plugin.Webapp != nil {
   544  					webappActiveCount += 1
   545  				}
   546  
   547  				if plugin.Backend != nil {
   548  					backendActiveCount += 1
   549  				}
   550  
   551  				if plugin.SettingsSchema != nil {
   552  					settingsCount += 1
   553  				}
   554  			}
   555  
   556  			totalInactiveCount = len(plugins.Inactive)
   557  
   558  			for _, plugin := range plugins.Inactive {
   559  				if plugin.Webapp != nil {
   560  					webappInactiveCount += 1
   561  				}
   562  
   563  				if plugin.Backend != nil {
   564  					backendInactiveCount += 1
   565  				}
   566  
   567  				if plugin.SettingsSchema != nil {
   568  					settingsCount += 1
   569  				}
   570  			}
   571  		}
   572  
   573  		a.SendDiagnostic(TRACK_PLUGINS, map[string]interface{}{
   574  			"active_plugins":           totalActiveCount,
   575  			"active_webapp_plugins":    webappActiveCount,
   576  			"active_backend_plugins":   backendActiveCount,
   577  			"inactive_plugins":         totalInactiveCount,
   578  			"inactive_webapp_plugins":  webappInactiveCount,
   579  			"inactive_backend_plugins": backendInactiveCount,
   580  			"plugins_with_settings":    settingsCount,
   581  		})
   582  	}
   583  }
   584  
   585  func (a *App) trackServer() {
   586  	data := map[string]interface{}{
   587  		"edition":          model.BuildEnterpriseReady,
   588  		"version":          model.CurrentVersion,
   589  		"database_type":    *a.Config().SqlSettings.DriverName,
   590  		"operating_system": runtime.GOOS,
   591  	}
   592  
   593  	if scr := <-a.Srv.Store.User().AnalyticsGetSystemAdminCount(); scr.Err == nil {
   594  		data["system_admins"] = scr.Data.(int64)
   595  	}
   596  
   597  	a.SendDiagnostic(TRACK_SERVER, data)
   598  }