EchoSrv: Add BrowserConsoleBackend to log analytics events (#95554)

* EchoSrv: Add BrowserConsoleBackend to log analytics events

* rename config name

* warn on non-scalar property values
This commit is contained in:
Josh Hunt 2024-10-29 18:20:54 +00:00 committed by GitHub
parent d480900a9b
commit 189802d3c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 68 additions and 1 deletions

View File

@ -316,6 +316,9 @@ feedback_links_enabled = true
# Static context that is being added to analytics events
reporting_static_context =
# Logs interaction events to the browser javascript console, intended for development only
browser_console_reporter = false
#################################### Security ############################
[security]
# disable creation of admin user on first start of grafana

View File

@ -315,6 +315,9 @@
# Static context that is being added to analytics events
;reporting_static_context = grafanaInstance=12, os=linux
# Logs interaction events to the browser javascript console, intended for development only
;browser_console_reporter = false
#################################### Security ####################################
[security]
# disable creation of admin user on first start of grafana

View File

@ -226,6 +226,7 @@ export interface GrafanaConfig {
rudderstackSdkUrl: string | undefined;
rudderstackConfigUrl: string | undefined;
rudderstackIntegrationsUrl: string | undefined;
analyticsConsoleReporting: boolean;
sqlConnectionLimits: SqlConnectionLimits;
sharedWithMeFolderUID?: string;
rootFolderUID?: string;

View File

@ -183,6 +183,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
rudderstackSdkUrl: undefined;
rudderstackConfigUrl: undefined;
rudderstackIntegrationsUrl: undefined;
analyticsConsoleReporting = false;
sqlConnectionLimits = {
maxOpenConns: 100,
maxIdleConns: 100,

View File

@ -187,6 +187,8 @@ type FrontendSettingsDTO struct {
RudderstackConfigUrl string `json:"rudderstackConfigUrl"`
RudderstackIntegrationsUrl string `json:"rudderstackIntegrationsUrl"`
AnalyticsConsoleReporting bool `json:"analyticsConsoleReporting"`
FeedbackLinksEnabled bool `json:"feedbackLinksEnabled"`
ApplicationInsightsConnectionString string `json:"applicationInsightsConnectionString"`
ApplicationInsightsEndpointUrl string `json:"applicationInsightsEndpointUrl"`

View File

@ -213,6 +213,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
RudderstackSdkUrl: hs.Cfg.RudderstackSDKURL,
RudderstackConfigUrl: hs.Cfg.RudderstackConfigURL,
RudderstackIntegrationsUrl: hs.Cfg.RudderstackIntegrationsURL,
AnalyticsConsoleReporting: hs.Cfg.FrontendAnalyticsConsoleReporting,
FeedbackLinksEnabled: hs.Cfg.FeedbackLinksEnabled,
ApplicationInsightsConnectionString: hs.Cfg.ApplicationInsightsConnectionString,
ApplicationInsightsEndpointUrl: hs.Cfg.ApplicationInsightsEndpointUrl,

View File

@ -382,6 +382,7 @@ type Cfg struct {
RudderstackConfigURL string
RudderstackIntegrationsURL string
IntercomSecret string
FrontendAnalyticsConsoleReporting bool
// LDAP
LDAPAuthEnabled bool
@ -1158,6 +1159,7 @@ func (cfg *Cfg) parseINIFile(iniFile *ini.File) error {
cfg.RudderstackConfigURL = analytics.Key("rudderstack_config_url").String()
cfg.RudderstackIntegrationsURL = analytics.Key("rudderstack_integrations_url").String()
cfg.IntercomSecret = analytics.Key("intercom_secret").String()
cfg.FrontendAnalyticsConsoleReporting = analytics.Key("browser_console_reporter").MustBool(false)
cfg.ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)
cfg.ReportingDistributor = analytics.Key("reporting_distributor").MustString("grafana-labs")

View File

@ -67,6 +67,7 @@ import { Echo } from './core/services/echo/Echo';
import { reportPerformance } from './core/services/echo/EchoSrv';
import { PerformanceBackend } from './core/services/echo/backends/PerformanceBackend';
import { ApplicationInsightsBackend } from './core/services/echo/backends/analytics/ApplicationInsightsBackend';
import { BrowserConsoleBackend } from './core/services/echo/backends/analytics/BrowseConsoleBackend';
import { GA4EchoBackend } from './core/services/echo/backends/analytics/GA4Backend';
import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend';
import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend';
@ -382,6 +383,10 @@ function initEchoSrv() {
})
);
}
if (config.analyticsConsoleReporting) {
registerEchoBackend(new BrowserConsoleBackend());
}
}
/**

View File

@ -1,6 +1,5 @@
import { PluginState } from '@grafana/data';
import { config, GrafanaBootConfig } from '@grafana/runtime';
// Legacy binding paths
export { config, GrafanaBootConfig as Settings };
let grafanaConfig: GrafanaBootConfig = config;

View File

@ -0,0 +1,50 @@
/* eslint-disable no-console */
import {
EchoBackend,
EchoEventType,
isExperimentViewEvent,
isInteractionEvent,
isPageviewEvent,
PageviewEchoEvent,
} from '@grafana/runtime';
export class BrowserConsoleBackend implements EchoBackend<PageviewEchoEvent, unknown> {
options = {};
supportedEvents = [EchoEventType.Pageview, EchoEventType.Interaction, EchoEventType.ExperimentView];
constructor() {}
addEvent = (e: PageviewEchoEvent) => {
if (isPageviewEvent(e)) {
console.log('[EchoSrv:pageview]', e.payload.page);
}
if (isInteractionEvent(e)) {
const eventName = e.payload.interactionName;
console.log('[EchoSrv:event]', eventName, e.payload.properties);
// Warn for non-scalar property values. We're not yet making this a hard a
const invalidTypeProperties = Object.entries(e.payload.properties ?? {}).filter(([_, value]) => {
const valueType = typeof value;
const isValidType =
valueType === 'string' || valueType === 'number' || valueType === 'boolean' || valueType === 'undefined';
return !isValidType;
});
if (invalidTypeProperties.length > 0) {
console.warn(
'Event',
eventName,
'has invalid property types. Event properties should only be string, number or boolean. Invalid properties:',
Object.fromEntries(invalidTypeProperties)
);
}
}
if (isExperimentViewEvent(e)) {
console.log('[EchoSrv:experiment]', e.payload);
}
};
flush = () => {};
}