From 401265522e584e4e71a1d92d5af311564b1ec33e Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Wed, 6 Mar 2024 12:32:28 +0100 Subject: [PATCH] Logs volume: Add options to specify field to group by (#83823) Logs volume: Add options to specify field to group by in options --- packages/grafana-data/src/types/logs.ts | 4 ++- .../datasource/loki/datasource.test.ts | 26 +++++++++++++++++ .../app/plugins/datasource/loki/datasource.ts | 29 ++++++++++++++----- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/packages/grafana-data/src/types/logs.ts b/packages/grafana-data/src/types/logs.ts index e63e5512976..d9edfca6bc2 100644 --- a/packages/grafana-data/src/types/logs.ts +++ b/packages/grafana-data/src/types/logs.ts @@ -185,6 +185,7 @@ export type SupplementaryQueryOptions = LogsVolumeOption | LogsSampleOptions; */ export type LogsVolumeOption = { type: SupplementaryQueryType.LogsVolume; + field?: string; }; /** @@ -237,7 +238,8 @@ export interface DataSourceWithSupplementaryQueriesSupport + request: DataQueryRequest, + options?: SupplementaryQueryOptions ): DataQueryRequest | undefined; /** * Returns supplementary query types that data source supports. diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index ea008bd2c6c..8509269a28b 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -1349,6 +1349,7 @@ describe('LokiDatasource', () => { queryType: LokiQueryType.Range, refId: 'log-volume-A', supportingQueryType: SupportingQueryType.LogsVolume, + legendFormat: '{{ level }}', }); }); @@ -1367,6 +1368,7 @@ describe('LokiDatasource', () => { queryType: LokiQueryType.Range, refId: 'log-volume-A', supportingQueryType: SupportingQueryType.LogsVolume, + legendFormat: '{{ level }}', }); }); @@ -1395,6 +1397,30 @@ describe('LokiDatasource', () => { ) ).toEqual(undefined); }); + + it('return logs volume query with defined field', () => { + const query = ds.getSupplementaryQuery( + { type: SupplementaryQueryType.LogsVolume, field: 'test' }, + { + expr: '{label="value"}', + queryType: LokiQueryType.Range, + refId: 'A', + } + ); + expect(query?.expr).toEqual('sum by (test) (count_over_time({label="value"} | drop __error__[$__auto]))'); + }); + + it('return logs volume query with level as field if no field specified', () => { + const query = ds.getSupplementaryQuery( + { type: SupplementaryQueryType.LogsVolume }, + { + expr: '{label="value"}', + queryType: LokiQueryType.Range, + refId: 'A', + } + ); + expect(query?.expr).toEqual('sum by (level) (count_over_time({label="value"} | drop __error__[$__auto]))'); + }); }); describe('logs sample', () => { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index 90380a9a883..74c1a814c94 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -38,6 +38,8 @@ import { DataSourceGetTagValuesOptions, DataSourceGetTagKeysOptions, DataSourceWithQueryModificationSupport, + LogsVolumeOption, + LogsSampleOptions, } from '@grafana/data'; import { Duration } from '@grafana/lezer-logql'; import { BackendSrvRequest, config, DataSourceWithBackend, getTemplateSrv, TemplateSrv } from '@grafana/runtime'; @@ -167,13 +169,18 @@ export class LokiDatasource */ getSupplementaryRequest( type: SupplementaryQueryType, - request: DataQueryRequest + request: DataQueryRequest, + options?: SupplementaryQueryOptions ): DataQueryRequest | undefined { switch (type) { case SupplementaryQueryType.LogsVolume: - return this.getLogsVolumeDataProvider(request); + const logsVolumeOption: LogsVolumeOption = + options?.type === SupplementaryQueryType.LogsVolume ? options : { type }; + return this.getLogsVolumeDataProvider(request, logsVolumeOption); case SupplementaryQueryType.LogsSample: - return this.getLogsSampleDataProvider(request); + const logsSampleOption: LogsSampleOptions = + options?.type === SupplementaryQueryType.LogsSample ? options : { type }; + return this.getLogsSampleDataProvider(request, logsSampleOption); default: return undefined; } @@ -207,6 +214,7 @@ export class LokiDatasource } const dropErrorExpression = `${expr} | drop __error__`; + const field = options.field || 'level'; if (isQueryWithError(this.interpolateString(dropErrorExpression, placeHolderScopedVars)) === false) { expr = dropErrorExpression; } @@ -216,7 +224,8 @@ export class LokiDatasource refId: `${REF_ID_STARTER_LOG_VOLUME}${normalizedQuery.refId}`, queryType: LokiQueryType.Range, supportingQueryType: SupportingQueryType.LogsVolume, - expr: `sum by (level) (count_over_time(${expr}[$__auto]))`, + expr: `sum by (${field}) (count_over_time(${expr}[$__auto]))`, + legendFormat: `{{ ${field} }}`, }; case SupplementaryQueryType.LogsSample: @@ -242,10 +251,13 @@ export class LokiDatasource * Private method used in the `getDataProvider` for DataSourceWithSupplementaryQueriesSupport, specifically for Logs volume queries. * @returns An Observable of DataQueryResponse or undefined if no suitable queries are found. */ - private getLogsVolumeDataProvider(request: DataQueryRequest): DataQueryRequest | undefined { + private getLogsVolumeDataProvider( + request: DataQueryRequest, + options: LogsVolumeOption + ): DataQueryRequest | undefined { const logsVolumeRequest = cloneDeep(request); const targets = logsVolumeRequest.targets - .map((query) => this.getSupplementaryQuery({ type: SupplementaryQueryType.LogsVolume }, query)) + .map((query) => this.getSupplementaryQuery(options, query)) .filter((query): query is LokiQuery => !!query); if (!targets.length) { @@ -259,7 +271,10 @@ export class LokiDatasource * Private method used in the `getDataProvider` for DataSourceWithSupplementaryQueriesSupport, specifically for Logs sample queries. * @returns An Observable of DataQueryResponse or undefined if no suitable queries are found. */ - private getLogsSampleDataProvider(request: DataQueryRequest): DataQueryRequest | undefined { + private getLogsSampleDataProvider( + request: DataQueryRequest, + options?: LogsSampleOptions + ): DataQueryRequest | undefined { const logsSampleRequest = cloneDeep(request); const targets = logsSampleRequest.targets .map((query) => this.getSupplementaryQuery({ type: SupplementaryQueryType.LogsSample, limit: 100 }, query))