mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Fix interpolating adhoc filters with template variables (#88626)
* Prometheus: replace variables on adhoc filters Fixes #87979 Signed-off-by: Stéphane Cazeaux <stephane.cazeaux@orange.com> * Prometheus: replace variable filters on adhoc variables also when promQLScope=true Signed-off-by: Stéphane Cazeaux <stephane.cazeaux@orange.com> --------- Signed-off-by: Stéphane Cazeaux <stephane.cazeaux@orange.com>
This commit is contained in:
@@ -552,7 +552,7 @@ describe('PrometheusDatasource', () => {
|
||||
config.featureToggles.promQLScope = undefined;
|
||||
});
|
||||
|
||||
it('should call replace function 2 times', () => {
|
||||
it('should call replace function 3 times', () => {
|
||||
const query: PromQuery = {
|
||||
expr: 'test{job="testjob"}',
|
||||
format: 'time_series',
|
||||
@@ -563,7 +563,7 @@ describe('PrometheusDatasource', () => {
|
||||
replaceMock.mockReturnValue(interval);
|
||||
|
||||
const queries = ds.interpolateVariablesInQueries([query], { Interval: { text: interval, value: interval } });
|
||||
expect(templateSrvStub.replace).toBeCalledTimes(2);
|
||||
expect(templateSrvStub.replace).toBeCalledTimes(3);
|
||||
expect(queries[0].interval).toBe(interval);
|
||||
});
|
||||
|
||||
@@ -753,6 +753,55 @@ describe('PrometheusDatasource', () => {
|
||||
const result = ds.applyTemplateVariables(query, {}, filters);
|
||||
expect(result).toMatchObject({ expr: 'test{job="99", k1="v1", k2!="v2"} > 99' });
|
||||
});
|
||||
|
||||
it('should replace variables in ad-hoc filters', () => {
|
||||
const searchPattern = /\$A/g;
|
||||
replaceMock.mockImplementation((a: string) => a?.replace(searchPattern, '99') ?? a);
|
||||
|
||||
const query = {
|
||||
expr: 'test',
|
||||
refId: 'A',
|
||||
};
|
||||
const filters = [
|
||||
{
|
||||
key: 'job',
|
||||
operator: '=~',
|
||||
value: '$A',
|
||||
},
|
||||
];
|
||||
|
||||
const result = ds.applyTemplateVariables(query, {}, filters);
|
||||
expect(result).toMatchObject({ expr: 'test{job=~"99"}' });
|
||||
});
|
||||
|
||||
it('should replace variables in adhoc filters on backend when promQLScope is enabled', () => {
|
||||
config.featureToggles.promQLScope = true;
|
||||
const searchPattern = /\$A/g;
|
||||
replaceMock.mockImplementation((a: string) => a?.replace(searchPattern, '99') ?? a);
|
||||
|
||||
const query = {
|
||||
expr: 'test',
|
||||
refId: 'A',
|
||||
};
|
||||
const filters = [
|
||||
{
|
||||
key: 'job',
|
||||
operator: '=~',
|
||||
value: '$A',
|
||||
},
|
||||
];
|
||||
const result = ds.applyTemplateVariables(query, {}, filters);
|
||||
expect(result).toMatchObject({
|
||||
expr: 'test',
|
||||
adhocFilters: [
|
||||
{
|
||||
key: 'job',
|
||||
operator: 'regex-match',
|
||||
value: '99',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('metricFindQuery', () => {
|
||||
|
||||
@@ -659,14 +659,19 @@ export class PrometheusDatasource
|
||||
if (queries && queries.length) {
|
||||
expandedQueries = queries.map((query) => {
|
||||
const interpolatedQuery = this.templateSrv.replace(query.expr, scopedVars, this.interpolateQueryExpr);
|
||||
const replacedInterpolatedQuery = config.featureToggles.promQLScope
|
||||
? interpolatedQuery
|
||||
: this.templateSrv.replace(
|
||||
this.enhanceExprWithAdHocFilters(filters, interpolatedQuery),
|
||||
scopedVars,
|
||||
this.interpolateQueryExpr
|
||||
);
|
||||
|
||||
const expandedQuery = {
|
||||
...query,
|
||||
...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
datasource: this.getRef(),
|
||||
expr: config.featureToggles.promQLScope
|
||||
? interpolatedQuery
|
||||
: this.enhanceExprWithAdHocFilters(filters, interpolatedQuery),
|
||||
expr: replacedInterpolatedQuery,
|
||||
interval: this.templateSrv.replace(query.interval, scopedVars),
|
||||
};
|
||||
|
||||
@@ -824,7 +829,11 @@ export class PrometheusDatasource
|
||||
return [];
|
||||
}
|
||||
|
||||
return filters.map((f) => ({ ...f, operator: scopeFilterOperatorMap[f.operator] }));
|
||||
return filters.map((f) => ({
|
||||
...f,
|
||||
value: this.templateSrv.replace(f.value, {}, this.interpolateQueryExpr),
|
||||
operator: scopeFilterOperatorMap[f.operator],
|
||||
}));
|
||||
}
|
||||
|
||||
enhanceExprWithAdHocFilters(filters: AdHocVariableFilter[] | undefined, expr: string) {
|
||||
@@ -865,12 +874,21 @@ export class PrometheusDatasource
|
||||
};
|
||||
|
||||
// interpolate expression
|
||||
|
||||
// We need a first replace to evaluate variables before applying adhoc filters
|
||||
// This is required for an expression like `metric > $VAR` where $VAR is a float to which we must not add adhoc filters
|
||||
const expr = this.templateSrv.replace(target.expr, variables, this.interpolateQueryExpr);
|
||||
|
||||
// Apply ad-hoc filters
|
||||
// When ad-hoc filters are applied, we replace again the variables in case the ad-hoc filters also reference a variable
|
||||
const exprWithAdhoc = config.featureToggles.promQLScope
|
||||
? expr
|
||||
: this.templateSrv.replace(this.enhanceExprWithAdHocFilters(filters, expr), variables, this.interpolateQueryExpr);
|
||||
|
||||
return {
|
||||
...target,
|
||||
...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
expr: config.featureToggles.promQLScope ? expr : this.enhanceExprWithAdHocFilters(filters, expr),
|
||||
expr: exprWithAdhoc,
|
||||
interval: this.templateSrv.replace(target.interval, variables),
|
||||
legendFormat: this.templateSrv.replace(target.legendFormat, variables),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user