diff --git a/packages/grafana-runtime/src/types/analytics.ts b/packages/grafana-runtime/src/types/analytics.ts index 804ab09d5a5..41a792d6ac5 100644 --- a/packages/grafana-runtime/src/types/analytics.ts +++ b/packages/grafana-runtime/src/types/analytics.ts @@ -1,18 +1,35 @@ import { EchoEvent, EchoEventType } from '../services/EchoSrv'; -export interface MetaAnalyticsEventPayload { - eventName: string; - dashboardId?: number; - dashboardUid?: string; - dashboardName?: string; +export interface DashboardInfo { + dashboardId: number; + dashboardUid: string; + dashboardName: string; folderName?: string; - panelId?: number; - panelName?: string; +} + +export interface DataRequestInfo extends Partial { datasourceName: string; datasourceId?: number; - error?: string; + panelId?: number; + panelName?: string; duration: number; + error?: string; dataSize?: number; } +export enum MetaAnalyticsEventName { + DashboardView = 'dashboard-view', + DataRequest = 'data-request', +} + +export interface DashboardViewEventPayload extends DashboardInfo { + eventName: MetaAnalyticsEventName.DashboardView; +} + +export interface DataRequestEventPayload extends DataRequestInfo { + eventName: MetaAnalyticsEventName.DataRequest; +} + +export type MetaAnalyticsEventPayload = DashboardViewEventPayload | DataRequestEventPayload; + export interface MetaAnalyticsEvent extends EchoEvent {} diff --git a/public/app/features/dashboard/state/analyticsProcessor.ts b/public/app/features/dashboard/state/analyticsProcessor.ts index 47b013c29af..ea4d600f65a 100644 --- a/public/app/features/dashboard/state/analyticsProcessor.ts +++ b/public/app/features/dashboard/state/analyticsProcessor.ts @@ -1,10 +1,16 @@ import { getDashboardSrv } from '../services/DashboardSrv'; +import { DashboardModel } from './DashboardModel'; import { PanelData, LoadingState, DataSourceApi } from '@grafana/data'; -import { reportMetaAnalytics, MetaAnalyticsEventPayload } from '@grafana/runtime'; +import { + reportMetaAnalytics, + MetaAnalyticsEventName, + DataRequestEventPayload, + DashboardViewEventPayload, +} from '@grafana/runtime'; -export function getAnalyticsProcessor(datasource: DataSourceApi) { +export function emitDataRequestEvent(datasource: DataSourceApi) { let done = false; return (data: PanelData) => { @@ -16,16 +22,14 @@ export function getAnalyticsProcessor(datasource: DataSourceApi) { return; } - const eventData: MetaAnalyticsEventPayload = { + const eventData: DataRequestEventPayload = { + eventName: MetaAnalyticsEventName.DataRequest, datasourceName: datasource.name, datasourceId: datasource.id, panelId: data.request.panelId, dashboardId: data.request.dashboardId, - // app: 'dashboard', dataSize: 0, duration: data.request.endTime - data.request.startTime, - eventName: 'data-request', - // sessionId: '', }; // enrich with dashboard info @@ -53,3 +57,15 @@ export function getAnalyticsProcessor(datasource: DataSourceApi) { done = true; }; } + +export function emitDashboardViewEvent(dashboard: DashboardModel) { + const eventData: DashboardViewEventPayload = { + dashboardId: dashboard.id, + dashboardName: dashboard.title, + dashboardUid: dashboard.uid, + folderName: dashboard.meta.folderTitle, + eventName: MetaAnalyticsEventName.DashboardView, + }; + + reportMetaAnalytics(eventData); +} diff --git a/public/app/features/dashboard/state/initDashboard.test.ts b/public/app/features/dashboard/state/initDashboard.test.ts index c07e729cfcd..adb0f395ec4 100644 --- a/public/app/features/dashboard/state/initDashboard.test.ts +++ b/public/app/features/dashboard/state/initDashboard.test.ts @@ -5,6 +5,8 @@ import { DashboardRouteInfo } from 'app/types'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { dashboardInitCompleted, dashboardInitFetching, dashboardInitServices } from './reducers'; import { updateLocation } from '../../../core/actions'; +import { setEchoSrv } from '@grafana/runtime'; +import { Echo } from '../../../core/services/echo/Echo'; jest.mock('app/core/services/backend_srv'); @@ -124,6 +126,7 @@ function describeInitScenario(description: string, scenarioFn: ScenarioFn) { beforeEach(async () => { setupFn(); + setEchoSrv(new Echo()); const store = mockStore(ctx.storeState); // @ts-ignore diff --git a/public/app/features/dashboard/state/initDashboard.ts b/public/app/features/dashboard/state/initDashboard.ts index b21a15e769e..95bf8eefc15 100644 --- a/public/app/features/dashboard/state/initDashboard.ts +++ b/public/app/features/dashboard/state/initDashboard.ts @@ -25,6 +25,7 @@ import { DataQuery } from '@grafana/data'; import { getConfig } from '../../../core/config'; import { initDashboardTemplating, processVariables } from '../../variables/state/actions'; import { variableAdapters } from '../../variables/adapters'; +import { emitDashboardViewEvent } from './analyticsProcessor'; export interface InitDashboardArgs { $injector: any; @@ -223,6 +224,11 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult { // legacy srv state dashboardSrv.setCurrent(dashboard); + // send open dashboard event + if (args.routeInfo !== DashboardRouteInfo.New) { + emitDashboardViewEvent(dashboard); + } + // yay we are done dispatch(dashboardInitCompleted(dashboard)); }; diff --git a/public/app/features/dashboard/state/runRequest.ts b/public/app/features/dashboard/state/runRequest.ts index dcf207c5102..57d02406860 100644 --- a/public/app/features/dashboard/state/runRequest.ts +++ b/public/app/features/dashboard/state/runRequest.ts @@ -18,7 +18,7 @@ import { DataFrame, guessFieldTypes, } from '@grafana/data'; -import { getAnalyticsProcessor } from './analyticsProcessor'; +import { emitDataRequestEvent } from './analyticsProcessor'; import { ExpressionDatasourceID, expressionDatasource } from 'app/features/expressions/ExpressionDatasource'; type MapOfResponsePackets = { [str: string]: DataQueryResponse }; @@ -120,7 +120,7 @@ export function runRequest(datasource: DataSourceApi, request: DataQueryRequest) error: processQueryError(err), }) ), - tap(getAnalyticsProcessor(datasource)), + tap(emitDataRequestEvent(datasource)), // finalize is triggered when subscriber unsubscribes // This makes sure any still running network requests are cancelled finalize(cancelNetworkRequestsOnUnsubscribe(request)),