From af2d5d98b5d3ef5ac109ad4d08557a5a86146c84 Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Tue, 21 Oct 2025 10:31:19 +0200 Subject: [PATCH] tempo: Use the correct filter separator for negative selector (#112280) Signed-off-by: Goutham Veeramachaneni --- .../tempo/SearchTraceQLEditor/utils.test.ts | 38 +++++++++++++++++++ .../tempo/SearchTraceQLEditor/utils.ts | 4 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.test.ts b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.test.ts index 3bdb9875635..d1cfa7a7703 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.test.ts +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.test.ts @@ -155,4 +155,42 @@ describe('filterToQuerySection returns the correct query section for a filter', const result = filterToQuerySection(filter, [], lp); expect(result).toBe('span.foo=~"bar|baz"'); }); + + it('filter with multiple values and != operator', () => { + const filter: TraceqlFilter = { + id: 'abc', + tag: 'foo', + operator: '!=', + value: ['bar', 'baz'], + scope: TraceqlSearchScope.Span, + }; + const result = filterToQuerySection(filter, [], lp); + expect(result).toBe('(span.foo!=bar && span.foo!=baz)'); + }); + + it('filter with multiple string values and != operator', () => { + const filter: TraceqlFilter = { + id: 'abc', + tag: 'foo', + operator: '!=', + value: ['bar', 'baz'], + scope: TraceqlSearchScope.Span, + valueType: 'string', + }; + const result = filterToQuerySection(filter, [], lp); + expect(result).toBe('(span.foo!="bar" && span.foo!="baz")'); + }); + + it('filter with multiple string values and !~ operator', () => { + const filter: TraceqlFilter = { + id: 'abc', + tag: 'foo', + operator: '!~', + value: ['bar', 'baz'], + scope: TraceqlSearchScope.Span, + valueType: 'string', + }; + const result = filterToQuerySection(filter, [], lp); + expect(result).toBe('span.foo!~"bar|baz"'); + }); }); diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts index bee794dec86..d381349486b 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts @@ -81,7 +81,9 @@ export const tagHelper = (f: TraceqlFilter, filters: TraceqlFilter[]) => { export const filterToQuerySection = (f: TraceqlFilter, filters: TraceqlFilter[], lp: TempoLanguageProvider) => { if (Array.isArray(f.value) && f.value.length > 1 && !isRegExpOperator(f.operator!)) { - return `(${f.value.map((v) => `${scopeHelper(f, lp)}${tagHelper(f, filters)}${f.operator}${valueHelper({ ...f, value: v })}`).join(' || ')})`; + // For negative operators (!=), use && instead of || + const joinOperator = f.operator === '!=' ? ' && ' : ' || '; + return `(${f.value.map((v) => `${scopeHelper(f, lp)}${tagHelper(f, filters)}${f.operator}${valueHelper({ ...f, value: v })}`).join(joinOperator)})`; } return `${scopeHelper(f, lp)}${tagHelper(f, filters)}${f.operator}${valueHelper(f)}`;