mirror of https://github.com/grafana/grafana
Tempo: dashboard feature tracking (#61210)
* grafana_tempo_dashboard_loaded * Update version * Updates * Added more tracking stats + updatesmatyax/snapping-test
parent
98cadb3aa0
commit
58c4c95e92
@ -1,11 +1,17 @@ |
||||
import { DataSourcePlugin } from '@grafana/data'; |
||||
import { DataSourcePlugin, DashboardLoadedEvent } from '@grafana/data'; |
||||
import { getAppEvents } from '@grafana/runtime'; |
||||
|
||||
import CheatSheet from './CheatSheet'; |
||||
import { TempoQueryField } from './QueryEditor/QueryField'; |
||||
import { ConfigEditor } from './configuration/ConfigEditor'; |
||||
import { TempoDatasource } from './datasource'; |
||||
import { onDashboardLoadedHandler } from './tracking'; |
||||
import { TempoQuery } from './types'; |
||||
|
||||
export const plugin = new DataSourcePlugin(TempoDatasource) |
||||
.setQueryEditor(TempoQueryField) |
||||
.setConfigEditor(ConfigEditor) |
||||
.setQueryEditorHelp(CheatSheet); |
||||
|
||||
// Subscribe to on dashboard loaded event so that we can track plugin adoption
|
||||
getAppEvents().subscribe<DashboardLoadedEvent<TempoQuery>>(DashboardLoadedEvent, onDashboardLoadedHandler); |
||||
|
@ -0,0 +1,113 @@ |
||||
import { DashboardLoadedEvent } from '@grafana/data'; |
||||
import { reportInteraction } from '@grafana/runtime'; |
||||
|
||||
import './module'; |
||||
|
||||
jest.mock('@grafana/runtime', () => { |
||||
return { |
||||
...jest.requireActual('@grafana/runtime'), |
||||
reportInteraction: jest.fn(), |
||||
getAppEvents: () => ({ |
||||
subscribe: jest.fn((_, handler) => { |
||||
handler( |
||||
new DashboardLoadedEvent({ |
||||
dashboardId: 'dash', |
||||
orgId: 1, |
||||
userId: 1, |
||||
grafanaVersion: 'v9.4.0', |
||||
queries: { |
||||
tempo: [ |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'nativeSearch', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'nativeSearch', |
||||
spanName: 'HTTP', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'nativeSearch', |
||||
spanName: '$var', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'search', |
||||
linkedQuery: { |
||||
expr: '{}', |
||||
}, |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'search', |
||||
linkedQuery: { |
||||
expr: '{$var}', |
||||
}, |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'serviceMap', |
||||
serviceMapQuery: '{}', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'serviceMap', |
||||
serviceMapQuery: '{$var}', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'traceql', |
||||
query: '{}', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'traceql', |
||||
query: '{$var}', |
||||
refId: 'A', |
||||
}, |
||||
{ |
||||
datasource: { type: 'tempo', uid: 'abc' }, |
||||
queryType: 'upload', |
||||
refId: 'A', |
||||
}, |
||||
], |
||||
}, |
||||
}) |
||||
); |
||||
}), |
||||
}), |
||||
getTemplateSrv: () => ({ |
||||
containsTemplate: (val: string): boolean => { |
||||
return val != null && val.includes('$'); |
||||
}, |
||||
}), |
||||
}; |
||||
}); |
||||
|
||||
describe('on dashboard loaded', () => { |
||||
it('triggers reportInteraction with grafana_tempo_dashboard_loaded', () => { |
||||
expect(reportInteraction).toHaveBeenCalledWith('grafana_tempo_dashboard_loaded', { |
||||
grafana_version: 'v9.4.0', |
||||
dashboard_id: 'dash', |
||||
org_id: 1, |
||||
traceql_query_count: 2, |
||||
search_query_count: 2, |
||||
service_map_query_count: 2, |
||||
upload_query_count: 1, |
||||
native_search_query_count: 3, |
||||
traceql_queries_with_template_variables_count: 1, |
||||
search_queries_with_template_variables_count: 1, |
||||
service_map_queries_with_template_variables_count: 1, |
||||
native_search_queries_with_template_variables_count: 1, |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,91 @@ |
||||
import { DashboardLoadedEvent } from '@grafana/data'; |
||||
import { getTemplateSrv, reportInteraction } from '@grafana/runtime'; |
||||
|
||||
import pluginJson from './plugin.json'; |
||||
import { TempoQuery } from './types'; |
||||
|
||||
type TempoOnDashboardLoadedTrackingEvent = { |
||||
grafana_version?: string; |
||||
dashboard_id?: string; |
||||
org_id?: number; |
||||
native_search_query_count: number; |
||||
search_query_count: number; |
||||
service_map_query_count: number; |
||||
traceql_query_count: number; |
||||
upload_query_count: number; |
||||
native_search_queries_with_template_variables_count: number; |
||||
search_queries_with_template_variables_count: number; |
||||
service_map_queries_with_template_variables_count: number; |
||||
traceql_queries_with_template_variables_count: number; |
||||
}; |
||||
|
||||
export const onDashboardLoadedHandler = ({ |
||||
payload: { dashboardId, orgId, grafanaVersion, queries }, |
||||
}: DashboardLoadedEvent<TempoQuery>) => { |
||||
try { |
||||
const tempoQueries = queries[pluginJson.id]; |
||||
|
||||
if (!tempoQueries?.length) { |
||||
return; |
||||
} |
||||
|
||||
let stats: TempoOnDashboardLoadedTrackingEvent = { |
||||
grafana_version: grafanaVersion, |
||||
dashboard_id: dashboardId, |
||||
org_id: orgId, |
||||
native_search_query_count: 0, |
||||
search_query_count: 0, |
||||
service_map_query_count: 0, |
||||
traceql_query_count: 0, |
||||
upload_query_count: 0, |
||||
native_search_queries_with_template_variables_count: 0, |
||||
search_queries_with_template_variables_count: 0, |
||||
service_map_queries_with_template_variables_count: 0, |
||||
traceql_queries_with_template_variables_count: 0, |
||||
}; |
||||
|
||||
for (const query of tempoQueries) { |
||||
if (query.hide) { |
||||
continue; |
||||
} |
||||
|
||||
if (query.queryType === 'nativeSearch') { |
||||
stats.native_search_query_count++; |
||||
if ( |
||||
(query.serviceName && hasTemplateVariables(query.serviceName)) || |
||||
(query.spanName && hasTemplateVariables(query.spanName)) || |
||||
(query.search && hasTemplateVariables(query.search)) || |
||||
(query.minDuration && hasTemplateVariables(query.minDuration)) || |
||||
(query.maxDuration && hasTemplateVariables(query.maxDuration)) |
||||
) { |
||||
stats.native_search_queries_with_template_variables_count++; |
||||
} |
||||
} else if (query.queryType === 'search') { |
||||
stats.search_query_count++; |
||||
if (query.linkedQuery && query.linkedQuery.expr && hasTemplateVariables(query.linkedQuery.expr)) { |
||||
stats.search_queries_with_template_variables_count++; |
||||
} |
||||
} else if (query.queryType === 'serviceMap') { |
||||
stats.service_map_query_count++; |
||||
if (query.serviceMapQuery && hasTemplateVariables(query.serviceMapQuery)) { |
||||
stats.service_map_queries_with_template_variables_count++; |
||||
} |
||||
} else if (query.queryType === 'traceql') { |
||||
stats.traceql_query_count++; |
||||
if (hasTemplateVariables(query.query)) { |
||||
stats.traceql_queries_with_template_variables_count++; |
||||
} |
||||
} else if (query.queryType === 'upload') { |
||||
stats.upload_query_count++; |
||||
} |
||||
} |
||||
|
||||
reportInteraction('grafana_tempo_dashboard_loaded', stats); |
||||
} catch (error) { |
||||
console.error('error in tempo tracking handler', error); |
||||
} |
||||
}; |
||||
|
||||
const hasTemplateVariables = (val: string): boolean => { |
||||
return getTemplateSrv().containsTemplate(val); |
||||
}; |
Loading…
Reference in new issue