diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 6672f6d167e..31d870cb794 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -1,6 +1,17 @@ import { lastValueFrom, of, throwError } from 'rxjs'; import { take } from 'rxjs/operators'; -import { AnnotationQueryRequest, CoreApp, DataFrame, dateTime, FieldCache, TimeSeries, toUtc } from '@grafana/data'; +import { + AnnotationQueryRequest, + CoreApp, + DataFrame, + dateTime, + FieldCache, + TimeSeries, + toUtc, + LogRowModel, + MutableDataFrame, + FieldType, +} from '@grafana/data'; import { BackendSrvRequest, FetchResponse } from '@grafana/runtime'; import LokiDatasource from './datasource'; @@ -882,6 +893,33 @@ describe('LokiDatasource', () => { expect(interval).toBeGreaterThanOrEqual(safeInterval); }); }); + + describe('prepareLogRowContextQueryTarget', () => { + const ds = createLokiDSForTests(); + it('creates query with only labels from /labels API', () => { + const row: LogRowModel = { + rowIndex: 0, + dataFrame: new MutableDataFrame({ + fields: [ + { + name: 'tsNs', + type: FieldType.string, + values: ['0'], + }, + ], + }), + labels: { bar: 'baz', foo: 'uniqueParsedLabel' }, + uid: '1', + } as any; + + //Mock stored labels to only include "bar" label + jest.spyOn(ds.languageProvider, 'getLabelKeys').mockImplementation(() => ['bar']); + const contextQuery = ds.prepareLogRowContextQueryTarget(row, 10, 'BACKWARD'); + + expect(contextQuery.expr).toContain('baz'); + expect(contextQuery.expr).not.toContain('uniqueParsedLabel'); + }); + }); }); function assertAdHocFilters(query: string, expectedResults: string, ds: LokiDatasource) { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index 7580a8abf71..063c51323ba 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -467,8 +467,17 @@ export class LokiDatasource extends DataSourceApi { }; prepareLogRowContextQueryTarget = (row: LogRowModel, limit: number, direction: 'BACKWARD' | 'FORWARD') => { + const labels = this.languageProvider.getLabelKeys(); const query = Object.keys(row.labels) - .map((label) => `${label}="${row.labels[label].replace(/\\/g, '\\\\')}"`) // escape backslashes in label as users can't escape them by themselves + .map((label: string) => { + if (labels.includes(label)) { + // escape backslashes in label as users can't escape them by themselves + return `${label}="${row.labels[label].replace(/\\/g, '\\\\')}"`; + } + return ''; + }) + // Filter empty strings + .filter((label) => !!label) .join(','); const contextTimeBuffer = 2 * 60 * 60 * 1000; // 2h buffer