diff --git a/public/app/plugins/datasource/loki/backendResultTransformer.test.ts b/public/app/plugins/datasource/loki/backendResultTransformer.test.ts index b323bfb4c34..29df5d1d6ab 100644 --- a/public/app/plugins/datasource/loki/backendResultTransformer.test.ts +++ b/public/app/plugins/datasource/loki/backendResultTransformer.test.ts @@ -64,8 +64,8 @@ const inputFrame: DataFrame = { length: 5, }; -describe('loki backendResultTransformer', () => { - it('processes a logs-dataframe correctly', () => { +describe('backendResultTransformer', () => { + it('processes a logs dataframe correctly', () => { const response: DataQueryResponse = { data: [cloneDeep(inputFrame)] }; const expectedFrame = cloneDeep(inputFrame); @@ -232,4 +232,24 @@ describe('loki backendResultTransformer', () => { ); expect(result.error?.message).toBe('parse error at line 1, col 2: invalid char escape'); }); + + it('resolves search words from queries with template variables', () => { + const dataFrame = cloneDeep(inputFrame); + dataFrame.meta = { + executedQueryString: 'Expr: {service_name="tns-app"} |~ "(?i)template" |= "variable"', + }; + const result = transformBackendResult( + { data: [dataFrame] }, + [ + { + refId: 'A', + expr: `{service_name="tns-app"} |~ "(?i)$search"`, + }, + ], + [] + ); + + expect(result.data[0].meta.searchWords).toContain('(?i)template'); + expect(result.data[0].meta.searchWords).toContain('variable'); + }); }); diff --git a/public/app/plugins/datasource/loki/backendResultTransformer.ts b/public/app/plugins/datasource/loki/backendResultTransformer.ts index 2a720cf0d7b..1cc91c4c621 100644 --- a/public/app/plugins/datasource/loki/backendResultTransformer.ts +++ b/public/app/plugins/datasource/loki/backendResultTransformer.ts @@ -2,7 +2,7 @@ import { DataQueryResponse, DataFrame, isDataFrame, FieldType, QueryResultMeta, import { getDerivedFields } from './getDerivedFields'; import { makeTableFrames } from './makeTableFrames'; -import { getHighlighterExpressionsFromQuery } from './queryUtils'; +import { getExpressionFromExecutedQuery, getHighlighterExpressionsFromQuery } from './queryUtils'; import { dataFrameHasLokiError } from './responseUtils'; import { DerivedFieldConfig, LokiQuery, LokiQueryType } from './types'; @@ -39,7 +39,7 @@ function processStreamFrame( const meta: QueryResultMeta = { preferredVisualisationType: 'logs', limit: query?.maxLines, - searchWords: query !== undefined ? getHighlighterExpressionsFromQuery(query.expr) : undefined, + searchWords: query ? getHighlighterExpressionsFromQuery(query.expr) : undefined, custom, }; @@ -145,7 +145,17 @@ export function transformBackendResult( return d; }); - const queryMap = new Map(queries.map((query) => [query.refId, query])); + const queryMap = new Map( + queries.map((query) => { + const executedExpr = response.data.find((data) => data.refId === query.refId)?.meta.executedQueryString; + const executedQuery = { + ...query, + expr: executedExpr ? getExpressionFromExecutedQuery(executedExpr) : query.expr, + }; + + return [query.refId, executedQuery]; + }) + ); const { streamsFrames, metricInstantFrames, metricRangeFrames } = groupFrames(dataFrames, queryMap); diff --git a/public/app/plugins/datasource/loki/queryUtils.ts b/public/app/plugins/datasource/loki/queryUtils.ts index 45bb0870104..368f1819620 100644 --- a/public/app/plugins/datasource/loki/queryUtils.ts +++ b/public/app/plugins/datasource/loki/queryUtils.ts @@ -31,10 +31,10 @@ import { LokiQuery, LokiQueryType } from './types'; /** * Returns search terms from a LogQL query. - * E.g., `{} |= foo |=bar != baz` returns `['foo', 'bar']`. + * E.g., `{} |= "foo" |= "bar" != "baz"` returns `['foo', 'bar']`. */ export function getHighlighterExpressionsFromQuery(input = ''): string[] { - const results = []; + const results: string[] = []; const filters = getNodesFromQuery(input, [LineFilter]); @@ -76,6 +76,10 @@ export function getHighlighterExpressionsFromQuery(input = ''): string[] { return results; } +export function getExpressionFromExecutedQuery(executedQueryString: string) { + return executedQueryString.replace('Expr: ', ''); +} + export function getStringsFromLineFilter(filter: SyntaxNode): SyntaxNode[] { const nodes: SyntaxNode[] = []; let node: SyntaxNode | null = filter;