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