github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/services/telemetry/telemetry.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package telemetry 5 6 import ( 7 "os" 8 "path/filepath" 9 "runtime" 10 "strings" 11 "time" 12 13 rudder "github.com/rudderlabs/analytics-go" 14 15 "github.com/mattermost/mattermost-server/v5/mlog" 16 "github.com/mattermost/mattermost-server/v5/model" 17 "github.com/mattermost/mattermost-server/v5/plugin" 18 "github.com/mattermost/mattermost-server/v5/services/httpservice" 19 "github.com/mattermost/mattermost-server/v5/services/marketplace" 20 "github.com/mattermost/mattermost-server/v5/services/searchengine" 21 "github.com/mattermost/mattermost-server/v5/store" 22 "github.com/mattermost/mattermost-server/v5/utils" 23 ) 24 25 const ( 26 DayMilliseconds = 24 * 60 * 60 * 1000 27 MonthMilliseconds = 31 * DayMilliseconds 28 29 RudderKey = "placeholder_rudder_key" 30 RudderDataplaneURL = "placeholder_rudder_dataplane_url" 31 32 EnvVarInstallType = "MM_INSTALL_TYPE" 33 34 TrackConfigService = "config_service" 35 TrackConfigTeam = "config_team" 36 TrackConfigClientReq = "config_client_requirements" 37 TrackConfigSQL = "config_sql" 38 TrackConfigLog = "config_log" 39 TrackConfigAudit = "config_audit" 40 TrackConfigNotificationLog = "config_notifications_log" 41 TrackConfigFile = "config_file" 42 TrackConfigRate = "config_rate" 43 TrackConfigEmail = "config_email" 44 TrackConfigPrivacy = "config_privacy" 45 TrackConfigTheme = "config_theme" 46 TrackConfigOauth = "config_oauth" 47 TrackConfigLDAP = "config_ldap" 48 TrackConfigCompliance = "config_compliance" 49 TrackConfigLocalization = "config_localization" 50 TrackConfigSAML = "config_saml" 51 TrackConfigPassword = "config_password" 52 TrackConfigCluster = "config_cluster" 53 TrackConfigMetrics = "config_metrics" 54 TrackConfigSupport = "config_support" 55 TrackConfigNativeApp = "config_nativeapp" 56 TrackConfigExperimental = "config_experimental" 57 TrackConfigAnalytics = "config_analytics" 58 TrackConfigAnnouncement = "config_announcement" 59 TrackConfigElasticsearch = "config_elasticsearch" 60 TrackConfigPlugin = "config_plugin" 61 TrackConfigDataRetention = "config_data_retention" 62 TrackConfigMessageExport = "config_message_export" 63 TrackConfigDisplay = "config_display" 64 TrackConfigGuestAccounts = "config_guest_accounts" 65 TrackConfigImageProxy = "config_image_proxy" 66 TrackConfigBleve = "config_bleve" 67 TrackConfigExport = "config_export" 68 TrackPermissionsGeneral = "permissions_general" 69 TrackPermissionsSystemScheme = "permissions_system_scheme" 70 TrackPermissionsTeamSchemes = "permissions_team_schemes" 71 TrackPermissionsSystemRoles = "permissions_system_roles" 72 TrackElasticsearch = "elasticsearch" 73 TrackGroups = "groups" 74 TrackChannelModeration = "channel_moderation" 75 TrackWarnMetrics = "warn_metrics" 76 77 TrackActivity = "activity" 78 TrackLicense = "license" 79 TrackServer = "server" 80 TrackPlugins = "plugins" 81 ) 82 83 type ServerIface interface { 84 Config() *model.Config 85 IsLeader() bool 86 HttpService() httpservice.HTTPService 87 GetPluginsEnvironment() *plugin.Environment 88 License() *model.License 89 GetRoleByName(string) (*model.Role, *model.AppError) 90 GetSchemes(string, int, int) ([]*model.Scheme, *model.AppError) 91 } 92 93 type TelemetryService struct { 94 srv ServerIface 95 dbStore store.Store 96 searchEngine *searchengine.Broker 97 log *mlog.Logger 98 rudderClient rudder.Client 99 TelemetryID string 100 timestampLastTelemetrySent time.Time 101 } 102 103 type RudderConfig struct { 104 RudderKey string 105 DataplaneUrl string 106 } 107 108 func New(srv ServerIface, dbStore store.Store, searchEngine *searchengine.Broker, log *mlog.Logger) *TelemetryService { 109 service := &TelemetryService{ 110 srv: srv, 111 dbStore: dbStore, 112 searchEngine: searchEngine, 113 log: log, 114 } 115 service.ensureTelemetryID() 116 return service 117 } 118 119 func (ts *TelemetryService) ensureTelemetryID() { 120 if ts.TelemetryID != "" { 121 return 122 } 123 props, err := ts.dbStore.System().Get() 124 if err != nil { 125 mlog.Error("unable to get the telemetry ID", mlog.Err(err)) 126 return 127 } 128 129 id := props[model.SYSTEM_TELEMETRY_ID] 130 if id == "" { 131 id = model.NewId() 132 systemID := &model.System{Name: model.SYSTEM_TELEMETRY_ID, Value: id} 133 ts.dbStore.System().Save(systemID) 134 } 135 136 ts.TelemetryID = id 137 } 138 139 func (ts *TelemetryService) getRudderConfig() RudderConfig { 140 if !strings.Contains(RudderKey, "placeholder") && !strings.Contains(RudderDataplaneURL, "placeholder") { 141 return RudderConfig{RudderKey, RudderDataplaneURL} 142 } else if os.Getenv("RudderKey") != "" && os.Getenv("RudderDataplaneURL") != "" { 143 return RudderConfig{os.Getenv("RudderKey"), os.Getenv("RudderDataplaneURL")} 144 } else { 145 return RudderConfig{} 146 } 147 } 148 149 func (ts *TelemetryService) telemetryEnabled() bool { 150 return *ts.srv.Config().LogSettings.EnableDiagnostics && ts.srv.IsLeader() 151 } 152 153 func (ts *TelemetryService) sendDailyTelemetry(override bool) { 154 config := ts.getRudderConfig() 155 if ts.telemetryEnabled() && ((config.DataplaneUrl != "" && config.RudderKey != "") || override) { 156 ts.initRudder(config.DataplaneUrl, config.RudderKey) 157 ts.trackActivity() 158 ts.trackConfig() 159 ts.trackLicense() 160 ts.trackPlugins() 161 ts.trackServer() 162 ts.trackPermissions() 163 ts.trackElasticsearch() 164 ts.trackGroups() 165 ts.trackChannelModeration() 166 ts.trackWarnMetrics() 167 } 168 } 169 170 func (ts *TelemetryService) sendTelemetry(event string, properties map[string]interface{}) { 171 if ts.rudderClient != nil { 172 var context *rudder.Context 173 // if we are part of a cloud installation, add it's ID to the tracked event's context 174 if installationId := os.Getenv("MM_CLOUD_INSTALLATION_ID"); installationId != "" { 175 context = &rudder.Context{Traits: map[string]interface{}{"installationId": installationId}} 176 } 177 ts.rudderClient.Enqueue(rudder.Track{ 178 Event: event, 179 UserId: ts.TelemetryID, 180 Properties: properties, 181 Context: context, 182 }) 183 } 184 } 185 186 func isDefaultArray(setting, defaultValue []string) bool { 187 if len(setting) != len(defaultValue) { 188 return false 189 } 190 for i := 0; i < len(setting); i++ { 191 if setting[i] != defaultValue[i] { 192 return false 193 } 194 } 195 return true 196 } 197 198 func isDefault(setting interface{}, defaultValue interface{}) bool { 199 return setting == defaultValue 200 } 201 202 func pluginSetting(pluginSettings *model.PluginSettings, plugin, key string, defaultValue interface{}) interface{} { 203 settings, ok := pluginSettings.Plugins[plugin] 204 if !ok { 205 return defaultValue 206 } 207 if value, ok := settings[key]; ok { 208 return value 209 } 210 return defaultValue 211 } 212 213 func pluginActivated(pluginStates map[string]*model.PluginState, pluginId string) bool { 214 state, ok := pluginStates[pluginId] 215 if !ok { 216 return false 217 } 218 return state.Enable 219 } 220 221 func pluginVersion(pluginsAvailable []*model.BundleInfo, pluginId string) string { 222 for _, plugin := range pluginsAvailable { 223 if plugin.Manifest != nil && plugin.Manifest.Id == pluginId { 224 return plugin.Manifest.Version 225 } 226 } 227 return "" 228 } 229 230 func (ts *TelemetryService) trackActivity() { 231 var userCount int64 232 var guestAccountsCount int64 233 var botAccountsCount int64 234 var inactiveUserCount int64 235 var publicChannelCount int64 236 var privateChannelCount int64 237 var directChannelCount int64 238 var deletedPublicChannelCount int64 239 var deletedPrivateChannelCount int64 240 var postsCount int64 241 var postsCountPreviousDay int64 242 var botPostsCountPreviousDay int64 243 var slashCommandsCount int64 244 var incomingWebhooksCount int64 245 var outgoingWebhooksCount int64 246 247 activeUsersDailyCountChan := make(chan store.StoreResult, 1) 248 go func() { 249 count, err := ts.dbStore.User().AnalyticsActiveCount(DayMilliseconds, model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false}) 250 activeUsersDailyCountChan <- store.StoreResult{Data: count, NErr: err} 251 close(activeUsersDailyCountChan) 252 }() 253 254 activeUsersMonthlyCountChan := make(chan store.StoreResult, 1) 255 go func() { 256 count, err := ts.dbStore.User().AnalyticsActiveCount(MonthMilliseconds, model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false}) 257 activeUsersMonthlyCountChan <- store.StoreResult{Data: count, NErr: err} 258 close(activeUsersMonthlyCountChan) 259 }() 260 261 if count, err := ts.dbStore.User().Count(model.UserCountOptions{IncludeDeleted: true}); err == nil { 262 userCount = count 263 } 264 265 if count, err := ts.dbStore.User().AnalyticsGetGuestCount(); err == nil { 266 guestAccountsCount = count 267 } 268 269 if count, err := ts.dbStore.User().Count(model.UserCountOptions{IncludeBotAccounts: true, ExcludeRegularUsers: true}); err == nil { 270 botAccountsCount = count 271 } 272 273 if iucr, err := ts.dbStore.User().AnalyticsGetInactiveUsersCount(); err == nil { 274 inactiveUserCount = iucr 275 } 276 277 teamCount, err := ts.dbStore.Team().AnalyticsTeamCount(false) 278 if err != nil { 279 mlog.Info("Could not get team count", mlog.Err(err)) 280 } 281 282 if ucc, err := ts.dbStore.Channel().AnalyticsTypeCount("", "O"); err == nil { 283 publicChannelCount = ucc 284 } 285 286 if pcc, err := ts.dbStore.Channel().AnalyticsTypeCount("", "P"); err == nil { 287 privateChannelCount = pcc 288 } 289 290 if dcc, err := ts.dbStore.Channel().AnalyticsTypeCount("", "D"); err == nil { 291 directChannelCount = dcc 292 } 293 294 if duccr, err := ts.dbStore.Channel().AnalyticsDeletedTypeCount("", "O"); err == nil { 295 deletedPublicChannelCount = duccr 296 } 297 298 if dpccr, err := ts.dbStore.Channel().AnalyticsDeletedTypeCount("", "P"); err == nil { 299 deletedPrivateChannelCount = dpccr 300 } 301 302 postsCount, _ = ts.dbStore.Post().AnalyticsPostCount("", false, false) 303 304 postCountsOptions := &model.AnalyticsPostCountsOptions{TeamId: "", BotsOnly: false, YesterdayOnly: true} 305 postCountsYesterday, _ := ts.dbStore.Post().AnalyticsPostCountsByDay(postCountsOptions) 306 postsCountPreviousDay = 0 307 if len(postCountsYesterday) > 0 { 308 postsCountPreviousDay = int64(postCountsYesterday[0].Value) 309 } 310 311 postCountsOptions = &model.AnalyticsPostCountsOptions{TeamId: "", BotsOnly: true, YesterdayOnly: true} 312 botPostCountsYesterday, _ := ts.dbStore.Post().AnalyticsPostCountsByDay(postCountsOptions) 313 botPostsCountPreviousDay = 0 314 if len(botPostCountsYesterday) > 0 { 315 botPostsCountPreviousDay = int64(botPostCountsYesterday[0].Value) 316 } 317 318 slashCommandsCount, _ = ts.dbStore.Command().AnalyticsCommandCount("") 319 320 if c, err := ts.dbStore.Webhook().AnalyticsIncomingCount(""); err == nil { 321 incomingWebhooksCount = c 322 } 323 324 outgoingWebhooksCount, _ = ts.dbStore.Webhook().AnalyticsOutgoingCount("") 325 326 var activeUsersDailyCount int64 327 if r := <-activeUsersDailyCountChan; r.NErr == nil { 328 activeUsersDailyCount = r.Data.(int64) 329 } 330 331 var activeUsersMonthlyCount int64 332 if r := <-activeUsersMonthlyCountChan; r.NErr == nil { 333 activeUsersMonthlyCount = r.Data.(int64) 334 } 335 336 ts.sendTelemetry(TrackActivity, map[string]interface{}{ 337 "registered_users": userCount, 338 "bot_accounts": botAccountsCount, 339 "guest_accounts": guestAccountsCount, 340 "active_users_daily": activeUsersDailyCount, 341 "active_users_monthly": activeUsersMonthlyCount, 342 "registered_deactivated_users": inactiveUserCount, 343 "teams": teamCount, 344 "public_channels": publicChannelCount, 345 "private_channels": privateChannelCount, 346 "direct_message_channels": directChannelCount, 347 "public_channels_deleted": deletedPublicChannelCount, 348 "private_channels_deleted": deletedPrivateChannelCount, 349 "posts_previous_day": postsCountPreviousDay, 350 "bot_posts_previous_day": botPostsCountPreviousDay, 351 "posts": postsCount, 352 "slash_commands": slashCommandsCount, 353 "incoming_webhooks": incomingWebhooksCount, 354 "outgoing_webhooks": outgoingWebhooksCount, 355 }) 356 } 357 358 func (ts *TelemetryService) trackConfig() { 359 cfg := ts.srv.Config() 360 ts.sendTelemetry(TrackConfigService, map[string]interface{}{ 361 "web_server_mode": *cfg.ServiceSettings.WebserverMode, 362 "enable_security_fix_alert": *cfg.ServiceSettings.EnableSecurityFixAlert, 363 "enable_insecure_outgoing_connections": *cfg.ServiceSettings.EnableInsecureOutgoingConnections, 364 "enable_incoming_webhooks": cfg.ServiceSettings.EnableIncomingWebhooks, 365 "enable_outgoing_webhooks": cfg.ServiceSettings.EnableOutgoingWebhooks, 366 "enable_commands": *cfg.ServiceSettings.EnableCommands, 367 "enable_only_admin_integrations": *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_EnableOnlyAdminIntegrations, 368 "enable_post_username_override": cfg.ServiceSettings.EnablePostUsernameOverride, 369 "enable_post_icon_override": cfg.ServiceSettings.EnablePostIconOverride, 370 "enable_user_access_tokens": *cfg.ServiceSettings.EnableUserAccessTokens, 371 "enable_custom_emoji": *cfg.ServiceSettings.EnableCustomEmoji, 372 "enable_emoji_picker": *cfg.ServiceSettings.EnableEmojiPicker, 373 "enable_gif_picker": *cfg.ServiceSettings.EnableGifPicker, 374 "gfycat_api_key": isDefault(*cfg.ServiceSettings.GfycatApiKey, model.SERVICE_SETTINGS_DEFAULT_GFYCAT_API_KEY), 375 "gfycat_api_secret": isDefault(*cfg.ServiceSettings.GfycatApiSecret, model.SERVICE_SETTINGS_DEFAULT_GFYCAT_API_SECRET), 376 "experimental_enable_authentication_transfer": *cfg.ServiceSettings.ExperimentalEnableAuthenticationTransfer, 377 "restrict_custom_emoji_creation": *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_RestrictCustomEmojiCreation, 378 "enable_testing": cfg.ServiceSettings.EnableTesting, 379 "enable_developer": *cfg.ServiceSettings.EnableDeveloper, 380 "enable_multifactor_authentication": *cfg.ServiceSettings.EnableMultifactorAuthentication, 381 "enforce_multifactor_authentication": *cfg.ServiceSettings.EnforceMultifactorAuthentication, 382 "enable_oauth_service_provider": cfg.ServiceSettings.EnableOAuthServiceProvider, 383 "connection_security": *cfg.ServiceSettings.ConnectionSecurity, 384 "tls_strict_transport": *cfg.ServiceSettings.TLSStrictTransport, 385 "uses_letsencrypt": *cfg.ServiceSettings.UseLetsEncrypt, 386 "forward_80_to_443": *cfg.ServiceSettings.Forward80To443, 387 "maximum_login_attempts": *cfg.ServiceSettings.MaximumLoginAttempts, 388 "extend_session_length_with_activity": *cfg.ServiceSettings.ExtendSessionLengthWithActivity, 389 "session_length_web_in_days": *cfg.ServiceSettings.SessionLengthWebInDays, 390 "session_length_mobile_in_days": *cfg.ServiceSettings.SessionLengthMobileInDays, 391 "session_length_sso_in_days": *cfg.ServiceSettings.SessionLengthSSOInDays, 392 "session_cache_in_minutes": *cfg.ServiceSettings.SessionCacheInMinutes, 393 "session_idle_timeout_in_minutes": *cfg.ServiceSettings.SessionIdleTimeoutInMinutes, 394 "isdefault_site_url": isDefault(*cfg.ServiceSettings.SiteURL, model.SERVICE_SETTINGS_DEFAULT_SITE_URL), 395 "isdefault_tls_cert_file": isDefault(*cfg.ServiceSettings.TLSCertFile, model.SERVICE_SETTINGS_DEFAULT_TLS_CERT_FILE), 396 "isdefault_tls_key_file": isDefault(*cfg.ServiceSettings.TLSKeyFile, model.SERVICE_SETTINGS_DEFAULT_TLS_KEY_FILE), 397 "isdefault_read_timeout": isDefault(*cfg.ServiceSettings.ReadTimeout, model.SERVICE_SETTINGS_DEFAULT_READ_TIMEOUT), 398 "isdefault_write_timeout": isDefault(*cfg.ServiceSettings.WriteTimeout, model.SERVICE_SETTINGS_DEFAULT_WRITE_TIMEOUT), 399 "isdefault_idle_timeout": isDefault(*cfg.ServiceSettings.IdleTimeout, model.SERVICE_SETTINGS_DEFAULT_IDLE_TIMEOUT), 400 "isdefault_google_developer_key": isDefault(cfg.ServiceSettings.GoogleDeveloperKey, ""), 401 "isdefault_allow_cors_from": isDefault(*cfg.ServiceSettings.AllowCorsFrom, model.SERVICE_SETTINGS_DEFAULT_ALLOW_CORS_FROM), 402 "isdefault_cors_exposed_headers": isDefault(cfg.ServiceSettings.CorsExposedHeaders, ""), 403 "cors_allow_credentials": *cfg.ServiceSettings.CorsAllowCredentials, 404 "cors_debug": *cfg.ServiceSettings.CorsDebug, 405 "isdefault_allowed_untrusted_internal_connections": isDefault(*cfg.ServiceSettings.AllowedUntrustedInternalConnections, ""), 406 "restrict_post_delete": *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_RestrictPostDelete, 407 "allow_edit_post": *cfg.ServiceSettings.DEPRECATED_DO_NOT_USE_AllowEditPost, 408 "post_edit_time_limit": *cfg.ServiceSettings.PostEditTimeLimit, 409 "enable_user_typing_messages": *cfg.ServiceSettings.EnableUserTypingMessages, 410 "enable_channel_viewed_messages": *cfg.ServiceSettings.EnableChannelViewedMessages, 411 "time_between_user_typing_updates_milliseconds": *cfg.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds, 412 "cluster_log_timeout_milliseconds": *cfg.ServiceSettings.ClusterLogTimeoutMilliseconds, 413 "enable_post_search": *cfg.ServiceSettings.EnablePostSearch, 414 "minimum_hashtag_length": *cfg.ServiceSettings.MinimumHashtagLength, 415 "enable_user_statuses": *cfg.ServiceSettings.EnableUserStatuses, 416 "close_unused_direct_messages": *cfg.ServiceSettings.CloseUnusedDirectMessages, 417 "enable_preview_features": *cfg.ServiceSettings.EnablePreviewFeatures, 418 "enable_tutorial": *cfg.ServiceSettings.EnableTutorial, 419 "experimental_enable_default_channel_leave_join_messages": *cfg.ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages, 420 "experimental_group_unread_channels": *cfg.ServiceSettings.ExperimentalGroupUnreadChannels, 421 "collapsed_threads": *cfg.ServiceSettings.CollapsedThreads, 422 "websocket_url": isDefault(*cfg.ServiceSettings.WebsocketURL, ""), 423 "allow_cookies_for_subdomains": *cfg.ServiceSettings.AllowCookiesForSubdomains, 424 "enable_api_team_deletion": *cfg.ServiceSettings.EnableAPITeamDeletion, 425 "enable_api_user_deletion": *cfg.ServiceSettings.EnableAPIUserDeletion, 426 "enable_api_channel_deletion": *cfg.ServiceSettings.EnableAPIChannelDeletion, 427 "experimental_enable_hardened_mode": *cfg.ServiceSettings.ExperimentalEnableHardenedMode, 428 "disable_legacy_mfa": *cfg.ServiceSettings.DisableLegacyMFA, 429 "experimental_strict_csrf_enforcement": *cfg.ServiceSettings.ExperimentalStrictCSRFEnforcement, 430 "enable_email_invitations": *cfg.ServiceSettings.EnableEmailInvitations, 431 "experimental_channel_organization": *cfg.ServiceSettings.ExperimentalChannelOrganization, 432 "disable_bots_when_owner_is_deactivated": *cfg.ServiceSettings.DisableBotsWhenOwnerIsDeactivated, 433 "enable_bot_account_creation": *cfg.ServiceSettings.EnableBotAccountCreation, 434 "enable_svgs": *cfg.ServiceSettings.EnableSVGs, 435 "enable_latex": *cfg.ServiceSettings.EnableLatex, 436 "enable_opentracing": *cfg.ServiceSettings.EnableOpenTracing, 437 "enable_local_mode": *cfg.ServiceSettings.EnableLocalMode, 438 "managed_resource_paths": isDefault(*cfg.ServiceSettings.ManagedResourcePaths, ""), 439 "enable_legacy_sidebar": *cfg.ServiceSettings.EnableLegacySidebar, 440 "thread_auto_follow": *cfg.ServiceSettings.ThreadAutoFollow, 441 "enable_link_previews": *cfg.ServiceSettings.EnableLinkPreviews, 442 }) 443 444 ts.sendTelemetry(TrackConfigTeam, map[string]interface{}{ 445 "enable_user_creation": cfg.TeamSettings.EnableUserCreation, 446 "enable_team_creation": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_EnableTeamCreation, 447 "restrict_team_invite": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictTeamInvite, 448 "restrict_public_channel_creation": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPublicChannelCreation, 449 "restrict_private_channel_creation": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelCreation, 450 "restrict_public_channel_management": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPublicChannelManagement, 451 "restrict_private_channel_management": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManagement, 452 "restrict_public_channel_deletion": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPublicChannelDeletion, 453 "restrict_private_channel_deletion": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelDeletion, 454 "enable_open_server": *cfg.TeamSettings.EnableOpenServer, 455 "enable_user_deactivation": *cfg.TeamSettings.EnableUserDeactivation, 456 "enable_custom_user_statuses": *cfg.TeamSettings.EnableCustomUserStatuses, 457 "enable_custom_brand": *cfg.TeamSettings.EnableCustomBrand, 458 "restrict_direct_message": *cfg.TeamSettings.RestrictDirectMessage, 459 "max_notifications_per_channel": *cfg.TeamSettings.MaxNotificationsPerChannel, 460 "enable_confirm_notifications_to_channel": *cfg.TeamSettings.EnableConfirmNotificationsToChannel, 461 "max_users_per_team": *cfg.TeamSettings.MaxUsersPerTeam, 462 "max_channels_per_team": *cfg.TeamSettings.MaxChannelsPerTeam, 463 "teammate_name_display": *cfg.TeamSettings.TeammateNameDisplay, 464 "experimental_view_archived_channels": *cfg.TeamSettings.ExperimentalViewArchivedChannels, 465 "lock_teammate_name_display": *cfg.TeamSettings.LockTeammateNameDisplay, 466 "isdefault_site_name": isDefault(cfg.TeamSettings.SiteName, "Mattermost"), 467 "isdefault_custom_brand_text": isDefault(*cfg.TeamSettings.CustomBrandText, model.TEAM_SETTINGS_DEFAULT_CUSTOM_BRAND_TEXT), 468 "isdefault_custom_description_text": isDefault(*cfg.TeamSettings.CustomDescriptionText, model.TEAM_SETTINGS_DEFAULT_CUSTOM_DESCRIPTION_TEXT), 469 "isdefault_user_status_away_timeout": isDefault(*cfg.TeamSettings.UserStatusAwayTimeout, model.TEAM_SETTINGS_DEFAULT_USER_STATUS_AWAY_TIMEOUT), 470 "restrict_private_channel_manage_members": *cfg.TeamSettings.DEPRECATED_DO_NOT_USE_RestrictPrivateChannelManageMembers, 471 "enable_X_to_leave_channels_from_LHS": *cfg.TeamSettings.EnableXToLeaveChannelsFromLHS, 472 "experimental_enable_automatic_replies": *cfg.TeamSettings.ExperimentalEnableAutomaticReplies, 473 "experimental_town_square_is_hidden_in_lhs": *cfg.TeamSettings.ExperimentalHideTownSquareinLHS, 474 "experimental_town_square_is_read_only": *cfg.TeamSettings.ExperimentalTownSquareIsReadOnly, 475 "experimental_primary_team": isDefault(*cfg.TeamSettings.ExperimentalPrimaryTeam, ""), 476 "experimental_default_channels": len(cfg.TeamSettings.ExperimentalDefaultChannels), 477 }) 478 479 ts.sendTelemetry(TrackConfigClientReq, map[string]interface{}{ 480 "android_latest_version": cfg.ClientRequirements.AndroidLatestVersion, 481 "android_min_version": cfg.ClientRequirements.AndroidMinVersion, 482 "desktop_latest_version": cfg.ClientRequirements.DesktopLatestVersion, 483 "desktop_min_version": cfg.ClientRequirements.DesktopMinVersion, 484 "ios_latest_version": cfg.ClientRequirements.IosLatestVersion, 485 "ios_min_version": cfg.ClientRequirements.IosMinVersion, 486 }) 487 488 ts.sendTelemetry(TrackConfigSQL, map[string]interface{}{ 489 "driver_name": *cfg.SqlSettings.DriverName, 490 "trace": cfg.SqlSettings.Trace, 491 "max_idle_conns": *cfg.SqlSettings.MaxIdleConns, 492 "conn_max_lifetime_milliseconds": *cfg.SqlSettings.ConnMaxLifetimeMilliseconds, 493 "conn_max_idletime_milliseconds": *cfg.SqlSettings.ConnMaxIdleTimeMilliseconds, 494 "max_open_conns": *cfg.SqlSettings.MaxOpenConns, 495 "data_source_replicas": len(cfg.SqlSettings.DataSourceReplicas), 496 "data_source_search_replicas": len(cfg.SqlSettings.DataSourceSearchReplicas), 497 "query_timeout": *cfg.SqlSettings.QueryTimeout, 498 "disable_database_search": *cfg.SqlSettings.DisableDatabaseSearch, 499 }) 500 501 ts.sendTelemetry(TrackConfigLog, map[string]interface{}{ 502 "enable_console": cfg.LogSettings.EnableConsole, 503 "console_level": cfg.LogSettings.ConsoleLevel, 504 "console_json": *cfg.LogSettings.ConsoleJson, 505 "enable_file": cfg.LogSettings.EnableFile, 506 "file_level": cfg.LogSettings.FileLevel, 507 "file_json": cfg.LogSettings.FileJson, 508 "enable_webhook_debugging": cfg.LogSettings.EnableWebhookDebugging, 509 "isdefault_file_location": isDefault(cfg.LogSettings.FileLocation, ""), 510 "advanced_logging_config": *cfg.LogSettings.AdvancedLoggingConfig != "", 511 }) 512 513 ts.sendTelemetry(TrackConfigAudit, map[string]interface{}{ 514 "file_enabled": *cfg.ExperimentalAuditSettings.FileEnabled, 515 "file_max_size_mb": *cfg.ExperimentalAuditSettings.FileMaxSizeMB, 516 "file_max_age_days": *cfg.ExperimentalAuditSettings.FileMaxAgeDays, 517 "file_max_backups": *cfg.ExperimentalAuditSettings.FileMaxBackups, 518 "file_compress": *cfg.ExperimentalAuditSettings.FileCompress, 519 "file_max_queue_size": *cfg.ExperimentalAuditSettings.FileMaxQueueSize, 520 "advanced_logging_config": *cfg.ExperimentalAuditSettings.AdvancedLoggingConfig != "", 521 }) 522 523 ts.sendTelemetry(TrackConfigNotificationLog, map[string]interface{}{ 524 "enable_console": *cfg.NotificationLogSettings.EnableConsole, 525 "console_level": *cfg.NotificationLogSettings.ConsoleLevel, 526 "console_json": *cfg.NotificationLogSettings.ConsoleJson, 527 "enable_file": *cfg.NotificationLogSettings.EnableFile, 528 "file_level": *cfg.NotificationLogSettings.FileLevel, 529 "file_json": *cfg.NotificationLogSettings.FileJson, 530 "isdefault_file_location": isDefault(*cfg.NotificationLogSettings.FileLocation, ""), 531 "advanced_logging_config": *cfg.NotificationLogSettings.AdvancedLoggingConfig != "", 532 }) 533 534 ts.sendTelemetry(TrackConfigPassword, map[string]interface{}{ 535 "minimum_length": *cfg.PasswordSettings.MinimumLength, 536 "lowercase": *cfg.PasswordSettings.Lowercase, 537 "number": *cfg.PasswordSettings.Number, 538 "uppercase": *cfg.PasswordSettings.Uppercase, 539 "symbol": *cfg.PasswordSettings.Symbol, 540 }) 541 542 ts.sendTelemetry(TrackConfigFile, map[string]interface{}{ 543 "enable_public_links": cfg.FileSettings.EnablePublicLink, 544 "driver_name": *cfg.FileSettings.DriverName, 545 "isdefault_directory": isDefault(*cfg.FileSettings.Directory, model.FILE_SETTINGS_DEFAULT_DIRECTORY), 546 "isabsolute_directory": filepath.IsAbs(*cfg.FileSettings.Directory), 547 "amazon_s3_ssl": *cfg.FileSettings.AmazonS3SSL, 548 "amazon_s3_sse": *cfg.FileSettings.AmazonS3SSE, 549 "amazon_s3_signv2": *cfg.FileSettings.AmazonS3SignV2, 550 "amazon_s3_trace": *cfg.FileSettings.AmazonS3Trace, 551 "max_file_size": *cfg.FileSettings.MaxFileSize, 552 "enable_file_attachments": *cfg.FileSettings.EnableFileAttachments, 553 "enable_mobile_upload": *cfg.FileSettings.EnableMobileUpload, 554 "enable_mobile_download": *cfg.FileSettings.EnableMobileDownload, 555 }) 556 557 ts.sendTelemetry(TrackConfigEmail, map[string]interface{}{ 558 "enable_sign_up_with_email": cfg.EmailSettings.EnableSignUpWithEmail, 559 "enable_sign_in_with_email": *cfg.EmailSettings.EnableSignInWithEmail, 560 "enable_sign_in_with_username": *cfg.EmailSettings.EnableSignInWithUsername, 561 "require_email_verification": cfg.EmailSettings.RequireEmailVerification, 562 "send_email_notifications": cfg.EmailSettings.SendEmailNotifications, 563 "use_channel_in_email_notifications": *cfg.EmailSettings.UseChannelInEmailNotifications, 564 "email_notification_contents_type": *cfg.EmailSettings.EmailNotificationContentsType, 565 "enable_smtp_auth": *cfg.EmailSettings.EnableSMTPAuth, 566 "connection_security": cfg.EmailSettings.ConnectionSecurity, 567 "send_push_notifications": *cfg.EmailSettings.SendPushNotifications, 568 "push_notification_contents": *cfg.EmailSettings.PushNotificationContents, 569 "enable_email_batching": *cfg.EmailSettings.EnableEmailBatching, 570 "email_batching_buffer_size": *cfg.EmailSettings.EmailBatchingBufferSize, 571 "email_batching_interval": *cfg.EmailSettings.EmailBatchingInterval, 572 "enable_preview_mode_banner": *cfg.EmailSettings.EnablePreviewModeBanner, 573 "isdefault_feedback_name": isDefault(cfg.EmailSettings.FeedbackName, ""), 574 "isdefault_feedback_email": isDefault(cfg.EmailSettings.FeedbackEmail, ""), 575 "isdefault_reply_to_address": isDefault(cfg.EmailSettings.ReplyToAddress, ""), 576 "isdefault_feedback_organization": isDefault(*cfg.EmailSettings.FeedbackOrganization, model.EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION), 577 "skip_server_certificate_verification": *cfg.EmailSettings.SkipServerCertificateVerification, 578 "isdefault_login_button_color": isDefault(*cfg.EmailSettings.LoginButtonColor, ""), 579 "isdefault_login_button_border_color": isDefault(*cfg.EmailSettings.LoginButtonBorderColor, ""), 580 "isdefault_login_button_text_color": isDefault(*cfg.EmailSettings.LoginButtonTextColor, ""), 581 "smtp_server_timeout": *cfg.EmailSettings.SMTPServerTimeout, 582 }) 583 584 ts.sendTelemetry(TrackConfigRate, map[string]interface{}{ 585 "enable_rate_limiter": *cfg.RateLimitSettings.Enable, 586 "vary_by_remote_address": *cfg.RateLimitSettings.VaryByRemoteAddr, 587 "vary_by_user": *cfg.RateLimitSettings.VaryByUser, 588 "per_sec": *cfg.RateLimitSettings.PerSec, 589 "max_burst": *cfg.RateLimitSettings.MaxBurst, 590 "memory_store_size": *cfg.RateLimitSettings.MemoryStoreSize, 591 "isdefault_vary_by_header": isDefault(cfg.RateLimitSettings.VaryByHeader, ""), 592 }) 593 594 ts.sendTelemetry(TrackConfigPrivacy, map[string]interface{}{ 595 "show_email_address": cfg.PrivacySettings.ShowEmailAddress, 596 "show_full_name": cfg.PrivacySettings.ShowFullName, 597 }) 598 599 ts.sendTelemetry(TrackConfigTheme, map[string]interface{}{ 600 "enable_theme_selection": *cfg.ThemeSettings.EnableThemeSelection, 601 "isdefault_default_theme": isDefault(*cfg.ThemeSettings.DefaultTheme, model.TEAM_SETTINGS_DEFAULT_TEAM_TEXT), 602 "allow_custom_themes": *cfg.ThemeSettings.AllowCustomThemes, 603 "allowed_themes": len(cfg.ThemeSettings.AllowedThemes), 604 }) 605 606 ts.sendTelemetry(TrackConfigOauth, map[string]interface{}{ 607 "enable_gitlab": cfg.GitLabSettings.Enable, 608 "openid_gitlab": *cfg.GitLabSettings.Enable && strings.Contains(*cfg.GitLabSettings.Scope, model.SERVICE_OPENID), 609 "enable_google": cfg.GoogleSettings.Enable, 610 "openid_google": *cfg.GoogleSettings.Enable && strings.Contains(*cfg.GoogleSettings.Scope, model.SERVICE_OPENID), 611 "enable_office365": cfg.Office365Settings.Enable, 612 "openid_office365": *cfg.Office365Settings.Enable && strings.Contains(*cfg.Office365Settings.Scope, model.SERVICE_OPENID), 613 "enable_openid": cfg.OpenIdSettings.Enable, 614 }) 615 616 ts.sendTelemetry(TrackConfigSupport, map[string]interface{}{ 617 "isdefault_terms_of_service_link": isDefault(*cfg.SupportSettings.TermsOfServiceLink, model.SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK), 618 "isdefault_privacy_policy_link": isDefault(*cfg.SupportSettings.PrivacyPolicyLink, model.SUPPORT_SETTINGS_DEFAULT_PRIVACY_POLICY_LINK), 619 "isdefault_about_link": isDefault(*cfg.SupportSettings.AboutLink, model.SUPPORT_SETTINGS_DEFAULT_ABOUT_LINK), 620 "isdefault_help_link": isDefault(*cfg.SupportSettings.HelpLink, model.SUPPORT_SETTINGS_DEFAULT_HELP_LINK), 621 "isdefault_report_a_problem_link": isDefault(*cfg.SupportSettings.ReportAProblemLink, model.SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK), 622 "isdefault_support_email": isDefault(*cfg.SupportSettings.SupportEmail, model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL), 623 "custom_terms_of_service_enabled": *cfg.SupportSettings.CustomTermsOfServiceEnabled, 624 "custom_terms_of_service_re_acceptance_period": *cfg.SupportSettings.CustomTermsOfServiceReAcceptancePeriod, 625 "enable_ask_community_link": *cfg.SupportSettings.EnableAskCommunityLink, 626 }) 627 628 ts.sendTelemetry(TrackConfigLDAP, map[string]interface{}{ 629 "enable": *cfg.LdapSettings.Enable, 630 "enable_sync": *cfg.LdapSettings.EnableSync, 631 "enable_admin_filter": *cfg.LdapSettings.EnableAdminFilter, 632 "connection_security": *cfg.LdapSettings.ConnectionSecurity, 633 "skip_certificate_verification": *cfg.LdapSettings.SkipCertificateVerification, 634 "sync_interval_minutes": *cfg.LdapSettings.SyncIntervalMinutes, 635 "query_timeout": *cfg.LdapSettings.QueryTimeout, 636 "max_page_size": *cfg.LdapSettings.MaxPageSize, 637 "isdefault_first_name_attribute": isDefault(*cfg.LdapSettings.FirstNameAttribute, model.LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE), 638 "isdefault_last_name_attribute": isDefault(*cfg.LdapSettings.LastNameAttribute, model.LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE), 639 "isdefault_email_attribute": isDefault(*cfg.LdapSettings.EmailAttribute, model.LDAP_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE), 640 "isdefault_username_attribute": isDefault(*cfg.LdapSettings.UsernameAttribute, model.LDAP_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE), 641 "isdefault_nickname_attribute": isDefault(*cfg.LdapSettings.NicknameAttribute, model.LDAP_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE), 642 "isdefault_id_attribute": isDefault(*cfg.LdapSettings.IdAttribute, model.LDAP_SETTINGS_DEFAULT_ID_ATTRIBUTE), 643 "isdefault_position_attribute": isDefault(*cfg.LdapSettings.PositionAttribute, model.LDAP_SETTINGS_DEFAULT_POSITION_ATTRIBUTE), 644 "isdefault_login_id_attribute": isDefault(*cfg.LdapSettings.LoginIdAttribute, ""), 645 "isdefault_login_field_name": isDefault(*cfg.LdapSettings.LoginFieldName, model.LDAP_SETTINGS_DEFAULT_LOGIN_FIELD_NAME), 646 "isdefault_login_button_color": isDefault(*cfg.LdapSettings.LoginButtonColor, ""), 647 "isdefault_login_button_border_color": isDefault(*cfg.LdapSettings.LoginButtonBorderColor, ""), 648 "isdefault_login_button_text_color": isDefault(*cfg.LdapSettings.LoginButtonTextColor, ""), 649 "isempty_group_filter": isDefault(*cfg.LdapSettings.GroupFilter, ""), 650 "isdefault_group_display_name_attribute": isDefault(*cfg.LdapSettings.GroupDisplayNameAttribute, model.LDAP_SETTINGS_DEFAULT_GROUP_DISPLAY_NAME_ATTRIBUTE), 651 "isdefault_group_id_attribute": isDefault(*cfg.LdapSettings.GroupIdAttribute, model.LDAP_SETTINGS_DEFAULT_GROUP_ID_ATTRIBUTE), 652 "isempty_guest_filter": isDefault(*cfg.LdapSettings.GuestFilter, ""), 653 "isempty_admin_filter": isDefault(*cfg.LdapSettings.AdminFilter, ""), 654 "isnotempty_picture_attribute": !isDefault(*cfg.LdapSettings.PictureAttribute, ""), 655 "isnotempty_public_certificate": !isDefault(*cfg.LdapSettings.PublicCertificateFile, ""), 656 "isnotempty_private_key": !isDefault(*cfg.LdapSettings.PrivateKeyFile, ""), 657 }) 658 659 ts.sendTelemetry(TrackConfigCompliance, map[string]interface{}{ 660 "enable": *cfg.ComplianceSettings.Enable, 661 "enable_daily": *cfg.ComplianceSettings.EnableDaily, 662 }) 663 664 ts.sendTelemetry(TrackConfigLocalization, map[string]interface{}{ 665 "default_server_locale": *cfg.LocalizationSettings.DefaultServerLocale, 666 "default_client_locale": *cfg.LocalizationSettings.DefaultClientLocale, 667 "available_locales": *cfg.LocalizationSettings.AvailableLocales, 668 }) 669 670 ts.sendTelemetry(TrackConfigSAML, map[string]interface{}{ 671 "enable": *cfg.SamlSettings.Enable, 672 "enable_sync_with_ldap": *cfg.SamlSettings.EnableSyncWithLdap, 673 "enable_sync_with_ldap_include_auth": *cfg.SamlSettings.EnableSyncWithLdapIncludeAuth, 674 "ignore_guests_ldap_sync": *cfg.SamlSettings.IgnoreGuestsLdapSync, 675 "enable_admin_attribute": *cfg.SamlSettings.EnableAdminAttribute, 676 "verify": *cfg.SamlSettings.Verify, 677 "encrypt": *cfg.SamlSettings.Encrypt, 678 "sign_request": *cfg.SamlSettings.SignRequest, 679 "isdefault_signature_algorithm": isDefault(*cfg.SamlSettings.SignatureAlgorithm, ""), 680 "isdefault_canonical_algorithm": isDefault(*cfg.SamlSettings.CanonicalAlgorithm, ""), 681 "isdefault_scoping_idp_provider_id": isDefault(*cfg.SamlSettings.ScopingIDPProviderId, ""), 682 "isdefault_scoping_idp_name": isDefault(*cfg.SamlSettings.ScopingIDPName, ""), 683 "isdefault_id_attribute": isDefault(*cfg.SamlSettings.IdAttribute, model.SAML_SETTINGS_DEFAULT_ID_ATTRIBUTE), 684 "isdefault_guest_attribute": isDefault(*cfg.SamlSettings.GuestAttribute, model.SAML_SETTINGS_DEFAULT_GUEST_ATTRIBUTE), 685 "isdefault_admin_attribute": isDefault(*cfg.SamlSettings.AdminAttribute, model.SAML_SETTINGS_DEFAULT_ADMIN_ATTRIBUTE), 686 "isdefault_first_name_attribute": isDefault(*cfg.SamlSettings.FirstNameAttribute, model.SAML_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE), 687 "isdefault_last_name_attribute": isDefault(*cfg.SamlSettings.LastNameAttribute, model.SAML_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE), 688 "isdefault_email_attribute": isDefault(*cfg.SamlSettings.EmailAttribute, model.SAML_SETTINGS_DEFAULT_EMAIL_ATTRIBUTE), 689 "isdefault_username_attribute": isDefault(*cfg.SamlSettings.UsernameAttribute, model.SAML_SETTINGS_DEFAULT_USERNAME_ATTRIBUTE), 690 "isdefault_nickname_attribute": isDefault(*cfg.SamlSettings.NicknameAttribute, model.SAML_SETTINGS_DEFAULT_NICKNAME_ATTRIBUTE), 691 "isdefault_locale_attribute": isDefault(*cfg.SamlSettings.LocaleAttribute, model.SAML_SETTINGS_DEFAULT_LOCALE_ATTRIBUTE), 692 "isdefault_position_attribute": isDefault(*cfg.SamlSettings.PositionAttribute, model.SAML_SETTINGS_DEFAULT_POSITION_ATTRIBUTE), 693 "isdefault_login_button_text": isDefault(*cfg.SamlSettings.LoginButtonText, model.USER_AUTH_SERVICE_SAML_TEXT), 694 "isdefault_login_button_color": isDefault(*cfg.SamlSettings.LoginButtonColor, ""), 695 "isdefault_login_button_border_color": isDefault(*cfg.SamlSettings.LoginButtonBorderColor, ""), 696 "isdefault_login_button_text_color": isDefault(*cfg.SamlSettings.LoginButtonTextColor, ""), 697 }) 698 699 ts.sendTelemetry(TrackConfigCluster, map[string]interface{}{ 700 "enable": *cfg.ClusterSettings.Enable, 701 "network_interface": isDefault(*cfg.ClusterSettings.NetworkInterface, ""), 702 "bind_address": isDefault(*cfg.ClusterSettings.BindAddress, ""), 703 "advertise_address": isDefault(*cfg.ClusterSettings.AdvertiseAddress, ""), 704 "use_ip_address": *cfg.ClusterSettings.UseIpAddress, 705 "use_experimental_gossip": *cfg.ClusterSettings.UseExperimentalGossip, 706 "enable_experimental_gossip_encryption": *cfg.ClusterSettings.EnableExperimentalGossipEncryption, 707 "enable_gossip_compression": *cfg.ClusterSettings.EnableGossipCompression, 708 "read_only_config": *cfg.ClusterSettings.ReadOnlyConfig, 709 }) 710 711 ts.sendTelemetry(TrackConfigMetrics, map[string]interface{}{ 712 "enable": *cfg.MetricsSettings.Enable, 713 "block_profile_rate": *cfg.MetricsSettings.BlockProfileRate, 714 }) 715 716 ts.sendTelemetry(TrackConfigNativeApp, map[string]interface{}{ 717 "isdefault_app_custom_url_schemes": isDefaultArray(cfg.NativeAppSettings.AppCustomURLSchemes, model.GetDefaultAppCustomURLSchemes()), 718 "isdefault_app_download_link": isDefault(*cfg.NativeAppSettings.AppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_APP_DOWNLOAD_LINK), 719 "isdefault_android_app_download_link": isDefault(*cfg.NativeAppSettings.AndroidAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_ANDROID_APP_DOWNLOAD_LINK), 720 "isdefault_iosapp_download_link": isDefault(*cfg.NativeAppSettings.IosAppDownloadLink, model.NATIVEAPP_SETTINGS_DEFAULT_IOS_APP_DOWNLOAD_LINK), 721 }) 722 723 ts.sendTelemetry(TrackConfigExperimental, map[string]interface{}{ 724 "client_side_cert_enable": *cfg.ExperimentalSettings.ClientSideCertEnable, 725 "isdefault_client_side_cert_check": isDefault(*cfg.ExperimentalSettings.ClientSideCertCheck, model.CLIENT_SIDE_CERT_CHECK_PRIMARY_AUTH), 726 "link_metadata_timeout_milliseconds": *cfg.ExperimentalSettings.LinkMetadataTimeoutMilliseconds, 727 "enable_click_to_reply": *cfg.ExperimentalSettings.EnableClickToReply, 728 "restrict_system_admin": *cfg.ExperimentalSettings.RestrictSystemAdmin, 729 "use_new_saml_library": *cfg.ExperimentalSettings.UseNewSAMLLibrary, 730 "cloud_billing": *cfg.ExperimentalSettings.CloudBilling, 731 "cloud_user_limit": *cfg.ExperimentalSettings.CloudUserLimit, 732 "enable_shared_channels": *cfg.ExperimentalSettings.EnableSharedChannels, 733 }) 734 735 ts.sendTelemetry(TrackConfigAnalytics, map[string]interface{}{ 736 "isdefault_max_users_for_statistics": isDefault(*cfg.AnalyticsSettings.MaxUsersForStatistics, model.ANALYTICS_SETTINGS_DEFAULT_MAX_USERS_FOR_STATISTICS), 737 }) 738 739 ts.sendTelemetry(TrackConfigAnnouncement, map[string]interface{}{ 740 "enable_banner": *cfg.AnnouncementSettings.EnableBanner, 741 "isdefault_banner_color": isDefault(*cfg.AnnouncementSettings.BannerColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_COLOR), 742 "isdefault_banner_text_color": isDefault(*cfg.AnnouncementSettings.BannerTextColor, model.ANNOUNCEMENT_SETTINGS_DEFAULT_BANNER_TEXT_COLOR), 743 "allow_banner_dismissal": *cfg.AnnouncementSettings.AllowBannerDismissal, 744 "admin_notices_enabled": *cfg.AnnouncementSettings.AdminNoticesEnabled, 745 "user_notices_enabled": *cfg.AnnouncementSettings.UserNoticesEnabled, 746 }) 747 748 ts.sendTelemetry(TrackConfigElasticsearch, map[string]interface{}{ 749 "isdefault_connection_url": isDefault(*cfg.ElasticsearchSettings.ConnectionUrl, model.ELASTICSEARCH_SETTINGS_DEFAULT_CONNECTION_URL), 750 "isdefault_username": isDefault(*cfg.ElasticsearchSettings.Username, model.ELASTICSEARCH_SETTINGS_DEFAULT_USERNAME), 751 "isdefault_password": isDefault(*cfg.ElasticsearchSettings.Password, model.ELASTICSEARCH_SETTINGS_DEFAULT_PASSWORD), 752 "enable_indexing": *cfg.ElasticsearchSettings.EnableIndexing, 753 "enable_searching": *cfg.ElasticsearchSettings.EnableSearching, 754 "enable_autocomplete": *cfg.ElasticsearchSettings.EnableAutocomplete, 755 "sniff": *cfg.ElasticsearchSettings.Sniff, 756 "post_index_replicas": *cfg.ElasticsearchSettings.PostIndexReplicas, 757 "post_index_shards": *cfg.ElasticsearchSettings.PostIndexShards, 758 "channel_index_replicas": *cfg.ElasticsearchSettings.ChannelIndexReplicas, 759 "channel_index_shards": *cfg.ElasticsearchSettings.ChannelIndexShards, 760 "user_index_replicas": *cfg.ElasticsearchSettings.UserIndexReplicas, 761 "user_index_shards": *cfg.ElasticsearchSettings.UserIndexShards, 762 "isdefault_index_prefix": isDefault(*cfg.ElasticsearchSettings.IndexPrefix, model.ELASTICSEARCH_SETTINGS_DEFAULT_INDEX_PREFIX), 763 "live_indexing_batch_size": *cfg.ElasticsearchSettings.LiveIndexingBatchSize, 764 "bulk_indexing_time_window_seconds": *cfg.ElasticsearchSettings.BulkIndexingTimeWindowSeconds, 765 "request_timeout_seconds": *cfg.ElasticsearchSettings.RequestTimeoutSeconds, 766 "skip_tls_verification": *cfg.ElasticsearchSettings.SkipTLSVerification, 767 "trace": *cfg.ElasticsearchSettings.Trace, 768 }) 769 770 ts.trackPluginConfig(cfg, model.PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL) 771 772 ts.sendTelemetry(TrackConfigDataRetention, map[string]interface{}{ 773 "enable_message_deletion": *cfg.DataRetentionSettings.EnableMessageDeletion, 774 "enable_file_deletion": *cfg.DataRetentionSettings.EnableFileDeletion, 775 "message_retention_days": *cfg.DataRetentionSettings.MessageRetentionDays, 776 "file_retention_days": *cfg.DataRetentionSettings.FileRetentionDays, 777 "deletion_job_start_time": *cfg.DataRetentionSettings.DeletionJobStartTime, 778 }) 779 780 ts.sendTelemetry(TrackConfigMessageExport, map[string]interface{}{ 781 "enable_message_export": *cfg.MessageExportSettings.EnableExport, 782 "export_format": *cfg.MessageExportSettings.ExportFormat, 783 "daily_run_time": *cfg.MessageExportSettings.DailyRunTime, 784 "default_export_from_timestamp": *cfg.MessageExportSettings.ExportFromTimestamp, 785 "batch_size": *cfg.MessageExportSettings.BatchSize, 786 "global_relay_customer_type": *cfg.MessageExportSettings.GlobalRelaySettings.CustomerType, 787 "is_default_global_relay_smtp_username": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpUsername, ""), 788 "is_default_global_relay_smtp_password": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpPassword, ""), 789 "is_default_global_relay_email_address": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.EmailAddress, ""), 790 "global_relay_smtp_server_timeout": *cfg.MessageExportSettings.GlobalRelaySettings.SMTPServerTimeout, 791 "download_export_results": *cfg.MessageExportSettings.DownloadExportResults, 792 }) 793 794 ts.sendTelemetry(TrackConfigDisplay, map[string]interface{}{ 795 "experimental_timezone": *cfg.DisplaySettings.ExperimentalTimezone, 796 "isdefault_custom_url_schemes": len(cfg.DisplaySettings.CustomUrlSchemes) != 0, 797 }) 798 799 ts.sendTelemetry(TrackConfigGuestAccounts, map[string]interface{}{ 800 "enable": *cfg.GuestAccountsSettings.Enable, 801 "allow_email_accounts": *cfg.GuestAccountsSettings.AllowEmailAccounts, 802 "enforce_multifactor_authentication": *cfg.GuestAccountsSettings.EnforceMultifactorAuthentication, 803 "isdefault_restrict_creation_to_domains": isDefault(*cfg.GuestAccountsSettings.RestrictCreationToDomains, ""), 804 }) 805 806 ts.sendTelemetry(TrackConfigImageProxy, map[string]interface{}{ 807 "enable": *cfg.ImageProxySettings.Enable, 808 "image_proxy_type": *cfg.ImageProxySettings.ImageProxyType, 809 "isdefault_remote_image_proxy_url": isDefault(*cfg.ImageProxySettings.RemoteImageProxyURL, ""), 810 "isdefault_remote_image_proxy_options": isDefault(*cfg.ImageProxySettings.RemoteImageProxyOptions, ""), 811 }) 812 813 ts.sendTelemetry(TrackConfigBleve, map[string]interface{}{ 814 "enable_indexing": *cfg.BleveSettings.EnableIndexing, 815 "enable_searching": *cfg.BleveSettings.EnableSearching, 816 "enable_autocomplete": *cfg.BleveSettings.EnableAutocomplete, 817 "bulk_indexing_time_window_seconds": *cfg.BleveSettings.BulkIndexingTimeWindowSeconds, 818 }) 819 820 ts.sendTelemetry(TrackConfigExport, map[string]interface{}{ 821 "retention_days": *cfg.ExportSettings.RetentionDays, 822 }) 823 } 824 825 func (ts *TelemetryService) trackLicense() { 826 if license := ts.srv.License(); license != nil { 827 data := map[string]interface{}{ 828 "customer_id": license.Customer.Id, 829 "license_id": license.Id, 830 "issued": license.IssuedAt, 831 "start": license.StartsAt, 832 "expire": license.ExpiresAt, 833 "users": *license.Features.Users, 834 "edition": license.SkuShortName, 835 } 836 837 features := license.Features.ToMap() 838 for featureName, featureValue := range features { 839 data["feature_"+featureName] = featureValue 840 } 841 842 ts.sendTelemetry(TrackLicense, data) 843 } 844 } 845 846 func (ts *TelemetryService) trackPlugins() { 847 pluginsEnvironment := ts.srv.GetPluginsEnvironment() 848 if pluginsEnvironment == nil { 849 return 850 } 851 852 totalEnabledCount := 0 853 webappEnabledCount := 0 854 backendEnabledCount := 0 855 totalDisabledCount := 0 856 webappDisabledCount := 0 857 backendDisabledCount := 0 858 brokenManifestCount := 0 859 settingsCount := 0 860 861 pluginStates := ts.srv.Config().PluginSettings.PluginStates 862 plugins, _ := pluginsEnvironment.Available() 863 864 if pluginStates != nil && plugins != nil { 865 for _, plugin := range plugins { 866 if plugin.Manifest == nil { 867 brokenManifestCount += 1 868 continue 869 } 870 871 if state, ok := pluginStates[plugin.Manifest.Id]; ok && state.Enable { 872 totalEnabledCount += 1 873 if plugin.Manifest.HasServer() { 874 backendEnabledCount += 1 875 } 876 if plugin.Manifest.HasWebapp() { 877 webappEnabledCount += 1 878 } 879 } else { 880 totalDisabledCount += 1 881 if plugin.Manifest.HasServer() { 882 backendDisabledCount += 1 883 } 884 if plugin.Manifest.HasWebapp() { 885 webappDisabledCount += 1 886 } 887 } 888 if plugin.Manifest.SettingsSchema != nil { 889 settingsCount += 1 890 } 891 } 892 } else { 893 totalEnabledCount = -1 // -1 to indicate disabled or error 894 totalDisabledCount = -1 // -1 to indicate disabled or error 895 } 896 897 ts.sendTelemetry(TrackPlugins, map[string]interface{}{ 898 "enabled_plugins": totalEnabledCount, 899 "enabled_webapp_plugins": webappEnabledCount, 900 "enabled_backend_plugins": backendEnabledCount, 901 "disabled_plugins": totalDisabledCount, 902 "disabled_webapp_plugins": webappDisabledCount, 903 "disabled_backend_plugins": backendDisabledCount, 904 "plugins_with_settings": settingsCount, 905 "plugins_with_broken_manifests": brokenManifestCount, 906 }) 907 } 908 909 func (ts *TelemetryService) trackServer() { 910 data := map[string]interface{}{ 911 "edition": model.BuildEnterpriseReady, 912 "version": model.CurrentVersion, 913 "database_type": *ts.srv.Config().SqlSettings.DriverName, 914 "operating_system": runtime.GOOS, 915 "installation_type": os.Getenv(EnvVarInstallType), 916 } 917 918 if scr, err := ts.dbStore.User().AnalyticsGetSystemAdminCount(); err == nil { 919 data["system_admins"] = scr 920 } 921 922 if scr, err := ts.dbStore.GetDbVersion(false); err == nil { 923 data["database_version"] = scr 924 } 925 926 ts.sendTelemetry(TrackServer, data) 927 } 928 929 func (ts *TelemetryService) trackPermissions() { 930 phase1Complete := false 931 if _, err := ts.dbStore.System().GetByName(model.ADVANCED_PERMISSIONS_MIGRATION_KEY); err == nil { 932 phase1Complete = true 933 } 934 935 phase2Complete := false 936 if _, err := ts.dbStore.System().GetByName(model.MIGRATION_KEY_ADVANCED_PERMISSIONS_PHASE_2); err == nil { 937 phase2Complete = true 938 } 939 940 ts.sendTelemetry(TrackPermissionsGeneral, map[string]interface{}{ 941 "phase_1_migration_complete": phase1Complete, 942 "phase_2_migration_complete": phase2Complete, 943 }) 944 945 systemAdminPermissions := "" 946 if role, err := ts.srv.GetRoleByName(model.SYSTEM_ADMIN_ROLE_ID); err == nil { 947 systemAdminPermissions = strings.Join(role.Permissions, " ") 948 } 949 950 systemUserPermissions := "" 951 if role, err := ts.srv.GetRoleByName(model.SYSTEM_USER_ROLE_ID); err == nil { 952 systemUserPermissions = strings.Join(role.Permissions, " ") 953 } 954 955 teamAdminPermissions := "" 956 if role, err := ts.srv.GetRoleByName(model.TEAM_ADMIN_ROLE_ID); err == nil { 957 teamAdminPermissions = strings.Join(role.Permissions, " ") 958 } 959 960 teamUserPermissions := "" 961 if role, err := ts.srv.GetRoleByName(model.TEAM_USER_ROLE_ID); err == nil { 962 teamUserPermissions = strings.Join(role.Permissions, " ") 963 } 964 965 teamGuestPermissions := "" 966 if role, err := ts.srv.GetRoleByName(model.TEAM_GUEST_ROLE_ID); err == nil { 967 teamGuestPermissions = strings.Join(role.Permissions, " ") 968 } 969 970 channelAdminPermissions := "" 971 if role, err := ts.srv.GetRoleByName(model.CHANNEL_ADMIN_ROLE_ID); err == nil { 972 channelAdminPermissions = strings.Join(role.Permissions, " ") 973 } 974 975 channelUserPermissions := "" 976 if role, err := ts.srv.GetRoleByName(model.CHANNEL_USER_ROLE_ID); err == nil { 977 channelUserPermissions = strings.Join(role.Permissions, " ") 978 } 979 980 channelGuestPermissions := "" 981 if role, err := ts.srv.GetRoleByName(model.CHANNEL_GUEST_ROLE_ID); err == nil { 982 channelGuestPermissions = strings.Join(role.Permissions, " ") 983 } 984 985 systemManagerPermissions := "" 986 systemManagerPermissionsModified := false 987 if role, err := ts.srv.GetRoleByName(model.SYSTEM_MANAGER_ROLE_ID); err == nil { 988 systemManagerPermissionsModified = len(model.PermissionsChangedByPatch(role, &model.RolePatch{Permissions: &model.SystemManagerDefaultPermissions})) > 0 989 systemManagerPermissions = strings.Join(role.Permissions, " ") 990 } 991 systemManagerCount, countErr := ts.dbStore.User().Count(model.UserCountOptions{Roles: []string{model.SYSTEM_MANAGER_ROLE_ID}}) 992 if countErr != nil { 993 systemManagerCount = 0 994 } 995 996 systemUserManagerPermissions := "" 997 systemUserManagerPermissionsModified := false 998 if role, err := ts.srv.GetRoleByName(model.SYSTEM_USER_MANAGER_ROLE_ID); err == nil { 999 systemUserManagerPermissionsModified = len(model.PermissionsChangedByPatch(role, &model.RolePatch{Permissions: &model.SystemUserManagerDefaultPermissions})) > 0 1000 systemUserManagerPermissions = strings.Join(role.Permissions, " ") 1001 } 1002 systemUserManagerCount, countErr := ts.dbStore.User().Count(model.UserCountOptions{Roles: []string{model.SYSTEM_USER_MANAGER_ROLE_ID}}) 1003 if countErr != nil { 1004 systemManagerCount = 0 1005 } 1006 1007 systemReadOnlyAdminPermissions := "" 1008 systemReadOnlyAdminPermissionsModified := false 1009 if role, err := ts.srv.GetRoleByName(model.SYSTEM_READ_ONLY_ADMIN_ROLE_ID); err == nil { 1010 systemReadOnlyAdminPermissionsModified = len(model.PermissionsChangedByPatch(role, &model.RolePatch{Permissions: &model.SystemReadOnlyAdminDefaultPermissions})) > 0 1011 systemReadOnlyAdminPermissions = strings.Join(role.Permissions, " ") 1012 } 1013 systemReadOnlyAdminCount, countErr := ts.dbStore.User().Count(model.UserCountOptions{Roles: []string{model.SYSTEM_READ_ONLY_ADMIN_ROLE_ID}}) 1014 if countErr != nil { 1015 systemReadOnlyAdminCount = 0 1016 } 1017 1018 ts.sendTelemetry(TrackPermissionsSystemScheme, map[string]interface{}{ 1019 "system_admin_permissions": systemAdminPermissions, 1020 "system_user_permissions": systemUserPermissions, 1021 "system_manager_permissions": systemManagerPermissions, 1022 "system_user_manager_permissions": systemUserManagerPermissions, 1023 "system_read_only_admin_permissions": systemReadOnlyAdminPermissions, 1024 "team_admin_permissions": teamAdminPermissions, 1025 "team_user_permissions": teamUserPermissions, 1026 "team_guest_permissions": teamGuestPermissions, 1027 "channel_admin_permissions": channelAdminPermissions, 1028 "channel_user_permissions": channelUserPermissions, 1029 "channel_guest_permissions": channelGuestPermissions, 1030 "system_manager_permissions_modified": systemManagerPermissionsModified, 1031 "system_manager_count": systemManagerCount, 1032 "system_user_manager_permissions_modified": systemUserManagerPermissionsModified, 1033 "system_user_manager_count": systemUserManagerCount, 1034 "system_read_only_admin_permissions_modified": systemReadOnlyAdminPermissionsModified, 1035 "system_read_only_admin_count": systemReadOnlyAdminCount, 1036 }) 1037 1038 if schemes, err := ts.srv.GetSchemes(model.SCHEME_SCOPE_TEAM, 0, 100); err == nil { 1039 for _, scheme := range schemes { 1040 teamAdminPermissions := "" 1041 if role, err := ts.srv.GetRoleByName(scheme.DefaultTeamAdminRole); err == nil { 1042 teamAdminPermissions = strings.Join(role.Permissions, " ") 1043 } 1044 1045 teamUserPermissions := "" 1046 if role, err := ts.srv.GetRoleByName(scheme.DefaultTeamUserRole); err == nil { 1047 teamUserPermissions = strings.Join(role.Permissions, " ") 1048 } 1049 1050 teamGuestPermissions := "" 1051 if role, err := ts.srv.GetRoleByName(scheme.DefaultTeamGuestRole); err == nil { 1052 teamGuestPermissions = strings.Join(role.Permissions, " ") 1053 } 1054 1055 channelAdminPermissions := "" 1056 if role, err := ts.srv.GetRoleByName(scheme.DefaultChannelAdminRole); err == nil { 1057 channelAdminPermissions = strings.Join(role.Permissions, " ") 1058 } 1059 1060 channelUserPermissions := "" 1061 if role, err := ts.srv.GetRoleByName(scheme.DefaultChannelUserRole); err == nil { 1062 channelUserPermissions = strings.Join(role.Permissions, " ") 1063 } 1064 1065 channelGuestPermissions := "" 1066 if role, err := ts.srv.GetRoleByName(scheme.DefaultChannelGuestRole); err == nil { 1067 channelGuestPermissions = strings.Join(role.Permissions, " ") 1068 } 1069 1070 count, _ := ts.dbStore.Team().AnalyticsGetTeamCountForScheme(scheme.Id) 1071 1072 ts.sendTelemetry(TrackPermissionsTeamSchemes, map[string]interface{}{ 1073 "scheme_id": scheme.Id, 1074 "team_admin_permissions": teamAdminPermissions, 1075 "team_user_permissions": teamUserPermissions, 1076 "team_guest_permissions": teamGuestPermissions, 1077 "channel_admin_permissions": channelAdminPermissions, 1078 "channel_user_permissions": channelUserPermissions, 1079 "channel_guest_permissions": channelGuestPermissions, 1080 "team_count": count, 1081 }) 1082 } 1083 } 1084 } 1085 1086 func (ts *TelemetryService) trackElasticsearch() { 1087 data := map[string]interface{}{} 1088 1089 for _, engine := range ts.searchEngine.GetActiveEngines() { 1090 if engine.GetVersion() != 0 && engine.GetName() == "elasticsearch" { 1091 data["elasticsearch_server_version"] = engine.GetVersion() 1092 } 1093 } 1094 1095 ts.sendTelemetry(TrackElasticsearch, data) 1096 } 1097 1098 func (ts *TelemetryService) trackGroups() { 1099 groupCount, err := ts.dbStore.Group().GroupCount() 1100 if err != nil { 1101 mlog.Debug("Could not get group_count", mlog.Err(err)) 1102 } 1103 1104 groupTeamCount, err := ts.dbStore.Group().GroupTeamCount() 1105 if err != nil { 1106 mlog.Debug("Could not get group_team_count", mlog.Err(err)) 1107 } 1108 1109 groupChannelCount, err := ts.dbStore.Group().GroupChannelCount() 1110 if err != nil { 1111 mlog.Debug("Could not get group_channel_count", mlog.Err(err)) 1112 } 1113 1114 groupSyncedTeamCount, nErr := ts.dbStore.Team().GroupSyncedTeamCount() 1115 if nErr != nil { 1116 mlog.Debug("Could not get group_synced_team_count", mlog.Err(nErr)) 1117 } 1118 1119 groupSyncedChannelCount, nErr := ts.dbStore.Channel().GroupSyncedChannelCount() 1120 if nErr != nil { 1121 mlog.Debug("Could not get group_synced_channel_count", mlog.Err(nErr)) 1122 } 1123 1124 groupMemberCount, err := ts.dbStore.Group().GroupMemberCount() 1125 if err != nil { 1126 mlog.Debug("Could not get group_member_count", mlog.Err(err)) 1127 } 1128 1129 distinctGroupMemberCount, err := ts.dbStore.Group().DistinctGroupMemberCount() 1130 if err != nil { 1131 mlog.Debug("Could not get distinct_group_member_count", mlog.Err(err)) 1132 } 1133 1134 groupCountWithAllowReference, err := ts.dbStore.Group().GroupCountWithAllowReference() 1135 if err != nil { 1136 mlog.Debug("Could not get group_count_with_allow_reference", mlog.Err(err)) 1137 } 1138 1139 ts.sendTelemetry(TrackGroups, map[string]interface{}{ 1140 "group_count": groupCount, 1141 "group_team_count": groupTeamCount, 1142 "group_channel_count": groupChannelCount, 1143 "group_synced_team_count": groupSyncedTeamCount, 1144 "group_synced_channel_count": groupSyncedChannelCount, 1145 "group_member_count": groupMemberCount, 1146 "distinct_group_member_count": distinctGroupMemberCount, 1147 "group_count_with_allow_reference": groupCountWithAllowReference, 1148 }) 1149 } 1150 1151 func (ts *TelemetryService) trackChannelModeration() { 1152 channelSchemeCount, err := ts.dbStore.Scheme().CountByScope(model.SCHEME_SCOPE_CHANNEL) 1153 if err != nil { 1154 mlog.Debug("Could not get channel_scheme_count", mlog.Err(err)) 1155 } 1156 1157 createPostUser, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_CREATE_POST.Id, model.RoleScopeChannel, model.RoleTypeUser) 1158 if err != nil { 1159 mlog.Debug("Could not get create_post_user_disabled_count", mlog.Err(err)) 1160 } 1161 1162 createPostGuest, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_CREATE_POST.Id, model.RoleScopeChannel, model.RoleTypeGuest) 1163 if err != nil { 1164 mlog.Debug("Could not get create_post_guest_disabled_count", mlog.Err(err)) 1165 } 1166 1167 // only need to track one of 'add_reaction' or 'remove_reaction` because they're both toggled together by the channel moderation feature 1168 postReactionsUser, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_ADD_REACTION.Id, model.RoleScopeChannel, model.RoleTypeUser) 1169 if err != nil { 1170 mlog.Debug("Could not get post_reactions_user_disabled_count", mlog.Err(err)) 1171 } 1172 1173 postReactionsGuest, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_ADD_REACTION.Id, model.RoleScopeChannel, model.RoleTypeGuest) 1174 if err != nil { 1175 mlog.Debug("Could not get post_reactions_guest_disabled_count", mlog.Err(err)) 1176 } 1177 1178 // only need to track one of 'manage_public_channel_members' or 'manage_private_channel_members` because they're both toggled together by the channel moderation feature 1179 manageMembersUser, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id, model.RoleScopeChannel, model.RoleTypeUser) 1180 if err != nil { 1181 mlog.Debug("Could not get manage_members_user_disabled_count", mlog.Err(err)) 1182 } 1183 1184 useChannelMentionsUser, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.RoleScopeChannel, model.RoleTypeUser) 1185 if err != nil { 1186 mlog.Debug("Could not get use_channel_mentions_user_disabled_count", mlog.Err(err)) 1187 } 1188 1189 useChannelMentionsGuest, err := ts.dbStore.Scheme().CountWithoutPermission(model.SCHEME_SCOPE_CHANNEL, model.PERMISSION_USE_CHANNEL_MENTIONS.Id, model.RoleScopeChannel, model.RoleTypeGuest) 1190 if err != nil { 1191 mlog.Debug("Could not get use_channel_mentions_guest_disabled_count", mlog.Err(err)) 1192 } 1193 1194 ts.sendTelemetry(TrackChannelModeration, map[string]interface{}{ 1195 "channel_scheme_count": channelSchemeCount, 1196 1197 "create_post_user_disabled_count": createPostUser, 1198 "create_post_guest_disabled_count": createPostGuest, 1199 1200 "post_reactions_user_disabled_count": postReactionsUser, 1201 "post_reactions_guest_disabled_count": postReactionsGuest, 1202 1203 "manage_members_user_disabled_count": manageMembersUser, // the UI does not allow this to be removed for guests 1204 1205 "use_channel_mentions_user_disabled_count": useChannelMentionsUser, 1206 "use_channel_mentions_guest_disabled_count": useChannelMentionsGuest, 1207 }) 1208 } 1209 1210 func (ts *TelemetryService) initRudder(endpoint string, rudderKey string) { 1211 if ts.rudderClient == nil { 1212 config := rudder.Config{} 1213 config.Logger = rudder.StdLogger(ts.log.StdLog(mlog.String("source", "rudder"))) 1214 config.Endpoint = endpoint 1215 // For testing 1216 if endpoint != RudderDataplaneURL { 1217 config.Verbose = true 1218 config.BatchSize = 1 1219 } 1220 client, err := rudder.NewWithConfig(rudderKey, endpoint, config) 1221 if err != nil { 1222 mlog.Error("Failed to create Rudder instance", mlog.Err(err)) 1223 return 1224 } 1225 client.Enqueue(rudder.Identify{ 1226 UserId: ts.TelemetryID, 1227 }) 1228 1229 ts.rudderClient = client 1230 } 1231 } 1232 1233 func (ts *TelemetryService) doTelemetryIfNeeded(firstRun time.Time) { 1234 hoursSinceFirstServerRun := time.Since(firstRun).Hours() 1235 // Send once every 10 minutes for the first hour 1236 // Send once every hour thereafter for the first 12 hours 1237 // Send at the 24 hour mark and every 24 hours after 1238 if hoursSinceFirstServerRun < 1 { 1239 ts.doTelemetry() 1240 } else if hoursSinceFirstServerRun <= 12 && time.Since(ts.timestampLastTelemetrySent) >= time.Hour { 1241 ts.doTelemetry() 1242 } else if hoursSinceFirstServerRun > 12 && time.Since(ts.timestampLastTelemetrySent) >= 24*time.Hour { 1243 ts.doTelemetry() 1244 } 1245 } 1246 1247 func (ts *TelemetryService) RunTelemetryJob(firstRun int64) { 1248 // Send on boot 1249 ts.doTelemetry() 1250 model.CreateRecurringTask("Telemetry", func() { 1251 ts.doTelemetryIfNeeded(utils.TimeFromMillis(firstRun)) 1252 }, time.Minute*10) 1253 } 1254 1255 func (ts *TelemetryService) doTelemetry() { 1256 if *ts.srv.Config().LogSettings.EnableDiagnostics { 1257 ts.timestampLastTelemetrySent = time.Now() 1258 ts.sendDailyTelemetry(false) 1259 } 1260 } 1261 1262 // Shutdown closes the telemetry client. 1263 func (ts *TelemetryService) Shutdown() error { 1264 if ts.rudderClient != nil { 1265 return ts.rudderClient.Close() 1266 } 1267 return nil 1268 } 1269 1270 func (ts *TelemetryService) trackWarnMetrics() { 1271 systemDataList, nErr := ts.dbStore.System().Get() 1272 if nErr != nil { 1273 return 1274 } 1275 for key, value := range systemDataList { 1276 if strings.HasPrefix(key, model.WARN_METRIC_STATUS_STORE_PREFIX) { 1277 if _, ok := model.WarnMetricsTable[key]; ok { 1278 ts.sendTelemetry(TrackWarnMetrics, map[string]interface{}{ 1279 key: value != "false", 1280 }) 1281 } 1282 } 1283 } 1284 } 1285 1286 func (ts *TelemetryService) trackPluginConfig(cfg *model.Config, marketplaceURL string) { 1287 pluginConfigData := map[string]interface{}{ 1288 "enable_nps_survey": pluginSetting(&cfg.PluginSettings, "com.mattermost.nps", "enablesurvey", true), 1289 "enable": *cfg.PluginSettings.Enable, 1290 "enable_uploads": *cfg.PluginSettings.EnableUploads, 1291 "allow_insecure_download_url": *cfg.PluginSettings.AllowInsecureDownloadUrl, 1292 "enable_health_check": *cfg.PluginSettings.EnableHealthCheck, 1293 "enable_marketplace": *cfg.PluginSettings.EnableMarketplace, 1294 "require_pluginSignature": *cfg.PluginSettings.RequirePluginSignature, 1295 "enable_remote_marketplace": *cfg.PluginSettings.EnableRemoteMarketplace, 1296 "automatic_prepackaged_plugins": *cfg.PluginSettings.AutomaticPrepackagedPlugins, 1297 "is_default_marketplace_url": isDefault(*cfg.PluginSettings.MarketplaceUrl, model.PLUGIN_SETTINGS_DEFAULT_MARKETPLACE_URL), 1298 "signature_public_key_files": len(cfg.PluginSettings.SignaturePublicKeyFiles), 1299 } 1300 1301 // knownPluginIDs lists all known plugin IDs in the Marketplace 1302 knownPluginIDs := []string{ 1303 "antivirus", 1304 "com.github.manland.mattermost-plugin-gitlab", 1305 "com.github.moussetc.mattermost.plugin.giphy", 1306 "com.github.phillipahereza.mattermost-plugin-digitalocean", 1307 "com.mattermost.aws-sns", 1308 "com.mattermost.confluence", 1309 "com.mattermost.custom-attributes", 1310 "com.mattermost.mscalendar", 1311 "com.mattermost.nps", 1312 "com.mattermost.plugin-channel-export", 1313 "com.mattermost.plugin-incident-management", 1314 "com.mattermost.plugin-todo", 1315 "com.mattermost.webex", 1316 "com.mattermost.welcomebot", 1317 "github", 1318 "jenkins", 1319 "jira", 1320 "jitsi", 1321 "mattermost-autolink", 1322 "memes", 1323 "skype4business", 1324 "zoom", 1325 } 1326 1327 marketplacePlugins, err := ts.getAllMarketplaceplugins(marketplaceURL) 1328 if err != nil { 1329 mlog.Info("Failed to fetch marketplace plugins for telemetry. Using predefined list.", mlog.Err(err)) 1330 1331 for _, id := range knownPluginIDs { 1332 pluginConfigData["enable_"+id] = pluginActivated(cfg.PluginSettings.PluginStates, id) 1333 } 1334 } else { 1335 for _, p := range marketplacePlugins { 1336 id := p.Manifest.Id 1337 1338 pluginConfigData["enable_"+id] = pluginActivated(cfg.PluginSettings.PluginStates, id) 1339 } 1340 } 1341 1342 pluginsEnvironment := ts.srv.GetPluginsEnvironment() 1343 if pluginsEnvironment != nil { 1344 if plugins, appErr := pluginsEnvironment.Available(); appErr != nil { 1345 mlog.Warn("Unable to add plugin versions to telemetry", mlog.Err(appErr)) 1346 } else { 1347 // If marketplace request failed, use predefined list 1348 if marketplacePlugins == nil { 1349 for _, id := range knownPluginIDs { 1350 pluginConfigData["version_"+id] = pluginVersion(plugins, id) 1351 } 1352 } else { 1353 for _, p := range marketplacePlugins { 1354 id := p.Manifest.Id 1355 1356 pluginConfigData["version_"+id] = pluginVersion(plugins, id) 1357 } 1358 } 1359 } 1360 } 1361 1362 ts.sendTelemetry(TrackConfigPlugin, pluginConfigData) 1363 } 1364 1365 func (ts *TelemetryService) getAllMarketplaceplugins(marketplaceURL string) ([]*model.BaseMarketplacePlugin, error) { 1366 marketplaceClient, err := marketplace.NewClient( 1367 marketplaceURL, 1368 ts.srv.HttpService(), 1369 ) 1370 if err != nil { 1371 return nil, err 1372 } 1373 1374 // Fetch all plugins from marketplace. 1375 filter := &model.MarketplacePluginFilter{ 1376 PerPage: -1, 1377 ServerVersion: model.CurrentVersion, 1378 } 1379 1380 license := ts.srv.License() 1381 if license != nil && *license.Features.EnterprisePlugins { 1382 filter.EnterprisePlugins = true 1383 } 1384 1385 if model.BuildEnterpriseReady == "true" { 1386 filter.BuildEnterpriseReady = true 1387 } 1388 1389 return marketplaceClient.GetPlugins(filter) 1390 }