From 961479b1115d39f3918b60c49a48841916939f03 Mon Sep 17 00:00:00 2001 From: Ivan Ortega Alba Date: Tue, 16 Aug 2022 10:32:00 +0200 Subject: [PATCH] Analytics: Use Fullstory to get behavioral data (#53732) --- conf/defaults.ini | 3 +++ package.json | 1 + packages/grafana-data/src/types/config.ts | 1 + .../src/types/featureToggles.gen.ts | 1 + packages/grafana-runtime/src/config.ts | 1 + .../grafana-runtime/src/services/EchoSrv.ts | 1 + .../grafana-runtime/src/types/analytics.ts | 7 ++++++ pkg/api/frontendsettings.go | 1 + pkg/services/featuremgmt/registry.go | 4 ++++ pkg/services/featuremgmt/toggles_gen.go | 4 ++++ pkg/setting/setting.go | 2 ++ public/app/app.ts | 7 ++++++ .../backends/analytics/FullstoryBackend.ts | 22 +++++++++++++++++++ yarn.lock | 8 +++++++ 14 files changed, 63 insertions(+) create mode 100644 public/app/core/services/echo/backends/analytics/FullstoryBackend.ts diff --git a/conf/defaults.ini b/conf/defaults.ini index 25cd162661b..3866d12a7ad 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -215,6 +215,9 @@ google_analytics_ua_id = # Google Tag Manager ID, only enabled if you specify an id here google_tag_manager_id = +# Fullstory org id, only enabled if you specify an org id here +fullstory_org_id = + # Rudderstack write key, enabled only if rudderstack_data_plane_url is also set rudderstack_write_key = diff --git a/package.json b/package.json index 05aeff0fccc..8a9ba1537f6 100644 --- a/package.json +++ b/package.json @@ -250,6 +250,7 @@ "dependencies": { "@emotion/css": "11.9.0", "@emotion/react": "11.9.3", + "@fullstory/browser": "^1.6.1", "@grafana/agent-core": "0.4.0", "@grafana/agent-web": "0.4.0", "@grafana/aws-sdk": "0.0.37", diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 7040900e88a..fe5ee5e03cf 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -211,6 +211,7 @@ export interface GrafanaConfig { feedbackLinksEnabled: boolean; secretsManagerPluginEnabled: boolean; googleAnalyticsId: string | undefined; + fullstoryOrgId: string | undefined; rudderstackWriteKey: string | undefined; rudderstackDataPlaneUrl: string | undefined; rudderstackSdkUrl: string | undefined; diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index e890d70144b..1c7cb199ea5 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -63,4 +63,5 @@ export interface FeatureToggles { internationalization?: boolean; topnav?: boolean; customBranding?: boolean; + fullstoryUserTracking?: boolean; } diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index e1c471f0199..97f07ab0b9d 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -134,6 +134,7 @@ export class GrafanaBootConfig implements GrafanaConfig { enabled: true, }; googleAnalyticsId: undefined; + fullstoryOrgId: undefined; rudderstackWriteKey: undefined; rudderstackDataPlaneUrl: undefined; rudderstackSdkUrl: undefined; diff --git a/packages/grafana-runtime/src/services/EchoSrv.ts b/packages/grafana-runtime/src/services/EchoSrv.ts index 7609c9fe85e..cc28e90da85 100644 --- a/packages/grafana-runtime/src/services/EchoSrv.ts +++ b/packages/grafana-runtime/src/services/EchoSrv.ts @@ -83,6 +83,7 @@ export enum EchoEventType { Interaction = 'interaction', ExperimentView = 'experimentview', GrafanaJavascriptAgent = 'grafana-javascript-agent', + Fullstory = 'fullstory-sdk', } /** diff --git a/packages/grafana-runtime/src/types/analytics.ts b/packages/grafana-runtime/src/types/analytics.ts index c3e7f585303..4439943e0fb 100644 --- a/packages/grafana-runtime/src/types/analytics.ts +++ b/packages/grafana-runtime/src/types/analytics.ts @@ -107,6 +107,13 @@ export interface InteractionEchoEventPayload { */ export type InteractionEchoEvent = EchoEvent; +/** + * Describes Fullstory custom interaction event with predefined {@link EchoEventType.EchoEventType} type. + * + * @public + */ +export type FullstoryEchoEvent = EchoEvent; + /** * Describes the payload of an experimentview event. * diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 45752ef8072..88afe5a00a1 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -118,6 +118,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i "profileEnabled": setting.ProfileEnabled, "queryHistoryEnabled": hs.Cfg.QueryHistoryEnabled, "googleAnalyticsId": setting.GoogleAnalyticsId, + "fullstoryOrgId": setting.FullstoryOrgId, "rudderstackWriteKey": setting.RudderstackWriteKey, "rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl, "rudderstackSdkUrl": setting.RudderstackSdkUrl, diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 473e3448f20..ebe3c19b44b 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -262,5 +262,9 @@ var ( Description: "Replaces whitelabeling with the new custom branding feature", State: FeatureStateAlpha, }, + { + Name: "fullstoryUserTracking", + Description: "Enables Fullstory cliend SDK to do user analytics", + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 140a58863b9..4a241607545 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -194,4 +194,8 @@ const ( // FlagCustomBranding // Replaces whitelabeling with the new custom branding feature FlagCustomBranding = "customBranding" + + // FlagFullstoryUserTracking + // Enables Fullstory cliend SDK to do user analytics + FlagFullstoryUserTracking = "fullstoryUserTracking" ) diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 8b18109ef92..eeec1f0a205 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -137,6 +137,7 @@ var ( // analytics GoogleAnalyticsId string GoogleTagManagerId string + FullstoryOrgId string RudderstackDataPlaneUrl string RudderstackWriteKey string RudderstackSdkUrl string @@ -953,6 +954,7 @@ func (cfg *Cfg) Load(args CommandLineArgs) error { cfg.CheckForPluginUpdates = analytics.Key("check_for_plugin_updates").MustBool(true) GoogleAnalyticsId = analytics.Key("google_analytics_ua_id").String() GoogleTagManagerId = analytics.Key("google_tag_manager_id").String() + FullstoryOrgId = analytics.Key("fullstory_org_id").String() RudderstackWriteKey = analytics.Key("rudderstack_write_key").String() RudderstackDataPlaneUrl = analytics.Key("rudderstack_data_plane_url").String() RudderstackSdkUrl = analytics.Key("rudderstack_sdk_url").String() diff --git a/public/app/app.ts b/public/app/app.ts index defcdd62ffc..aded9396b1e 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -53,6 +53,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 { FullstoryBackend } from './core/services/echo/backends/analytics/FullstoryBackend'; import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend'; import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend'; import { GrafanaJavascriptAgentBackend } from './core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend'; @@ -206,6 +207,12 @@ function initEchoSrv() { registerEchoBackend(new PerformanceBackend({})); } + if (config.featureToggles.fullstoryUserTracking && config.fullstoryOrgId) { + registerEchoBackend( + new FullstoryBackend({ orgId: config.fullstoryOrgId, devMode: process.env.NODE_ENV === 'development' }) + ); + } + if (config.sentry.enabled) { registerEchoBackend( new SentryEchoBackend({ diff --git a/public/app/core/services/echo/backends/analytics/FullstoryBackend.ts b/public/app/core/services/echo/backends/analytics/FullstoryBackend.ts new file mode 100644 index 00000000000..179d36104e6 --- /dev/null +++ b/public/app/core/services/echo/backends/analytics/FullstoryBackend.ts @@ -0,0 +1,22 @@ +import { init } from '@fullstory/browser'; + +import { EchoBackend, EchoEventType, FullstoryEchoEvent } from '@grafana/runtime'; + +export interface FullstoryBackendOptions { + orgId: string; + devMode?: boolean; +} + +export class FullstoryBackend implements EchoBackend { + supportedEvents = [EchoEventType.Fullstory]; + + constructor(public options: FullstoryBackendOptions) { + init({ orgId: options.orgId, devMode: options.devMode ?? false, debug: options.devMode ?? false }); + } + + // Not using custom events, Fullstory track every interaction automatically + addEvent = (e: FullstoryEchoEvent) => {}; + + // Not using Echo buffering + flush = () => {}; +} diff --git a/yarn.lock b/yarn.lock index 731e9a6566a..51b03451238 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4719,6 +4719,13 @@ __metadata: languageName: node linkType: hard +"@fullstory/browser@npm:^1.6.1": + version: 1.6.1 + resolution: "@fullstory/browser@npm:1.6.1" + checksum: 79bb1c05b92b6bb6163566eeceb2ddf8e7e7bf5b9d629d99a937cecc21eafc019a0149c78d968e623424cbc84e9ce10e162e8ab56e59d47d259ca8e364f5c249 + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1": version: 1.1.2 resolution: "@gar/promisify@npm:1.1.2" @@ -21642,6 +21649,7 @@ __metadata: "@emotion/css": 11.9.0 "@emotion/eslint-plugin": 11.7.0 "@emotion/react": 11.9.3 + "@fullstory/browser": ^1.6.1 "@grafana/agent-core": 0.4.0 "@grafana/agent-web": 0.4.0 "@grafana/api-documenter": 7.11.2