diff --git a/conf/defaults.ini b/conf/defaults.ini index 88ed4791098..3f7693ad008 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -312,6 +312,9 @@ application_insights_endpoint_url = # Controls if the UI contains any links to user feedback forms feedback_links_enabled = true +# Static context that is being added to analytics events +reporting_static_context = + #################################### Security ############################ [security] # disable creation of admin user on first start of grafana diff --git a/conf/sample.ini b/conf/sample.ini index c9885cda40f..a12b063078f 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -309,6 +309,9 @@ # Controls if the UI contains any links to user feedback forms ;feedback_links_enabled = true +# Static context that is being added to analytics events +;reporting_static_context = grafanaInstance=12, os=linux + #################################### Security #################################### [security] # disable creation of admin user on first start of grafana diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index b8703f55aaf..e3903ed78c3 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -232,6 +232,7 @@ export interface GrafanaConfig { cloudMigrationIsTarget?: boolean; listDashboardScopesEndpoint?: string; listScopesEndpoint?: string; + reportingStaticContext?: Record; // The namespace to use for kubernetes apiserver requests namespace: string; diff --git a/packages/grafana-runtime/src/analytics/utils.ts b/packages/grafana-runtime/src/analytics/utils.ts index ac901f0879c..a5363420e74 100644 --- a/packages/grafana-runtime/src/analytics/utils.ts +++ b/packages/grafana-runtime/src/analytics/utils.ts @@ -44,6 +44,10 @@ export const reportPageview = () => { * @public */ export const reportInteraction = (interactionName: string, properties?: Record) => { + // get static reporting context and append it to properties + if (config.reportingStaticContext && config.reportingStaticContext instanceof Object) { + properties = { ...properties, ...config.reportingStaticContext }; + } getEchoSrv().addEvent({ type: EchoEventType.Interaction, payload: { diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 82fb397c7ab..8d615b27d1a 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -177,6 +177,7 @@ export class GrafanaBootConfig implements GrafanaConfig { rootFolderUID: string | undefined; localFileSystemAvailable: boolean | undefined; cloudMigrationIsTarget: boolean | undefined; + reportingStaticContext?: Record; /** * Language used in Grafana's UI. This is after the user's preference (or deteceted locale) is resolved to one of diff --git a/pkg/api/dtos/frontend_settings.go b/pkg/api/dtos/frontend_settings.go index 2475d0b8892..a58b0ca00b1 100644 --- a/pkg/api/dtos/frontend_settings.go +++ b/pkg/api/dtos/frontend_settings.go @@ -231,6 +231,7 @@ type FrontendSettingsDTO struct { SupportBundlesEnabled bool `json:"supportBundlesEnabled"` SnapshotEnabled bool `json:"snapshotEnabled"` SecureSocksDSProxyEnabled bool `json:"secureSocksDSProxyEnabled"` + ReportingStaticContext map[string]string `json:"reportingStaticContext"` Azure FrontendSettingsAzureDTO `json:"azure"` diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 0148bc450a3..abb5a3783da 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -226,6 +226,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro SharedWithMeFolderUID: folder.SharedWithMeFolderUID, RootFolderUID: accesscontrol.GeneralFolderUID, LocalFileSystemAvailable: hs.Cfg.LocalFileSystemAvailable, + ReportingStaticContext: hs.Cfg.ReportingStaticContext, BuildInfo: dtos.FrontendSettingsBuildInfoDTO{ HideVersion: hideVersion, diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 336a27b7e28..aa37813cc6e 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -366,6 +366,7 @@ type Cfg struct { ApplicationInsightsConnectionString string ApplicationInsightsEndpointUrl string FeedbackLinksEnabled bool + ReportingStaticContext map[string]string // Frontend analytics GoogleAnalyticsID string @@ -1156,6 +1157,15 @@ func (cfg *Cfg) parseINIFile(iniFile *ini.File) error { cfg.ApplicationInsightsEndpointUrl = analytics.Key("application_insights_endpoint_url").String() cfg.FeedbackLinksEnabled = analytics.Key("feedback_links_enabled").MustBool(true) + // parse reporting static context string of key=value, key=value pairs into an object + cfg.ReportingStaticContext = make(map[string]string) + for _, pair := range strings.Split(analytics.Key("reporting_static_context").String(), ",") { + kv := strings.Split(pair, "=") + if len(kv) == 2 { + cfg.ReportingStaticContext[strings.TrimSpace("_static_context_"+kv[0])] = strings.TrimSpace(kv[1]) + } + } + if err := cfg.readAlertingSettings(iniFile); err != nil { return err }