From 66dc20f46f2ea568e6303fb665bec90732425cc9 Mon Sep 17 00:00:00 2001 From: Joey <90795735+joey-grafana@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:06:51 +0100 Subject: [PATCH] Tempo: Upgrade interpolation for Tempo (#89664) Upgrade interpolation for Tempo --- .../SearchTraceQLEditor/TraceQLSearch.tsx | 7 +++--- .../tempo/SearchTraceQLEditor/utils.ts | 24 ++++++++++++++++++- .../datasource/tempo/datasource.test.ts | 8 +++---- .../plugins/datasource/tempo/datasource.ts | 22 +++++------------ .../datasource/tempo/language_provider.ts | 7 +++++- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TraceQLSearch.tsx b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TraceQLSearch.tsx index 6a94b728784..64adda814ac 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TraceQLSearch.tsx +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/TraceQLSearch.tsx @@ -18,7 +18,7 @@ import { GroupByField } from './GroupByField'; import InlineSearchField from './InlineSearchField'; import SearchField from './SearchField'; import TagsInput from './TagsInput'; -import { filterScopedTag, filterTitle, generateQueryFromFilters, replaceAt } from './utils'; +import { filterScopedTag, filterTitle, generateQueryFromFilters, interpolateFilters, replaceAt } from './utils'; interface Props { datasource: TempoDatasource; @@ -62,9 +62,10 @@ const TraceQLSearch = ({ datasource, query, onChange, onClearResults, app, addVa onChange({ ...query, filters: query.filters.filter((f) => f.id !== s.id) }); }; + const templateVariables = getTemplateSrv().getVariables(); useEffect(() => { - setTraceQlQuery(generateQueryFromFilters(query.filters || [])); - }, [query]); + setTraceQlQuery(generateQueryFromFilters(interpolateFilters(query.filters || []))); + }, [query, templateVariables]); const findFilter = useCallback((id: string) => query.filters?.find((f) => f.id === id), [query.filters]); diff --git a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts index 378076ed50b..7191e90f6ed 100644 --- a/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts +++ b/public/app/plugins/datasource/tempo/SearchTraceQLEditor/utils.ts @@ -1,11 +1,33 @@ import { startCase, uniq } from 'lodash'; -import { AdHocVariableFilter, SelectableValue } from '@grafana/data'; +import { AdHocVariableFilter, ScopedVars, SelectableValue } from '@grafana/data'; +import { getTemplateSrv } from '@grafana/runtime'; +import { VariableFormatID } from '@grafana/schema'; import { TraceqlFilter, TraceqlSearchScope } from '../dataquery.gen'; import { intrinsics } from '../traceql/traceql'; import { Scope } from '../types'; +export const interpolateFilters = (filters: TraceqlFilter[], scopedVars?: ScopedVars) => { + const interpolatedFilters = filters.map((filter) => { + const updatedFilter = { + ...filter, + tag: getTemplateSrv().replace(filter.tag ?? '', scopedVars ?? {}), + }; + + if (filter.value) { + updatedFilter.value = + typeof filter.value === 'string' + ? getTemplateSrv().replace(filter.value ?? '', scopedVars ?? {}, VariableFormatID.Pipe) + : filter.value.map((v) => getTemplateSrv().replace(v ?? '', scopedVars ?? {}, VariableFormatID.Pipe)); + } + + return updatedFilter; + }); + + return interpolatedFilters; +}; + export const generateQueryFromFilters = (filters: TraceqlFilter[]) => { return `{${filters .filter((f) => f.tag && f.operator && f.value?.length) diff --git a/public/app/plugins/datasource/tempo/datasource.test.ts b/public/app/plugins/datasource/tempo/datasource.test.ts index 2cc8f39594e..771220631ee 100644 --- a/public/app/plugins/datasource/tempo/datasource.test.ts +++ b/public/app/plugins/datasource/tempo/datasource.test.ts @@ -112,7 +112,7 @@ describe('Tempo data source', () => { config.liveEnabled = true; const ds = new TempoDatasource(defaultSettings, templateSrv); await lastValueFrom(ds.query(traceqlSearchQuery as DataQueryRequest)); - expect(handleStreamingSearch).toHaveBeenCalledTimes(2); + expect(handleStreamingSearch).toHaveBeenCalledTimes(1); expect(request).toHaveBeenCalledTimes(0); }); @@ -120,7 +120,7 @@ describe('Tempo data source', () => { config.liveEnabled = false; const ds = new TempoDatasource(defaultSettings, templateSrv); await lastValueFrom(ds.query(traceqlQuery as DataQueryRequest)); - expect(handleStreamingSearch).toHaveBeenCalledTimes(2); + expect(handleStreamingSearch).toHaveBeenCalledTimes(1); expect(request).toHaveBeenCalledTimes(1); }); @@ -128,8 +128,8 @@ describe('Tempo data source', () => { config.liveEnabled = false; const ds = new TempoDatasource(defaultSettings, templateSrv); await lastValueFrom(ds.query(traceqlSearchQuery as DataQueryRequest)); - expect(handleStreamingSearch).toHaveBeenCalledTimes(2); - expect(request).toHaveBeenCalledTimes(2); + expect(handleStreamingSearch).toHaveBeenCalledTimes(1); + expect(request).toHaveBeenCalledTimes(1); }); }); diff --git a/public/app/plugins/datasource/tempo/datasource.ts b/public/app/plugins/datasource/tempo/datasource.ts index b7ae4f1c77d..d287cae6459 100644 --- a/public/app/plugins/datasource/tempo/datasource.ts +++ b/public/app/plugins/datasource/tempo/datasource.ts @@ -34,7 +34,11 @@ import { } from '@grafana/runtime'; import { BarGaugeDisplayMode, TableCellDisplayMode, VariableFormatID } from '@grafana/schema'; -import { generateQueryFromAdHocFilters, generateQueryFromFilters } from './SearchTraceQLEditor/utils'; +import { + generateQueryFromAdHocFilters, + generateQueryFromFilters, + interpolateFilters, +} from './SearchTraceQLEditor/utils'; import { TempoVariableQuery, TempoVariableQueryType } from './VariableQueryEditor'; import { PrometheusDatasource, PromQuery } from './_importedDependencies/datasources/prometheus/types'; import { TraceqlFilter, TraceqlSearchScope } from './dataquery.gen'; @@ -470,21 +474,7 @@ export class TempoDatasource extends DataSourceWithBackend { - const updatedFilter = { - ...filter, - tag: this.templateSrv.replace(filter.tag ?? '', scopedVars), - }; - - if (filter.value) { - updatedFilter.value = - typeof filter.value === 'string' - ? this.templateSrv.replace(filter.value ?? '', scopedVars, VariableFormatID.Pipe) - : filter.value.map((v) => this.templateSrv.replace(v ?? '', scopedVars, VariableFormatID.Pipe)); - } - - return updatedFilter; - }); + expandedQuery.filters = interpolateFilters(query.filters, scopedVars); } if (query.groupBy) { diff --git a/public/app/plugins/datasource/tempo/language_provider.ts b/public/app/plugins/datasource/tempo/language_provider.ts index 968259d6326..a91cd899d06 100644 --- a/public/app/plugins/datasource/tempo/language_provider.ts +++ b/public/app/plugins/datasource/tempo/language_provider.ts @@ -1,4 +1,6 @@ import { LanguageProvider, SelectableValue } from '@grafana/data'; +import { getTemplateSrv } from '@grafana/runtime'; +import { VariableFormatID } from '@grafana/schema'; import { getAllTags, getTagsByScope, getUnscopedTags } from './SearchTraceQLEditor/utils'; import { TraceqlSearchScope } from './dataquery.gen'; @@ -132,7 +134,10 @@ export default class TempoLanguageProvider extends LanguageProvider { async getOptionsV2(tag: string, query?: string): Promise>> { const encodedTag = this.encodeTag(tag); - const response = await this.request(`/api/v2/search/tag/${encodedTag}/values`, query ? { q: query } : {}); + const response = await this.request( + `/api/v2/search/tag/${encodedTag}/values`, + query ? { q: getTemplateSrv().replace(query, {}, VariableFormatID.Pipe) } : {} + ); let options: Array> = []; if (response && response.tagValues) { response.tagValues.forEach((v: { type: string; value?: string }) => {