InfluxDB: Ad hoc filters support for expressions (#109344)
* Support adhoc filters * Tests
This commit is contained in:
@@ -419,3 +419,157 @@ describe('interpolateQueryExpr', () => {
|
||||
expect(result.adhocFilters![0].value).toBe(templateVarValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('interpolateVariablesInQueries', () => {
|
||||
const templateSrvStub = {
|
||||
replace: jest.fn().mockImplementation((target: string) => {
|
||||
if (target === '$database') {
|
||||
return 'test_db';
|
||||
}
|
||||
if (target === '$measurement') {
|
||||
return 'cpu_usage';
|
||||
}
|
||||
if (target === 'SELECT * FROM $measurement WHERE database = "$database"') {
|
||||
return 'SELECT * FROM cpu_usage WHERE database = "test_db"';
|
||||
}
|
||||
if (target === 'SELECT * FROM $measurement') {
|
||||
return 'SELECT * FROM cpu_usage';
|
||||
}
|
||||
if (target === '$server') {
|
||||
return 'prod-server';
|
||||
}
|
||||
return target;
|
||||
}),
|
||||
} as unknown as TemplateSrv;
|
||||
let dsInfluxQL = getMockInfluxDS(getMockDSInstanceSettings(), templateSrvStub);
|
||||
let dsFlux = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.Flux }), templateSrvStub);
|
||||
let dsSQL = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.SQL }), templateSrvStub);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return an empty array if there are no queries', () => {
|
||||
const result = dsInfluxQL.interpolateVariablesInQueries([], {}, []);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should interpolate template variables in query rawQuery (Flux)', () => {
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: true,
|
||||
query: 'SELECT * FROM $measurement WHERE database = "$database"',
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const result = dsFlux.interpolateVariablesInQueries(queries, {}, []);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].query).toBe('SELECT * FROM cpu_usage WHERE database = "test_db"');
|
||||
});
|
||||
|
||||
it('should apply adhoc filters to queries (InfluxQL)', () => {
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: false,
|
||||
measurement: 'cpu',
|
||||
tags: [],
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const adhocFilters: AdHocVariableFilter[] = [
|
||||
{ key: 'host', value: 'server1', operator: '=' },
|
||||
{ key: 'region', value: 'us-east', operator: '=' },
|
||||
];
|
||||
|
||||
const result = dsInfluxQL.interpolateVariablesInQueries(queries, {}, adhocFilters);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].adhocFilters).toEqual(adhocFilters);
|
||||
});
|
||||
|
||||
it('should apply adhoc filters to queries (SQL)', () => {
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: false,
|
||||
measurement: 'cpu',
|
||||
tags: [],
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const adhocFilters: AdHocVariableFilter[] = [
|
||||
{ key: 'host', value: 'server1', operator: '=' },
|
||||
{ key: 'region', value: 'us-east', operator: '=' },
|
||||
];
|
||||
|
||||
const result = dsSQL.interpolateVariablesInQueries(queries, {}, adhocFilters);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].adhocFilters).toEqual(adhocFilters);
|
||||
});
|
||||
|
||||
it('should interpolate template variables in adhoc filter values (InfluxQL)', () => {
|
||||
const templateSrvWithAdhoc = {
|
||||
replace: jest.fn().mockImplementation((target: string) => {
|
||||
if (target === '$server') {
|
||||
return 'prod-server';
|
||||
}
|
||||
return target;
|
||||
}),
|
||||
} as unknown as TemplateSrv;
|
||||
|
||||
const ds = getMockInfluxDS(getMockDSInstanceSettings({ version: InfluxVersion.InfluxQL }), templateSrvWithAdhoc);
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: false,
|
||||
measurement: 'cpu',
|
||||
tags: [],
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const adhocFilters: AdHocVariableFilter[] = [{ key: 'host', value: '$server', operator: '=' }];
|
||||
|
||||
const result = ds.interpolateVariablesInQueries(queries, {}, adhocFilters);
|
||||
|
||||
expect(result[0].adhocFilters![0].value).toBe('prod-server');
|
||||
});
|
||||
|
||||
it('should preserve existing tags when applying adhoc filters', () => {
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: false,
|
||||
measurement: 'cpu',
|
||||
tags: [{ key: 'datacenter', value: 'dc1', operator: '=' }],
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const adhocFilters: AdHocVariableFilter[] = [{ key: 'host', value: 'server1', operator: '=' }];
|
||||
|
||||
const result = dsInfluxQL.interpolateVariablesInQueries(queries, {}, adhocFilters);
|
||||
|
||||
expect(result[0].tags?.length).toEqual(2);
|
||||
expect(result[0].tags![0]).toEqual({ key: 'datacenter', value: 'dc1', operator: '=' });
|
||||
expect(result[0].tags![1]).toEqual({ key: 'host', value: 'server1', operator: '=' });
|
||||
expect(result[0].adhocFilters).toEqual(adhocFilters);
|
||||
});
|
||||
|
||||
it('should handle empty adhoc filters array', () => {
|
||||
const queries: InfluxQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
rawQuery: true,
|
||||
query: 'SELECT * FROM cpu',
|
||||
} as InfluxQuery,
|
||||
];
|
||||
|
||||
const result = dsInfluxQL.interpolateVariablesInQueries(queries, {}, []);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].adhocFilters).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -221,7 +221,11 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
return this.templateSrv.containsTemplate(queryText);
|
||||
}
|
||||
|
||||
interpolateVariablesInQueries(queries: InfluxQuery[], scopedVars: ScopedVars): InfluxQuery[] {
|
||||
interpolateVariablesInQueries(
|
||||
queries: InfluxQuery[],
|
||||
scopedVars: ScopedVars,
|
||||
filters?: AdHocVariableFilter[]
|
||||
): InfluxQuery[] {
|
||||
if (!queries || queries.length === 0) {
|
||||
return [];
|
||||
}
|
||||
@@ -240,10 +244,19 @@ export default class InfluxDatasource extends DataSourceWithBackend<InfluxQuery,
|
||||
};
|
||||
}
|
||||
|
||||
const queryWithVariables = this.applyVariables(query, scopedVars, filters);
|
||||
if (queryWithVariables.adhocFilters?.length) {
|
||||
queryWithVariables.adhocFilters = (queryWithVariables.adhocFilters ?? []).map((af) => {
|
||||
const { condition, ...asTag } = af;
|
||||
asTag.value = this.templateSrv.replace(asTag.value ?? '', scopedVars);
|
||||
return asTag;
|
||||
});
|
||||
queryWithVariables.tags = [...(queryWithVariables.tags ?? []), ...queryWithVariables.adhocFilters];
|
||||
}
|
||||
|
||||
return {
|
||||
...query,
|
||||
...queryWithVariables,
|
||||
datasource: this.getRef(),
|
||||
...this.applyVariables(query, scopedVars),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user