Tempo: Properly escape double quotes in TraceQL query (#106909)
* Properly escape double quotes * Simplify regex
This commit is contained in:
@@ -5,7 +5,7 @@ import { getTemplateSrv } from '@grafana/runtime';
|
||||
import { VariableFormatID } from '@grafana/schema';
|
||||
|
||||
import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen';
|
||||
import { getEscapedSpanNames } from '../datasource';
|
||||
import { getEscapedRegexValues, getEscapedValues } from '../datasource';
|
||||
import TempoLanguageProvider from '../language_provider';
|
||||
import { intrinsics } from '../traceql/traceql';
|
||||
import { Scope } from '../types';
|
||||
@@ -32,11 +32,16 @@ export const interpolateFilters = (filters: TraceqlFilter[], scopedVars?: Scoped
|
||||
|
||||
const isRegExpOperator = (operator: string) => operator === '=~' || operator === '!~';
|
||||
|
||||
const escapeValues = (values: string[]) => getEscapedSpanNames(values);
|
||||
|
||||
export const valueHelper = (f: TraceqlFilter) => {
|
||||
const value =
|
||||
Array.isArray(f.value) && isRegExpOperator(f.operator!) && !f.isCustomValue ? escapeValues(f.value) : f.value;
|
||||
let value = f.value;
|
||||
|
||||
if (Array.isArray(value) && !f.isCustomValue) {
|
||||
value = getEscapedValues(value);
|
||||
|
||||
if (isRegExpOperator(f.operator!)) {
|
||||
value = getEscapedRegexValues(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value) && value.length > 1) {
|
||||
return `"${value.join('|')}"`;
|
||||
|
||||
@@ -41,7 +41,8 @@ import {
|
||||
makeServiceGraphViewRequest,
|
||||
makeTempoLink,
|
||||
getFieldConfig,
|
||||
getEscapedSpanNames,
|
||||
getEscapedRegexValues,
|
||||
getEscapedValues,
|
||||
makeHistogramLink,
|
||||
makePromServiceMapRequest,
|
||||
} from './datasource';
|
||||
@@ -778,12 +779,12 @@ describe('Tempo service graph view', () => {
|
||||
'server.cluster.local:9090^/sample.test(.*)?',
|
||||
'test\\path',
|
||||
];
|
||||
let escaped = getEscapedSpanNames(spanNames);
|
||||
let escaped = getEscapedRegexValues(getEscapedValues(spanNames));
|
||||
expect(escaped).toEqual([
|
||||
'/actuator/health/\\\\*\\\\*',
|
||||
'\\\\$type \\\\+ \\\\[test\\\\]\\\\|HTTP POST - post',
|
||||
'server\\\\.cluster\\\\.local:9090\\\\^/sample\\\\.test\\\\(\\\\.\\\\*\\\\)\\\\?',
|
||||
'test\\\\\\\\path',
|
||||
'test\\\\path',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -1081,7 +1081,7 @@ function errorAndDurationQuery(
|
||||
}
|
||||
});
|
||||
}
|
||||
const spanNames = getEscapedSpanNames(labels);
|
||||
const spanNames = getEscapedRegexValues(getEscapedValues(labels));
|
||||
|
||||
if (spanNames.length > 0) {
|
||||
errorRateBySpanName = buildExpr(errorRateMetric, 'span_name=~"' + spanNames.join('|') + '"', request);
|
||||
@@ -1151,8 +1151,12 @@ function makePromLink(title: string, expr: string, datasourceUid: string, instan
|
||||
|
||||
// TODO: this is basically the same as prometheus/datasource.ts#prometheusSpecialRegexEscape which is used to escape
|
||||
// template variable values. It would be best to move it to some common place.
|
||||
export function getEscapedSpanNames(values: string[]) {
|
||||
return values.map((value: string) => value.replace(/\\/g, '\\\\\\\\').replace(/[$^*{}\[\]\'+?.()|]/g, '\\\\$&'));
|
||||
export function getEscapedRegexValues(values: string[]) {
|
||||
return values.map((value: string) => value.replace(/[$^*{}\[\]\'+?.()|]/g, '\\\\$&'));
|
||||
}
|
||||
|
||||
export function getEscapedValues(values: string[]) {
|
||||
return values.map((value: string) => value.replace(/["\\]/g, '\\$&'));
|
||||
}
|
||||
|
||||
export function getFieldConfig(
|
||||
|
||||
@@ -174,7 +174,7 @@ describe('Language_provider', () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
).toBe(`{name${operator}"api/v2/variants/by-upc/\\\\(\\\\?P<upc>\\\\[\\\\\\\\s\\\\\\\\S\\\\]\\\\*\\\\)/\\\\$"}`);
|
||||
).toBe(`{name${operator}"api/v2/variants/by-upc/\\\\(\\\\?P<upc>\\\\[\\\\s\\\\S\\\\]\\\\*\\\\)/\\\\$"}`);
|
||||
});
|
||||
it('two fields with everything filled in', () => {
|
||||
expect(
|
||||
|
||||
Reference in New Issue
Block a user