From 0db19a79241741e1ecb661a90545ccfbb256ebbc Mon Sep 17 00:00:00 2001 From: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com> Date: Wed, 20 Dec 2023 07:33:58 -0600 Subject: [PATCH] Loki: strip out backticks in query editor line filter (#79340) * pull in @svennergr's solution to switch delimiter on existence of backtick --------- Co-authored-by: Sven Grossmann --- .../loki/querybuilder/operationUtils.test.ts | 9 +++++++++ .../loki/querybuilder/operationUtils.ts | 18 ++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/loki/querybuilder/operationUtils.test.ts b/public/app/plugins/datasource/loki/querybuilder/operationUtils.test.ts index 1335e1a2944..6c6bc4d3094 100644 --- a/public/app/plugins/datasource/loki/querybuilder/operationUtils.test.ts +++ b/public/app/plugins/datasource/loki/querybuilder/operationUtils.test.ts @@ -144,6 +144,10 @@ describe('getLineFilterRenderer', () => { id: '__line_contains_case_insensitive', params: ['ERrOR'], }; + const MOCK_MODEL_BACKTICKS = { + id: '__line_contains', + params: ['`error`'], + }; const MOCK_DEF = undefined as unknown as QueryBuilderOperationDef; @@ -159,6 +163,11 @@ describe('getLineFilterRenderer', () => { expect(lineFilterRenderer(MOCK_MODEL, MOCK_DEF, MOCK_INNER_EXPR)).toBe('{job="grafana"} !~ `error`'); }); + it('lineFilterRenderer returns the correct query for line contains, containing backticks', () => { + const lineFilterRenderer = getLineFilterRenderer('!~'); + expect(lineFilterRenderer(MOCK_MODEL_BACKTICKS, MOCK_DEF, MOCK_INNER_EXPR)).toBe('{job="grafana"} !~ "`error`"'); + }); + it('lineFilterRenderer returns the correct query for line contains case insensitive', () => { const lineFilterRenderer = getLineFilterRenderer('!~', true); expect(lineFilterRenderer(MOCK_MODEL_INSENSITIVE, MOCK_DEF, MOCK_INNER_EXPR)).toBe( diff --git a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts index 73f0aa145e6..14b06912617 100644 --- a/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts +++ b/public/app/plugins/datasource/loki/querybuilder/operationUtils.ts @@ -10,6 +10,7 @@ import { QueryWithOperations, VisualQueryModeller, } from '../../prometheus/querybuilder/shared/types'; +import { escapeLabelValueInExactSelector } from '../languageUtils'; import { FUNCTIONS } from '../syntax'; import { LokiOperationId, LokiOperationOrder, LokiVisualQuery, LokiVisualQueryOperationCategory } from './types'; @@ -294,13 +295,22 @@ export function addNestedQueryHandler(def: QueryBuilderOperationDef, query: Loki export function getLineFilterRenderer(operation: string, caseInsensitive?: boolean) { return function lineFilterRenderer(model: QueryBuilderOperation, def: QueryBuilderOperationDef, innerExpr: string) { - if (caseInsensitive) { - return `${innerExpr} ${operation} \`(?i)${model.params.join('` or `(?i)')}\``; + const hasBackticks = model.params.some((param) => typeof param === 'string' && param.includes('`')); + const delimiter = hasBackticks ? '"' : '`'; + let params; + if (hasBackticks) { + params = model.params.map((param) => + typeof param === 'string' ? escapeLabelValueInExactSelector(param) : param + ); + } else { + params = model.params; } - return `${innerExpr} ${operation} \`${model.params.join('` or `')}\``; + if (caseInsensitive) { + return `${innerExpr} ${operation} ${delimiter}(?i)${params.join(`${delimiter} or ${delimiter}(?i)`)}${delimiter}`; + } + return `${innerExpr} ${operation} ${delimiter}${params.join(`${delimiter} or ${delimiter}`)}${delimiter}`; }; } - function getRangeVectorParamDef(): QueryBuilderOperationParamDef { return { name: 'Range',