github.com/vnforks/kid/v5@v5.22.1-0.20200408055009-b89d99c65676/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  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  
    11  	"github.com/segmentio/analytics-go"
    12  
    13  	"github.com/vnforks/kid/v5/mlog"
    14  	"github.com/vnforks/kid/v5/model"
    15  	"github.com/vnforks/kid/v5/store"
    16  )
    17  
    18  const (
    19  	SEGMENT_KEY = "placeholder_segment_key"
    20  
    21  	TRACK_CONFIG_SERVICE             = "config_service"
    22  	TRACK_CONFIG_BRANCH              = "config_branch"
    23  	TRACK_CONFIG_CLIENT_REQ          = "config_client_requirements"
    24  	TRACK_CONFIG_SQL                 = "config_sql"
    25  	TRACK_CONFIG_LOG                 = "config_log"
    26  	TRACK_CONFIG_NOTIFICATION_LOG    = "config_notifications_log"
    27  	TRACK_CONFIG_FILE                = "config_file"
    28  	TRACK_CONFIG_RATE                = "config_rate"
    29  	TRACK_CONFIG_EMAIL               = "config_email"
    30  	TRACK_CONFIG_PRIVACY             = "config_privacy"
    31  	TRACK_CONFIG_THEME               = "config_theme"
    32  	TRACK_CONFIG_OAUTH               = "config_oauth"
    33  	TRACK_CONFIG_LDAP                = "config_ldap"
    34  	TRACK_CONFIG_COMPLIANCE          = "config_compliance"
    35  	TRACK_CONFIG_LOCALIZATION        = "config_localization"
    36  	TRACK_CONFIG_SAML                = "config_saml"
    37  	TRACK_CONFIG_PASSWORD            = "config_password"
    38  	TRACK_CONFIG_CLUSTER             = "config_cluster"
    39  	TRACK_CONFIG_METRICS             = "config_metrics"
    40  	TRACK_CONFIG_SUPPORT             = "config_support"
    41  	TRACK_CONFIG_NATIVEAPP           = "config_nativeapp"
    42  	TRACK_CONFIG_EXPERIMENTAL        = "config_experimental"
    43  	TRACK_CONFIG_ANALYTICS           = "config_analytics"
    44  	TRACK_CONFIG_ANNOUNCEMENT        = "config_announcement"
    45  	TRACK_CONFIG_ELASTICSEARCH       = "config_elasticsearch"
    46  	TRACK_CONFIG_DATA_RETENTION      = "config_data_retention"
    47  	TRACK_CONFIG_MESSAGE_EXPORT      = "config_message_export"
    48  	TRACK_CONFIG_DISPLAY             = "config_display"
    49  	TRACK_CONFIG_GUEST_ACCOUNTS      = "config_guest_accounts"
    50  	TRACK_CONFIG_IMAGE_PROXY         = "config_image_proxy"
    51  	TRACK_PERMISSIONS_GENERAL        = "permissions_general"
    52  	TRACK_PERMISSIONS_SYSTEM_SCHEME  = "permissions_system_scheme"
    53  	TRACK_PERMISSIONS_BRANCH_SCHEMES = "permissions_branch_schemes"
    54  	TRACK_ELASTICSEARCH              = "elasticsearch"
    55  	TRACK_GROUPS                     = "groups"
    56  	TRACK_CLASS_MODERATION           = "class_moderation"
    57  
    58  	TRACK_ACTIVITY = "activity"
    59  	TRACK_LICENSE  = "license"
    60  	TRACK_SERVER   = "server"
    61  )
    62  
    63  func (a *App) SendDailyDiagnostics() {
    64  	a.sendDailyDiagnostics(false)
    65  }
    66  
    67  func (a *App) sendDailyDiagnostics(override bool) {
    68  	if *a.Config().LogSettings.EnableDiagnostics && a.IsLeader() && (!strings.Contains(SEGMENT_KEY, "placeholder") || override) {
    69  		a.Srv().initDiagnostics("")
    70  		a.trackActivity()
    71  		a.trackConfig()
    72  		a.trackLicense()
    73  		a.trackServer()
    74  		a.trackPermissions()
    75  		a.trackElasticsearch()
    76  		a.trackClassModeration()
    77  	}
    78  }
    79  
    80  func (a *App) SendDiagnostic(event string, properties map[string]interface{}) {
    81  	a.Srv().diagnosticClient.Enqueue(analytics.Track{
    82  		Event:      event,
    83  		UserId:     a.DiagnosticId(),
    84  		Properties: properties,
    85  	})
    86  }
    87  
    88  func isDefault(setting interface{}, defaultValue interface{}) bool {
    89  	return setting == defaultValue
    90  }
    91  
    92  func (a *App) trackActivity() {
    93  	var userCount int64
    94  	var botAccountsCount int64
    95  	var inactiveUserCount int64
    96  	var publicClassCount int64
    97  	var privateClassCount int64
    98  	var directClassCount int64
    99  	var deletedPublicClassCount int64
   100  	var deletedPrivateClassCount int64
   101  	var postsCount int64
   102  	var postsCountPreviousDay int64
   103  	var botPostsCountPreviousDay int64
   104  	var slashCommandsCount int64
   105  	var incomingWebhooksCount int64
   106  	var outgoingWebhooksCount int64
   107  
   108  	activeUsersDailyCountChan := make(chan store.StoreResult, 1)
   109  	go func() {
   110  		count, err := a.Srv().Store.User().AnalyticsActiveCount(DAY_MILLISECONDS, model.UserCountOptions{IncludeDeleted: false})
   111  		activeUsersDailyCountChan <- store.StoreResult{Data: count, Err: err}
   112  		close(activeUsersDailyCountChan)
   113  	}()
   114  
   115  	activeUsersMonthlyCountChan := make(chan store.StoreResult, 1)
   116  	go func() {
   117  		count, err := a.Srv().Store.User().AnalyticsActiveCount(MONTH_MILLISECONDS, model.UserCountOptions{IncludeDeleted: false})
   118  		activeUsersMonthlyCountChan <- store.StoreResult{Data: count, Err: err}
   119  		close(activeUsersMonthlyCountChan)
   120  	}()
   121  
   122  	if count, err := a.Srv().Store.User().Count(model.UserCountOptions{IncludeDeleted: true}); err == nil {
   123  		userCount = count
   124  	}
   125  
   126  	if count, err := a.Srv().Store.User().Count(model.UserCountOptions{ExcludeRegularUsers: true}); err == nil {
   127  		botAccountsCount = count
   128  	}
   129  
   130  	if iucr, err := a.Srv().Store.User().AnalyticsGetInactiveUsersCount(); err == nil {
   131  		inactiveUserCount = iucr
   132  	}
   133  
   134  	branchCount, err := a.Srv().Store.Branch().AnalyticsBranchCount(false)
   135  	if err != nil {
   136  		mlog.Error(err.Error())
   137  	}
   138  
   139  	postsCount, _ = a.Srv().Store.Post().AnalyticsPostCount("", false, false)
   140  
   141  	postCountsOptions := &model.AnalyticsPostCountsOptions{BranchId: "", YesterdayOnly: true}
   142  	postCountsYesterday, _ := a.Srv().Store.Post().AnalyticsPostCountsByDay(postCountsOptions)
   143  	postsCountPreviousDay = 0
   144  	if len(postCountsYesterday) > 0 {
   145  		postsCountPreviousDay = int64(postCountsYesterday[0].Value)
   146  	}
   147  
   148  	postCountsOptions = &model.AnalyticsPostCountsOptions{BranchId: "", YesterdayOnly: true}
   149  	botPostCountsYesterday, _ := a.Srv().Store.Post().AnalyticsPostCountsByDay(postCountsOptions)
   150  	botPostsCountPreviousDay = 0
   151  	if len(botPostCountsYesterday) > 0 {
   152  		botPostsCountPreviousDay = int64(botPostCountsYesterday[0].Value)
   153  	}
   154  
   155  	slashCommandsCount, _ = a.Srv().Store.Command().AnalyticsCommandCount("")
   156  
   157  	if c, err := a.Srv().Store.Webhook().AnalyticsIncomingCount(""); err == nil {
   158  		incomingWebhooksCount = c
   159  	}
   160  
   161  	outgoingWebhooksCount, _ = a.Srv().Store.Webhook().AnalyticsOutgoingCount("")
   162  
   163  	var activeUsersDailyCount int64
   164  	if r := <-activeUsersDailyCountChan; r.Err == nil {
   165  		activeUsersDailyCount = r.Data.(int64)
   166  	}
   167  
   168  	var activeUsersMonthlyCount int64
   169  	if r := <-activeUsersMonthlyCountChan; r.Err == nil {
   170  		activeUsersMonthlyCount = r.Data.(int64)
   171  	}
   172  
   173  	a.SendDiagnostic(TRACK_ACTIVITY, map[string]interface{}{
   174  		"registered_users":             userCount,
   175  		"bot_accounts":                 botAccountsCount,
   176  		"active_users_daily":           activeUsersDailyCount,
   177  		"active_users_monthly":         activeUsersMonthlyCount,
   178  		"registered_deactivated_users": inactiveUserCount,
   179  		"branches":                     branchCount,
   180  		"public_classes":               publicClassCount,
   181  		"private_classes":              privateClassCount,
   182  		"direct_message_classes":       directClassCount,
   183  		"public_classes_deleted":       deletedPublicClassCount,
   184  		"private_classes_deleted":      deletedPrivateClassCount,
   185  		"posts_previous_day":           postsCountPreviousDay,
   186  		"bot_posts_previous_day":       botPostsCountPreviousDay,
   187  		"posts":                        postsCount,
   188  		"slash_commands":               slashCommandsCount,
   189  		"incoming_webhooks":            incomingWebhooksCount,
   190  		"outgoing_webhooks":            outgoingWebhooksCount,
   191  	})
   192  }
   193  
   194  func (a *App) trackConfig() {
   195  	cfg := a.Config()
   196  	a.SendDiagnostic(TRACK_CONFIG_SERVICE, map[string]interface{}{
   197  		"web_server_mode":                                       *cfg.ServiceSettings.WebserverMode,
   198  		"enable_security_fix_alert":                             *cfg.ServiceSettings.EnableSecurityFixAlert,
   199  		"enable_insecure_outgoing_connections":                  *cfg.ServiceSettings.EnableInsecureOutgoingConnections,
   200  		"enable_incoming_webhooks":                              cfg.ServiceSettings.EnableIncomingWebhooks,
   201  		"enable_outgoing_webhooks":                              cfg.ServiceSettings.EnableOutgoingWebhooks,
   202  		"enable_commands":                                       *cfg.ServiceSettings.EnableCommands,
   203  		"enable_only_admin_integrations":                        *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations,
   204  		"enable_user_access_tokens":                             *cfg.ServiceSettings.EnableUserAccessTokens,
   205  		"enable_custom_emoji":                                   *cfg.ServiceSettings.EnableCustomEmoji,
   206  		"enable_emoji_picker":                                   *cfg.ServiceSettings.EnableEmojiPicker,
   207  		"enable_gif_picker":                                     *cfg.ServiceSettings.EnableGifPicker,
   208  		"gfycat_api_key":                                        isDefault(*cfg.ServiceSettings.GfycatApiKey, model.SERVICE_SETTINGS_DEFAULT_GFYCAT_API_KEY),
   209  		"gfycat_api_secret":                                     isDefault(*cfg.ServiceSettings.GfycatApiSecret, model.SERVICE_SETTINGS_DEFAULT_GFYCAT_API_SECRET),
   210  		"experimental_enable_authentication_transfer":           *cfg.ServiceSettings.ExperimentalEnableAuthenticationTransfer,
   211  		"restrict_custom_emoji_creation":                        *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation,
   212  		"enable_testing":                                        cfg.ServiceSettings.EnableTesting,
   213  		"enable_developer":                                      *cfg.ServiceSettings.EnableDeveloper,
   214  		"enable_multifactor_authentication":                     *cfg.ServiceSettings.EnableMultifactorAuthentication,
   215  		"enforce_multifactor_authentication":                    *cfg.ServiceSettings.EnforceMultifactorAuthentication,
   216  		"enable_oauth_service_provider":                         cfg.ServiceSettings.EnableOAuthServiceProvider,
   217  		"connection_security":                                   *cfg.ServiceSettings.ConnectionSecurity,
   218  		"tls_strict_transport":                                  *cfg.ServiceSettings.TLSStrictTransport,
   219  		"uses_letsencrypt":                                      *cfg.ServiceSettings.UseLetsEncrypt,
   220  		"forward_80_to_443":                                     *cfg.ServiceSettings.Forward80To443,
   221  		"maximum_login_attempts":                                *cfg.ServiceSettings.MaximumLoginAttempts,
   222  		"session_length_web_in_days":                            *cfg.ServiceSettings.SessionLengthWebInDays,
   223  		"session_length_mobile_in_days":                         *cfg.ServiceSettings.SessionLengthMobileInDays,
   224  		"session_length_sso_in_days":                            *cfg.ServiceSettings.SessionLengthSSOInDays,
   225  		"session_cache_in_minutes":                              *cfg.ServiceSettings.SessionCacheInMinutes,
   226  		"session_idle_timeout_in_minutes":                       *cfg.ServiceSettings.SessionIdleTimeoutInMinutes,
   227  		"isdefault_site_url":                                    isDefault(*cfg.ServiceSettings.SiteURL, model.SERVICE_SETTINGS_DEFAULT_SITE_URL),
   228  		"isdefault_tls_cert_file":                               isDefault(*cfg.ServiceSettings.TLSCertFile, model.SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE),
   229  		"isdefault_tls_key_file":                                isDefault(*cfg.ServiceSettings.TLSKeyFile, model.SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE),
   230  		"isdefault_read_timeout":                                isDefault(*cfg.ServiceSettings.ReadTimeout, model.SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT),
   231  		"isdefault_write_timeout":                               isDefault(*cfg.ServiceSettings.WriteTimeout, model.SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT),
   232  		"isdefault_google_developer_key":                        isDefault(cfg.ServiceSettings.GoogleDeveloperKey, ""),
   233  		"isdefault_allow_cors_from":                             isDefault(*cfg.ServiceSettings.AllowCorsFrom, model.SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM),
   234  		"isdefault_cors_exposed_headers":                        isDefault(cfg.ServiceSettings.CorsExposedHeaders, ""),
   235  		"cors_allow_credentials":                                *cfg.ServiceSettings.CorsAllowCredentials,
   236  		"cors_debug":                                            *cfg.ServiceSettings.CorsDebug,
   237  		"isdefault_allowed_untrusted_internal_connections":      isDefault(*cfg.ServiceSettings.AllowedUntrustedInternalConnections, ""),
   238  		"restrict_post_delete":                                  *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_RestrictPostDelete,
   239  		"allow_edit_post":                                       *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_AllowEditPost,
   240  		"post_edit_time_limit":                                  *cfg.ServiceSettings.PostEditTimeLimit,
   241  		"enable_user_typing_messages":                           *cfg.ServiceSettings.EnableUserTypingMessages,
   242  		"enable_class_viewed_messages":                          *cfg.ServiceSettings.EnableClassViewedMessages,
   243  		"time_between_user_typing_updates_milliseconds":         *cfg.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds,
   244  		"cluster_log_timeout_milliseconds":                      *cfg.ServiceSettings.ClusterLogTimeoutMilliseconds,
   245  		"minimum_hashtag_length":                                *cfg.ServiceSettings.MinimumHashtagLength,
   246  		"enable_user_statuses":                                  *cfg.ServiceSettings.EnableUserStatuses,
   247  		"close_unused_direct_messages":                          *cfg.ServiceSettings.CloseUnusedDirectMessages,
   248  		"enable_preview_features":                               *cfg.ServiceSettings.EnablePreviewFeatures,
   249  		"enable_tutorial":                                       *cfg.ServiceSettings.EnableTutorial,
   250  		"experimental_enable_default_class_leave_join_messages": *cfg.ServiceSettings.ExperimentalEnableDefaultClassLeaveJoinMessages,
   251  		"experimental_group_unread_classes":                     *cfg.ServiceSettings.ExperimentalGroupUnreadClasses,
   252  		"websocket_url":                                         isDefault(*cfg.ServiceSettings.WebsocketURL, ""),
   253  		"allow_cookies_for_subdomains":                          *cfg.ServiceSettings.AllowCookiesForSubdomains,
   254  		"enable_api_branch_deletion":                            *cfg.ServiceSettings.EnableAPIBranchDeletion,
   255  		"experimental_enable_hardened_mode":                     *cfg.ServiceSettings.ExperimentalEnableHardenedMode,
   256  		"disable_legacy_mfa":                                    *cfg.ServiceSettings.DisableLegacyMFA,
   257  		"experimental_strict_csrf_enforcement":                  *cfg.ServiceSettings.ExperimentalStrictCSRFEnforcement,
   258  		"enable_email_invitations":                              *cfg.ServiceSettings.EnableEmailInvitations,
   259  		"experimental_class_organization":                       *cfg.ServiceSettings.ExperimentalClassOrganization,
   260  		"experimental_class_sidebar_organization":               *cfg.ServiceSettings.ExperimentalClassSidebarOrganization,
   261  		"enable_bot_account_creation":                           *cfg.ServiceSettings.EnableBotAccountCreation,
   262  		"enable_svgs":                                           *cfg.ServiceSettings.EnableSVGs,
   263  		"enable_latex":                                          *cfg.ServiceSettings.EnableLatex,
   264  	})
   265  
   266  	a.SendDiagnostic(TRACK_CONFIG_BRANCH, map[string]interface{}{
   267  		"enable_user_creation":                      cfg.BranchSettings.EnableUserCreation,
   268  		"enable_branch_creation":                    *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_EnableBranchCreation,
   269  		"restrict_branch_invite":                    *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictBranchInvite,
   270  		"restrict_public_class_creation":            *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPublicClassCreation,
   271  		"restrict_private_class_creation":           *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateClassCreation,
   272  		"restrict_public_class_management":          *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPublicClassManagement,
   273  		"restrict_private_class_management":         *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateClassManagement,
   274  		"restrict_public_class_deletion":            *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPublicClassDeletion,
   275  		"restrict_private_class_deletion":           *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateClassDeletion,
   276  		"enable_open_server":                        *cfg.BranchSettings.EnableOpenServer,
   277  		"enable_user_deactivation":                  *cfg.BranchSettings.EnableUserDeactivation,
   278  		"enable_custom_brand":                       *cfg.BranchSettings.EnableCustomBrand,
   279  		"restrict_direct_message":                   *cfg.BranchSettings.RestrictDirectMessage,
   280  		"max_notifications_per_class":               *cfg.BranchSettings.MaxNotificationsPerClass,
   281  		"enable_confirm_notifications_to_class":     *cfg.BranchSettings.EnableConfirmNotificationsToClass,
   282  		"max_users_per_branch":                      *cfg.BranchSettings.MaxUsersPerBranch,
   283  		"max_classes_per_branch":                    *cfg.BranchSettings.MaxClassesPerBranch,
   284  		"branchmate_name_display":                   *cfg.BranchSettings.BranchmateNameDisplay,
   285  		"experimental_view_archived_classes":        *cfg.BranchSettings.ExperimentalViewArchivedClasses,
   286  		"lock_branchmate_name_display":              *cfg.BranchSettings.LockBranchmateNameDisplay,
   287  		"isdefault_site_name":                       isDefault(cfg.BranchSettings.SiteName, "Mattermost"),
   288  		"isdefault_custom_brand_text":               isDefault(*cfg.BranchSettings.CustomBrandText, model.BRANCH_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT),
   289  		"isdefault_custom_description_text":         isDefault(*cfg.BranchSettings.CustomDescriptionText, model.BRANCH_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT),
   290  		"isdefault_user_status_away_timeout":        isDefault(*cfg.BranchSettings.UserStatusAwayTimeout, model.BRANCH_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT),
   291  		"restrict_private_class_manage_members":     *cfg.BranchSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateClassManageMembers,
   292  		"enable_X_to_leave_classes_from_LHS":        *cfg.BranchSettings.EnableXToLeaveClassesFromLHS,
   293  		"experimental_enable_automatic_replies":     *cfg.BranchSettings.ExperimentalEnableAutomaticReplies,
   294  		"experimental_town_square_is_hidden_in_lhs": *cfg.BranchSettings.ExperimentalHideTownSquareinLHS,
   295  		"experimental_town_square_is_read_only":     *cfg.BranchSettings.ExperimentalTownSquareIsReadOnly,
   296  		"experimental_primary_branch":               isDefault(*cfg.BranchSettings.ExperimentalPrimaryBranch, ""),
   297  		"experimental_default_classes":              len(cfg.BranchSettings.ExperimentalDefaultClasses),
   298  	})
   299  
   300  	a.SendDiagnostic(TRACK_CONFIG_CLIENT_REQ, map[string]interface{}{
   301  		"android_latest_version": cfg.ClientRequirements.AndroidLatestVersion,
   302  		"android_min_version":    cfg.ClientRequirements.AndroidMinVersion,
   303  		"desktop_latest_version": cfg.ClientRequirements.DesktopLatestVersion,
   304  		"desktop_min_version":    cfg.ClientRequirements.DesktopMinVersion,
   305  		"ios_latest_version":     cfg.ClientRequirements.IosLatestVersion,
   306  		"ios_min_version":        cfg.ClientRequirements.IosMinVersion,
   307  	})
   308  
   309  	a.SendDiagnostic(TRACK_CONFIG_SQL, map[string]interface{}{
   310  		"driver_name":                    *cfg.SqlSettings.DriverName,
   311  		"trace":                          cfg.SqlSettings.Trace,
   312  		"max_idle_conns":                 *cfg.SqlSettings.MaxIdleConns,
   313  		"conn_max_lifetime_milliseconds": *cfg.SqlSettings.ConnMaxLifetimeMilliseconds,
   314  		"max_open_conns":                 *cfg.SqlSettings.MaxOpenConns,
   315  		"data_source_replicas":           len(cfg.SqlSettings.DataSourceReplicas),
   316  		"data_source_search_replicas":    len(cfg.SqlSettings.DataSourceSearchReplicas),
   317  		"query_timeout":                  *cfg.SqlSettings.QueryTimeout,
   318  	})
   319  
   320  	a.SendDiagnostic(TRACK_CONFIG_LOG, map[string]interface{}{
   321  		"enable_console":           cfg.LogSettings.EnableConsole,
   322  		"console_level":            cfg.LogSettings.ConsoleLevel,
   323  		"console_json":             *cfg.LogSettings.ConsoleJson,
   324  		"enable_file":              cfg.LogSettings.EnableFile,
   325  		"file_level":               cfg.LogSettings.FileLevel,
   326  		"file_json":                cfg.LogSettings.FileJson,
   327  		"enable_webhook_debugging": cfg.LogSettings.EnableWebhookDebugging,
   328  		"isdefault_file_location":  isDefault(cfg.LogSettings.FileLocation, ""),
   329  	})
   330  
   331  	a.SendDiagnostic(TRACK_CONFIG_NOTIFICATION_LOG, map[string]interface{}{
   332  		"enable_console":          *cfg.NotificationLogSettings.EnableConsole,
   333  		"console_level":           *cfg.NotificationLogSettings.ConsoleLevel,
   334  		"console_json":            *cfg.NotificationLogSettings.ConsoleJson,
   335  		"enable_file":             *cfg.NotificationLogSettings.EnableFile,
   336  		"file_level":              *cfg.NotificationLogSettings.FileLevel,
   337  		"file_json":               *cfg.NotificationLogSettings.FileJson,
   338  		"isdefault_file_location": isDefault(*cfg.NotificationLogSettings.FileLocation, ""),
   339  	})
   340  
   341  	a.SendDiagnostic(TRACK_CONFIG_PASSWORD, map[string]interface{}{
   342  		"minimum_length": *cfg.PasswordSettings.MinimumLength,
   343  		"lowercase":      *cfg.PasswordSettings.Lowercase,
   344  		"number":         *cfg.PasswordSettings.Number,
   345  		"uppercase":      *cfg.PasswordSettings.Uppercase,
   346  		"symbol":         *cfg.PasswordSettings.Symbol,
   347  	})
   348  
   349  	a.SendDiagnostic(TRACK_CONFIG_FILE, map[string]interface{}{
   350  		"enable_public_links":     cfg.FileSettings.EnablePublicLink,
   351  		"driver_name":             *cfg.FileSettings.DriverName,
   352  		"isdefault_directory":     isDefault(*cfg.FileSettings.Directory, model.FILE_SETTINGS_DEFAULT_DIRECTORY),
   353  		"isabsolute_directory":    filepath.IsAbs(*cfg.FileSettings.Directory),
   354  		"amazon_s3_ssl":           *cfg.FileSettings.AmazonS3SSL,
   355  		"amazon_s3_sse":           *cfg.FileSettings.AmazonS3SSE,
   356  		"amazon_s3_signv2":        *cfg.FileSettings.AmazonS3SignV2,
   357  		"amazon_s3_trace":         *cfg.FileSettings.AmazonS3Trace,
   358  		"max_file_size":           *cfg.FileSettings.MaxFileSize,
   359  		"enable_file_attachments": *cfg.FileSettings.EnableFileAttachments,
   360  		"enable_mobile_upload":    *cfg.FileSettings.EnableMobileUpload,
   361  		"enable_mobile_download":  *cfg.FileSettings.EnableMobileDownload,
   362  	})
   363  
   364  	a.SendDiagnostic(TRACK_CONFIG_EMAIL, map[string]interface{}{
   365  		"enable_sign_up_with_email":            cfg.EmailSettings.EnableSignUpWithEmail,
   366  		"enable_sign_in_with_email":            *cfg.EmailSettings.EnableSignInWithEmail,
   367  		"enable_sign_in_with_username":         *cfg.EmailSettings.EnableSignInWithUsername,
   368  		"require_email_verification":           cfg.EmailSettings.RequireEmailVerification,
   369  		"send_email_notifications":             cfg.EmailSettings.SendEmailNotifications,
   370  		"use_class_in_email_notifications":     *cfg.EmailSettings.UseClassInEmailNotifications,
   371  		"email_notification_contents_type":     *cfg.EmailSettings.EmailNotificationContentsType,
   372  		"enable_smtp_auth":                     *cfg.EmailSettings.EnableSMTPAuth,
   373  		"connection_security":                  cfg.EmailSettings.ConnectionSecurity,
   374  		"send_push_notifications":              *cfg.EmailSettings.SendPushNotifications,
   375  		"push_notification_contents":           *cfg.EmailSettings.PushNotificationContents,
   376  		"enable_email_batching":                *cfg.EmailSettings.EnableEmailBatching,
   377  		"email_batching_buffer_size":           *cfg.EmailSettings.EmailBatchingBufferSize,
   378  		"email_batching_interval":              *cfg.EmailSettings.EmailBatchingInterval,
   379  		"enable_preview_mode_banner":           *cfg.EmailSettings.EnablePreviewModeBanner,
   380  		"isdefault_feedback_name":              isDefault(cfg.EmailSettings.FeedbackName, ""),
   381  		"isdefault_feedback_email":             isDefault(cfg.EmailSettings.FeedbackEmail, ""),
   382  		"isdefault_reply_to_address":           isDefault(cfg.EmailSettings.ReplyToAddress, ""),
   383  		"isdefault_feedback_organization":      isDefault(*cfg.EmailSettings.FeedbackOrganization, model.EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION),
   384  		"skip_server_certificate_verification": *cfg.EmailSettings.SkipServerCertificateVerification,
   385  		"isdefault_login_button_color":         isDefault(*cfg.EmailSettings.LoginButtonColor, ""),
   386  		"isdefault_login_button_border_color":  isDefault(*cfg.EmailSettings.LoginButtonBorderColor, ""),
   387  		"isdefault_login_button_text_color":    isDefault(*cfg.EmailSettings.LoginButtonTextColor, ""),
   388  	})
   389  
   390  	a.SendDiagnostic(TRACK_CONFIG_RATE, map[string]interface{}{
   391  		"enable_rate_limiter":      *cfg.RateLimitSettings.Enable,
   392  		"vary_by_remote_address":   *cfg.RateLimitSettings.VaryByRemoteAddr,
   393  		"vary_by_user":             *cfg.RateLimitSettings.VaryByUser,
   394  		"per_sec":                  *cfg.RateLimitSettings.PerSec,
   395  		"max_burst":                *cfg.RateLimitSettings.MaxBurst,
   396  		"memory_store_size":        *cfg.RateLimitSettings.MemoryStoreSize,
   397  		"isdefault_vary_by_header": isDefault(cfg.RateLimitSettings.VaryByHeader, ""),
   398  	})
   399  
   400  	a.SendDiagnostic(TRACK_CONFIG_PRIVACY, map[string]interface{}{
   401  		"show_email_address": cfg.PrivacySettings.ShowEmailAddress,
   402  		"show_full_name":     cfg.PrivacySettings.ShowFullName,
   403  	})
   404  
   405  	a.SendDiagnostic(TRACK_CONFIG_THEME, map[string]interface{}{
   406  		"enable_theme_selection":  *cfg.ThemeSettings.EnableThemeSelection,
   407  		"isdefault_default_theme": isDefault(*cfg.ThemeSettings.DefaultTheme, model.BRANCH_SETTINGS_DEFAULT_BRANCH_TEXT),
   408  		"allow_custom_themes":     *cfg.ThemeSettings.AllowCustomThemes,
   409  		"allowed_themes":          len(cfg.ThemeSettings.AllowedThemes),
   410  	})
   411  
   412  	a.SendDiagnostic(TRACK_CONFIG_OAUTH, map[string]interface{}{
   413  		"enable_gitlab":    cfg.GitLabSettings.Enable,
   414  		"enable_google":    cfg.GoogleSettings.Enable,
   415  		"enable_office365": cfg.Office365Settings.Enable,
   416  	})
   417  
   418  	a.SendDiagnostic(TRACK_CONFIG_SUPPORT, map[string]interface{}{
   419  		"isdefault_terms_of_service_link":              isDefault(*cfg.SupportSettings.TermsOfServiceLink, model.SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK),
   420  		"isdefault_privacy_policy_link":                isDefault(*cfg.SupportSettings.PrivacyPolicyLink, model.SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK),
   421  		"isdefault_about_link":                         isDefault(*cfg.SupportSettings.AboutLink, model.SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK),
   422  		"isdefault_help_link":                          isDefault(*cfg.SupportSettings.HelpLink, model.SUPPORT_SETTINGS_DEFAULT_HELP_LINK),
   423  		"isdefault_report_a_problem_link":              isDefault(*cfg.SupportSettings.ReportAProblemLink, model.SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK),
   424  		"isdefault_support_email":                      isDefault(*cfg.SupportSettings.SupportEmail, model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL),
   425  		"custom_terms_of_service_enabled":              *cfg.SupportSettings.CustomTermsOfServiceEnabled,
   426  		"custom_terms_of_service_re_acceptance_period": *cfg.SupportSettings.CustomTermsOfServiceReAcceptancePeriod,
   427  	})
   428  
   429  	a.SendDiagnostic(TRACK_CONFIG_LDAP, map[string]interface{}{
   430  		"enable":                                 *cfg.LdapSettings.Enable,
   431  		"enable_sync":                            *cfg.LdapSettings.EnableSync,
   432  		"enable_admin_filter":                    *cfg.LdapSettings.EnableAdminFilter,
   433  		"connection_security":                    *cfg.LdapSettings.ConnectionSecurity,
   434  		"skip_certificate_verification":          *cfg.LdapSettings.SkipCertificateVerification,
   435  		"sync_interval_minutes":                  *cfg.LdapSettings.SyncIntervalMinutes,
   436  		"query_timeout":                          *cfg.LdapSettings.QueryTimeout,
   437  		"max_page_size":                          *cfg.LdapSettings.MaxPageSize,
   438  		"isdefault_first_name_attribute":         isDefault(*cfg.LdapSettings.FirstNameAttribute, model.LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE),
   439  		"isdefault_last_name_attribute":          isDefault(*cfg.LdapSettings.LastNameAttribute, model.LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE),
   440  		"isdefault_email_attribute":              isDefault(*cfg.LdapSettings.EmailAttribute, model.LDAP_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE),
   441  		"isdefault_username_attribute":           isDefault(*cfg.LdapSettings.UsernameAttribute, model.LDAP_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE),
   442  		"isdefault_nickname_attribute":           isDefault(*cfg.LdapSettings.NicknameAttribute, model.LDAP_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE),
   443  		"isdefault_id_attribute":                 isDefault(*cfg.LdapSettings.IdAttribute, model.LDAP_SETTINGS_DEFAULT_ID_ATTRIBUTE),
   444  		"isdefault_position_attribute":           isDefault(*cfg.LdapSettings.PositionAttribute, model.LDAP_SETTINGS_DEFAULT_POSITION_ATTRIBUTE),
   445  		"isdefault_login_id_attribute":           isDefault(*cfg.LdapSettings.LoginIdAttribute, ""),
   446  		"isdefault_login_field_name":             isDefault(*cfg.LdapSettings.LoginFieldName, model.LDAP_SETTINGS_DEFAULT_LOGIN_FIELD_NAME),
   447  		"isdefault_login_button_color":           isDefault(*cfg.LdapSettings.LoginButtonColor, ""),
   448  		"isdefault_login_button_border_color":    isDefault(*cfg.LdapSettings.LoginButtonBorderColor, ""),
   449  		"isdefault_login_button_text_color":      isDefault(*cfg.LdapSettings.LoginButtonTextColor, ""),
   450  		"isempty_group_filter":                   isDefault(*cfg.LdapSettings.GroupFilter, ""),
   451  		"isdefault_group_display_name_attribute": isDefault(*cfg.LdapSettings.GroupDisplayNameAttribute, model.LDAP_SETTINGS_DEFAULT_GROUP_DISPLAY_NAME_ATTRIBUTE),
   452  		"isdefault_group_id_attribute":           isDefault(*cfg.LdapSettings.GroupIdAttribute, model.LDAP_SETTINGS_DEFAULT_GROUP_ID_ATTRIBUTE),
   453  		"isempty_guest_filter":                   isDefault(*cfg.LdapSettings.GuestFilter, ""),
   454  		"isempty_admin_filter":                   isDefault(*cfg.LdapSettings.AdminFilter, ""),
   455  	})
   456  
   457  	a.SendDiagnostic(TRACK_CONFIG_COMPLIANCE, map[string]interface{}{
   458  		"enable":       *cfg.ComplianceSettings.Enable,
   459  		"enable_daily": *cfg.ComplianceSettings.EnableDaily,
   460  	})
   461  
   462  	a.SendDiagnostic(TRACK_CONFIG_LOCALIZATION, map[string]interface{}{
   463  		"default_server_locale": *cfg.LocalizationSettings.DefaultServerLocale,
   464  		"default_client_locale": *cfg.LocalizationSettings.DefaultClientLocale,
   465  		"available_locales":     *cfg.LocalizationSettings.AvailableLocales,
   466  	})
   467  
   468  	a.SendDiagnostic(TRACK_CONFIG_SAML, map[string]interface{}{
   469  		"enable":                              *cfg.SamlSettings.Enable,
   470  		"enable_sync_with_ldap":               *cfg.SamlSettings.EnableSyncWithLdap,
   471  		"enable_sync_with_ldap_include_auth":  *cfg.SamlSettings.EnableSyncWithLdapIncludeAuth,
   472  		"enable_admin_attribute":              *cfg.SamlSettings.EnableAdminAttribute,
   473  		"verify":                              *cfg.SamlSettings.Verify,
   474  		"encrypt":                             *cfg.SamlSettings.Encrypt,
   475  		"sign_request":                        *cfg.SamlSettings.SignRequest,
   476  		"isdefault_signature_algorithm":       isDefault(*cfg.SamlSettings.SignatureAlgorithm, ""),
   477  		"isdefault_canonical_algorithm":       isDefault(*cfg.SamlSettings.CanonicalAlgorithm, ""),
   478  		"isdefault_scoping_idp_provider_id":   isDefault(*cfg.SamlSettings.ScopingIDPProviderId, ""),
   479  		"isdefault_scoping_idp_name":          isDefault(*cfg.SamlSettings.ScopingIDPName, ""),
   480  		"isdefault_id_attribute":              isDefault(*cfg.SamlSettings.IdAttribute, model.SAML_SETTINGS_DEFAULT_ID_ATTRIBUTE),
   481  		"isdefault_guest_attribute":           isDefault(*cfg.SamlSettings.GuestAttribute, model.SAML_SETTINGS_DEFAULT_GUEST_ATTRIBUTE),
   482  		"isdefault_admin_attribute":           isDefault(*cfg.SamlSettings.AdminAttribute, model.SAML_SETTINGS_DEFAULT_ADMIN_ATTRIBUTE),
   483  		"isdefault_first_name_attribute":      isDefault(*cfg.SamlSettings.FirstNameAttribute, model.SAML_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE),
   484  		"isdefault_last_name_attribute":       isDefault(*cfg.SamlSettings.LastNameAttribute, model.SAML_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE),
   485  		"isdefault_email_attribute":           isDefault(*cfg.SamlSettings.EmailAttribute, model.SAML_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE),
   486  		"isdefault_username_attribute":        isDefault(*cfg.SamlSettings.UsernameAttribute, model.SAML_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE),
   487  		"isdefault_nickname_attribute":        isDefault(*cfg.SamlSettings.NicknameAttribute, model.SAML_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE),
   488  		"isdefault_locale_attribute":          isDefault(*cfg.SamlSettings.LocaleAttribute, model.SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE),
   489  		"isdefault_position_attribute":        isDefault(*cfg.SamlSettings.PositionAttribute, model.SAML_SETTINGS_DEFAULT_POSITION_ATTRIBUTE),
   490  		"isdefault_login_button_text":         isDefault(*cfg.SamlSettings.LoginButtonText, model.USER_AUTH_SERVICE_SAML_TEXT),
   491  		"isdefault_login_button_color":        isDefault(*cfg.SamlSettings.LoginButtonColor, ""),
   492  		"isdefault_login_button_border_color": isDefault(*cfg.SamlSettings.LoginButtonBorderColor, ""),
   493  		"isdefault_login_button_text_color":   isDefault(*cfg.SamlSettings.LoginButtonTextColor, ""),
   494  	})
   495  
   496  	a.SendDiagnostic(TRACK_CONFIG_CLUSTER, map[string]interface{}{
   497  		"enable":                  *cfg.ClusterSettings.Enable,
   498  		"network_interface":       isDefault(*cfg.ClusterSettings.NetworkInterface, ""),
   499  		"bind_address":            isDefault(*cfg.ClusterSettings.BindAddress, ""),
   500  		"advertise_address":       isDefault(*cfg.ClusterSettings.AdvertiseAddress, ""),
   501  		"use_ip_address":          *cfg.ClusterSettings.UseIpAddress,
   502  		"use_experimental_gossip": *cfg.ClusterSettings.UseExperimentalGossip,
   503  		"read_only_config":        *cfg.ClusterSettings.ReadOnlyConfig,
   504  	})
   505  
   506  	a.SendDiagnostic(TRACK_CONFIG_METRICS, map[string]interface{}{
   507  		"enable":             *cfg.MetricsSettings.Enable,
   508  		"block_profile_rate": *cfg.MetricsSettings.BlockProfileRate,
   509  	})
   510  
   511  	a.SendDiagnostic(TRACK_CONFIG_NATIVEAPP, map[string]interface{}{
   512  		"isdefault_app_download_link":         isDefault(*cfg.NativeAppSettings.AppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK),
   513  		"isdefault_android_app_download_link": isDefault(*cfg.NativeAppSettings.AndroidAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK),
   514  		"isdefault_iosapp_download_link":      isDefault(*cfg.NativeAppSettings.IosAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK),
   515  	})
   516  
   517  	a.SendDiagnostic(TRACK_CONFIG_EXPERIMENTAL, map[string]interface{}{
   518  		"client_side_cert_enable":            *cfg.ExperimentalSettings.ClientSideCertEnable,
   519  		"isdefault_client_side_cert_check":   isDefault(*cfg.ExperimentalSettings.ClientSideCertCheck, model.CLIENT_SIDE_CERT_CHECK_PRIMARY_AUTH),
   520  		"link_metadata_timeout_milliseconds": *cfg.ExperimentalSettings.LinkMetadataTimeoutMilliseconds,
   521  		"enable_click_to_reply":              *cfg.ExperimentalSettings.EnableClickToReply,
   522  		"restrict_system_admin":              *cfg.ExperimentalSettings.RestrictSystemAdmin,
   523  		"use_new_saml_library":               *cfg.ExperimentalSettings.UseNewSAMLLibrary,
   524  	})
   525  
   526  	a.SendDiagnostic(TRACK_CONFIG_ANALYTICS, map[string]interface{}{
   527  		"isdefault_max_users_for_statistics": isDefault(*cfg.AnalyticsSettings.MaxUsersForStatistics, model.ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS),
   528  	})
   529  
   530  	a.SendDiagnostic(TRACK_CONFIG_ANNOUNCEMENT, map[string]interface{}{
   531  		"enable_banner":               *cfg.AnnouncementSettings.EnableBanner,
   532  		"isdefault_banner_color":      isDefault(*cfg.AnnouncementSettings.BannerColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR),
   533  		"isdefault_banner_text_color": isDefault(*cfg.AnnouncementSettings.BannerTextColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR),
   534  		"allow_banner_dismissal":      *cfg.AnnouncementSettings.AllowBannerDismissal,
   535  	})
   536  
   537  	a.SendDiagnostic(TRACK_CONFIG_ELASTICSEARCH, map[string]interface{}{
   538  		"isdefault_connection_url":          isDefault(*cfg.ElasticsearchSettings.ConnectionUrl, model.ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL),
   539  		"isdefault_username":                isDefault(*cfg.ElasticsearchSettings.Username, model.ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME),
   540  		"isdefault_password":                isDefault(*cfg.ElasticsearchSettings.Password, model.ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD),
   541  		"enable_indexing":                   *cfg.ElasticsearchSettings.EnableIndexing,
   542  		"enable_searching":                  *cfg.ElasticsearchSettings.EnableSearching,
   543  		"enable_autocomplete":               *cfg.ElasticsearchSettings.EnableAutocomplete,
   544  		"sniff":                             *cfg.ElasticsearchSettings.Sniff,
   545  		"post_index_replicas":               *cfg.ElasticsearchSettings.PostIndexReplicas,
   546  		"post_index_shards":                 *cfg.ElasticsearchSettings.PostIndexShards,
   547  		"class_index_replicas":              *cfg.ElasticsearchSettings.ClassIndexReplicas,
   548  		"class_index_shards":                *cfg.ElasticsearchSettings.ClassIndexShards,
   549  		"user_index_replicas":               *cfg.ElasticsearchSettings.UserIndexReplicas,
   550  		"user_index_shards":                 *cfg.ElasticsearchSettings.UserIndexShards,
   551  		"isdefault_index_prefix":            isDefault(*cfg.ElasticsearchSettings.IndexPrefix, model.ELASTICSEARCH_SETTINGS_DEFAULT_INDEX_PREFIX),
   552  		"live_indexing_batch_size":          *cfg.ElasticsearchSettings.LiveIndexingBatchSize,
   553  		"bulk_indexing_time_window_seconds": *cfg.ElasticsearchSettings.BulkIndexingTimeWindowSeconds,
   554  		"request_timeout_seconds":           *cfg.ElasticsearchSettings.RequestTimeoutSeconds,
   555  		"skip_tls_verification":             *cfg.ElasticsearchSettings.SkipTLSVerification,
   556  		"trace":                             *cfg.ElasticsearchSettings.Trace,
   557  	})
   558  
   559  	a.SendDiagnostic(TRACK_CONFIG_DATA_RETENTION, map[string]interface{}{
   560  		"enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion,
   561  		"enable_file_deletion":    *cfg.DataRetentionSettings.EnableFileDeletion,
   562  		"message_retention_days":  *cfg.DataRetentionSettings.MessageRetentionDays,
   563  		"file_retention_days":     *cfg.DataRetentionSettings.FileRetentionDays,
   564  		"deletion_job_start_time": *cfg.DataRetentionSettings.DeletionJobStartTime,
   565  	})
   566  
   567  	a.SendDiagnostic(TRACK_CONFIG_MESSAGE_EXPORT, map[string]interface{}{
   568  		"enable_message_export":                 *cfg.MessageExportSettings.EnableExport,
   569  		"export_format":                         *cfg.MessageExportSettings.ExportFormat,
   570  		"daily_run_time":                        *cfg.MessageExportSettings.DailyRunTime,
   571  		"default_export_from_timestamp":         *cfg.MessageExportSettings.ExportFromTimestamp,
   572  		"batch_size":                            *cfg.MessageExportSettings.BatchSize,
   573  		"global_relay_customer_type":            *cfg.MessageExportSettings.GlobalRelaySettings.CustomerType,
   574  		"is_default_global_relay_smtp_username": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpUsername, ""),
   575  		"is_default_global_relay_smtp_password": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpPassword, ""),
   576  		"is_default_global_relay_email_address": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.EmailAddress, ""),
   577  	})
   578  
   579  	a.SendDiagnostic(TRACK_CONFIG_DISPLAY, map[string]interface{}{
   580  		"experimental_timezone":        *cfg.DisplaySettings.ExperimentalTimezone,
   581  		"isdefault_custom_url_schemes": len(cfg.DisplaySettings.CustomUrlSchemes) != 0,
   582  	})
   583  
   584  	a.SendDiagnostic(TRACK_CONFIG_GUEST_ACCOUNTS, map[string]interface{}{
   585  		"enable":                                 *cfg.GuestAccountsSettings.Enable,
   586  		"allow_email_accounts":                   *cfg.GuestAccountsSettings.AllowEmailAccounts,
   587  		"enforce_multifactor_authentication":     *cfg.GuestAccountsSettings.EnforceMultifactorAuthentication,
   588  		"isdefault_restrict_creation_to_domains": isDefault(*cfg.GuestAccountsSettings.RestrictCreationToDomains, ""),
   589  	})
   590  
   591  	a.SendDiagnostic(TRACK_CONFIG_IMAGE_PROXY, map[string]interface{}{
   592  		"enable":                               *cfg.ImageProxySettings.Enable,
   593  		"image_proxy_type":                     *cfg.ImageProxySettings.ImageProxyType,
   594  		"isdefault_remote_image_proxy_url":     isDefault(*cfg.ImageProxySettings.RemoteImageProxyURL, ""),
   595  		"isdefault_remote_image_proxy_options": isDefault(*cfg.ImageProxySettings.RemoteImageProxyOptions, ""),
   596  	})
   597  }
   598  
   599  func (a *App) trackLicense() {
   600  	if license := a.License(); license != nil {
   601  		data := map[string]interface{}{
   602  			"customer_id": license.Customer.Id,
   603  			"license_id":  license.Id,
   604  			"issued":      license.IssuedAt,
   605  			"start":       license.StartsAt,
   606  			"expire":      license.ExpiresAt,
   607  			"users":       *license.Features.Users,
   608  			"edition":     license.SkuShortName,
   609  		}
   610  
   611  		features := license.Features.ToMap()
   612  		for featureName, featureValue := range features {
   613  			data["feature_"+featureName] = featureValue
   614  		}
   615  
   616  		a.SendDiagnostic(TRACK_LICENSE, data)
   617  	}
   618  }
   619  
   620  func (a *App) trackServer() {
   621  	data := map[string]interface{}{
   622  		"edition":          model.BuildEnterpriseReady,
   623  		"version":          model.CurrentVersion,
   624  		"database_type":    *a.Config().SqlSettings.DriverName,
   625  		"operating_system": runtime.GOOS,
   626  	}
   627  
   628  	if scr, err := a.Srv().Store.User().AnalyticsGetSystemAdminCount(); err == nil {
   629  		data["system_admins"] = scr
   630  	}
   631  
   632  	a.SendDiagnostic(TRACK_SERVER, data)
   633  }
   634  
   635  func (a *App) trackPermissions() {
   636  	phase1Complete := false
   637  	if _, err := a.Srv().Store.System().GetByName(ADVANCED_PERMISSIONS_MIGRATION_KEY); err == nil {
   638  		phase1Complete = true
   639  	}
   640  
   641  	phase2Complete := false
   642  	if _, err := a.Srv().Store.System().GetByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2); err == nil {
   643  		phase2Complete = true
   644  	}
   645  
   646  	a.SendDiagnostic(TRACK_PERMISSIONS_GENERAL, map[string]interface{}{
   647  		"phase_1_migration_complete": phase1Complete,
   648  		"phase_2_migration_complete": phase2Complete,
   649  	})
   650  
   651  	systemAdminPermissions := ""
   652  	if role, err := a.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID); err == nil {
   653  		systemAdminPermissions = strings.Join(role.Permissions, " ")
   654  	}
   655  
   656  	systemUserPermissions := ""
   657  	if role, err := a.GetRoleByName(model.SYSTEM_USER_ROLE_ID); err == nil {
   658  		systemUserPermissions = strings.Join(role.Permissions, " ")
   659  	}
   660  
   661  	branchAdminPermissions := ""
   662  	if role, err := a.GetRoleByName(model.BRANCH_ADMIN_ROLE_ID); err == nil {
   663  		branchAdminPermissions = strings.Join(role.Permissions, " ")
   664  	}
   665  
   666  	branchUserPermissions := ""
   667  	if role, err := a.GetRoleByName(model.BRANCH_USER_ROLE_ID); err == nil {
   668  		branchUserPermissions = strings.Join(role.Permissions, " ")
   669  	}
   670  
   671  	classAdminPermissions := ""
   672  	if role, err := a.GetRoleByName(model.CLASS_ADMIN_ROLE_ID); err == nil {
   673  		classAdminPermissions = strings.Join(role.Permissions, " ")
   674  	}
   675  
   676  	classUserPermissions := ""
   677  	if role, err := a.GetRoleByName(model.CLASS_USER_ROLE_ID); err == nil {
   678  		classUserPermissions = strings.Join(role.Permissions, " ")
   679  	}
   680  
   681  	a.SendDiagnostic(TRACK_PERMISSIONS_SYSTEM_SCHEME, map[string]interface{}{
   682  		"system_admin_permissions": systemAdminPermissions,
   683  		"system_user_permissions":  systemUserPermissions,
   684  		"branch_admin_permissions": branchAdminPermissions,
   685  		"branch_user_permissions":  branchUserPermissions,
   686  		"class_admin_permissions":  classAdminPermissions,
   687  		"class_user_permissions":   classUserPermissions,
   688  	})
   689  
   690  	if schemes, err := a.GetSchemes(model.SCHEME_SCOPE_BRANCH, 0, 100); err == nil {
   691  		for _, scheme := range schemes {
   692  			branchAdminPermissions := ""
   693  			if role, err := a.GetRoleByName(scheme.DefaultBranchAdminRole); err == nil {
   694  				branchAdminPermissions = strings.Join(role.Permissions, " ")
   695  			}
   696  
   697  			branchUserPermissions := ""
   698  			if role, err := a.GetRoleByName(scheme.DefaultBranchUserRole); err == nil {
   699  				branchUserPermissions = strings.Join(role.Permissions, " ")
   700  			}
   701  
   702  			classAdminPermissions := ""
   703  			if role, err := a.GetRoleByName(scheme.DefaultClassAdminRole); err == nil {
   704  				classAdminPermissions = strings.Join(role.Permissions, " ")
   705  			}
   706  
   707  			classUserPermissions := ""
   708  			if role, err := a.GetRoleByName(scheme.DefaultClassUserRole); err == nil {
   709  				classUserPermissions = strings.Join(role.Permissions, " ")
   710  			}
   711  
   712  			count, _ := a.Srv().Store.Branch().AnalyticsGetBranchCountForScheme(scheme.Id)
   713  
   714  			a.SendDiagnostic(TRACK_PERMISSIONS_BRANCH_SCHEMES, map[string]interface{}{
   715  				"scheme_id":                scheme.Id,
   716  				"branch_admin_permissions": branchAdminPermissions,
   717  				"branch_user_permissions":  branchUserPermissions,
   718  				"class_admin_permissions":  classAdminPermissions,
   719  				"class_user_permissions":   classUserPermissions,
   720  				"branch_count":             count,
   721  			})
   722  		}
   723  	}
   724  }
   725  
   726  func (a *App) trackElasticsearch() {
   727  	data := map[string]interface{}{}
   728  
   729  	for _, engine := range a.SearchEngine().GetActiveEngines() {
   730  		if engine.GetVersion() != 0 && engine.GetName() == "elasticsearch" {
   731  			data["elasticsearch_server_version"] = engine.GetVersion()
   732  		}
   733  	}
   734  
   735  	a.SendDiagnostic(TRACK_ELASTICSEARCH, data)
   736  }
   737  
   738  func (a *App) trackClassModeration() {
   739  	classSchemeCount, err := a.Srv().Store.Scheme().CountByScope(model.SCHEME_SCOPE_CLASS)
   740  	if err != nil {
   741  		mlog.Error(err.Error())
   742  	}
   743  
   744  	createPostUser, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_CREATE_POST.Id, model.RoleScopeClass, model.RoleTypeUser)
   745  	if err != nil {
   746  		mlog.Error(err.Error())
   747  	}
   748  
   749  	createPostGuest, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_CREATE_POST.Id, model.RoleScopeClass, model.RoleTypeGuest)
   750  	if err != nil {
   751  		mlog.Error(err.Error())
   752  	}
   753  
   754  	// only need to track one of 'add_reaction' or 'remove_reaction` because they're both toggled together by the class moderation feature
   755  	postReactionsUser, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_ADD_REACTION.Id, model.RoleScopeClass, model.RoleTypeUser)
   756  	if err != nil {
   757  		mlog.Error(err.Error())
   758  	}
   759  
   760  	postReactionsGuest, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_ADD_REACTION.Id, model.RoleScopeClass, model.RoleTypeGuest)
   761  	if err != nil {
   762  		mlog.Error(err.Error())
   763  	}
   764  
   765  	// only need to track one of 'manage_public_class_members' or 'manage_private_class_members` because they're both toggled together by the class moderation feature
   766  	manageMembersUser, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_MANAGE_CLASS_MEMBERS.Id, model.RoleScopeClass, model.RoleTypeUser)
   767  	if err != nil {
   768  		mlog.Error(err.Error())
   769  	}
   770  
   771  	useClassMentionsUser, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_USE_CLASS_MENTIONS.Id, model.RoleScopeClass, model.RoleTypeUser)
   772  	if err != nil {
   773  		mlog.Error(err.Error())
   774  	}
   775  
   776  	useClassMentionsGuest, err := a.Srv().Store.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CLASS, model.PERMISSION_USE_CLASS_MENTIONS.Id, model.RoleScopeClass, model.RoleTypeGuest)
   777  	if err != nil {
   778  		mlog.Error(err.Error())
   779  	}
   780  
   781  	a.SendDiagnostic(TRACK_CLASS_MODERATION, map[string]interface{}{
   782  		"class_scheme_count": classSchemeCount,
   783  
   784  		"create_post_user_disabled_count":  createPostUser,
   785  		"create_post_guest_disabled_count": createPostGuest,
   786  
   787  		"post_reactions_user_disabled_count":  postReactionsUser,
   788  		"post_reactions_guest_disabled_count": postReactionsGuest,
   789  
   790  		"manage_members_user_disabled_count": manageMembersUser, // the UI does not allow this to be removed for guests
   791  
   792  		"use_class_mentions_user_disabled_count":  useClassMentionsUser,
   793  		"use_class_mentions_guest_disabled_count": useClassMentionsGuest,
   794  	})
   795  }