The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/loki/tracking.test.ts

218 lines
6.7 KiB

import { CoreApp, DashboardLoadedEvent, DataQueryRequest, dateTime } from '@grafana/data';
import { QueryEditorMode } from '@grafana/experimental';
import { reportInteraction } from '@grafana/runtime';
import pluginJson from './plugin.json';
import { partitionTimeRange } from './querySplitting';
import { onDashboardLoadedHandler, trackGroupedQueries, trackQuery } from './tracking';
import { LokiGroupedRequest, LokiQuery } from './types';
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
reportInteraction: jest.fn(),
}));
const baseTarget = {
resolution: 1,
editorMode: QueryEditorMode.Builder,
};
const range = {
from: dateTime('2023-02-08T05:00:00.000Z'),
to: dateTime('2023-02-10T06:00:00.000Z'),
raw: {
from: dateTime('2023-02-08T05:00:00.000Z'),
to: dateTime('2023-02-10T06:00:00.000Z'),
},
};
const originalRequest = {
targets: [
{ expr: 'count_over_time({a="b"}[1m])', refId: 'A', ...baseTarget },
{ expr: '{a="b"}', refId: 'B', maxLines: 10, ...baseTarget },
{ expr: 'count_over_time({hidden="true"}[1m])', refId: 'C', ...baseTarget, hide: true },
],
range,
app: CoreApp.Explore,
} as DataQueryRequest<LokiQuery>;
const requests: LokiGroupedRequest[] = [
{
request: {
targets: [{ expr: 'count_over_time({a="b"}[1m])', refId: 'A', ...baseTarget }],
range,
app: 'explore',
} as DataQueryRequest<LokiQuery>,
partition: partitionTimeRange(true, range, 60000, 24 * 60 * 60 * 1000),
},
{
request: {
targets: [{ expr: '{a="b"}', refId: 'B', maxLines: 10, ...baseTarget }],
range,
app: 'explore',
} as DataQueryRequest<LokiQuery>,
partition: partitionTimeRange(false, range, 60000, 24 * 60 * 60 * 1000),
},
];
beforeAll(() => {
jest.useFakeTimers().setSystemTime(new Date('Wed May 17 2023 17:20:12 GMT+0200'));
});
afterAll(() => {
jest.useRealTimers();
jest.clearAllMocks();
});
beforeEach(() => {
jest.mocked(reportInteraction).mockClear();
});
describe('Tracks queries', () => {
it('should track queries in Explore', () => {
trackQuery({ data: [] }, originalRequest, new Date());
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
bytes_processed: 0,
editor_mode: 'builder',
grafana_version: '1.0',
has_data: false,
has_error: false,
is_split: false,
legend: undefined,
line_limit: undefined,
obfuscated_query: 'count_over_time({Identifier=String}[1m])',
query_type: 'metric',
query_vector_type: undefined,
resolution: 1,
simultaneously_executed_query_count: 2,
simultaneously_hidden_query_count: 1,
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
});
it('should not track queries if app is not Explore', () => {
trackQuery({ data: [] }, { ...originalRequest, app: CoreApp.PanelViewer }, new Date());
expect(reportInteraction).not.toHaveBeenCalled();
});
it('should not track queries if no app', () => {
trackQuery({ data: [] }, { ...originalRequest, app: '' }, new Date());
expect(reportInteraction).not.toHaveBeenCalled();
});
});
test('Tracks predefined operations', () => {
trackQuery({ data: [] }, originalRequest, new Date(), { predefinedOperations: 'count_over_time' });
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
bytes_processed: 0,
editor_mode: 'builder',
grafana_version: '1.0',
has_data: false,
has_error: false,
is_split: false,
legend: undefined,
line_limit: undefined,
obfuscated_query: 'count_over_time({Identifier=String}[1m])',
query_type: 'metric',
query_vector_type: undefined,
resolution: 1,
simultaneously_executed_query_count: 2,
simultaneously_hidden_query_count: 1,
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: true,
});
});
test('Tracks grouped queries', () => {
trackGroupedQueries({ data: [] }, requests, originalRequest, new Date());
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
bytes_processed: 0,
editor_mode: 'builder',
grafana_version: '1.0',
has_data: false,
has_error: false,
is_split: true,
legend: undefined,
line_limit: undefined,
obfuscated_query: 'count_over_time({Identifier=String}[1m])',
query_type: 'metric',
query_vector_type: undefined,
resolution: 1,
simultaneously_executed_query_count: 2,
simultaneously_hidden_query_count: 1,
split_query_group_count: 2,
split_query_largest_partition_size: 3,
split_query_partition_size: 3,
split_query_total_request_count: 6,
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
expect(reportInteraction).toHaveBeenCalledWith('grafana_explore_loki_query_executed', {
bytes_processed: 0,
editor_mode: 'builder',
grafana_version: '1.0',
has_data: false,
has_error: false,
is_split: true,
legend: undefined,
line_limit: 10,
obfuscated_query: '{Identifier=String}',
query_type: 'logs',
query_vector_type: undefined,
resolution: 1,
simultaneously_executed_query_count: 2,
simultaneously_hidden_query_count: 1,
split_query_group_count: 2,
split_query_largest_partition_size: 3,
split_query_partition_size: 3,
split_query_total_request_count: 6,
time_range_from: '2023-02-08T05:00:00.000Z',
time_range_to: '2023-02-10T06:00:00.000Z',
time_taken: 0,
predefined_operations_applied: 'n/a',
});
});
describe('onDashboardLoadedHandler', () => {
beforeEach(() => {
jest.mocked(reportInteraction).mockClear();
jest.spyOn(console, 'error');
});
test('Reports dashboard loaded interactions', () => {
const event = new DashboardLoadedEvent({
dashboardId: 'test',
orgId: 1,
userId: 2,
grafanaVersion: '11',
queries: {
[pluginJson.id]: originalRequest.targets,
},
});
onDashboardLoadedHandler(event);
expect(reportInteraction).toHaveBeenCalled();
expect(console.error).not.toHaveBeenCalled();
});
test('Does not report or fails when the dashboard id has no queries', () => {
const event = new DashboardLoadedEvent({
dashboardId: 'test',
orgId: 1,
userId: 2,
grafanaVersion: '11',
queries: {
'not loki': originalRequest.targets,
},
});
onDashboardLoadedHandler(event);
expect(reportInteraction).not.toHaveBeenCalled();
expect(console.error).not.toHaveBeenCalled();
});
});