Loki: Fixes chained template variable queries for scene apps (#75880)

* Loki: Fixes chained template variable queries for scene apps

* Remove bit
This commit is contained in:
Torkel Ödegaard
2023-10-04 12:47:25 +02:00
committed by GitHub
parent 3749c17556
commit 963049e2b7
8 changed files with 58 additions and 43 deletions

View File

@@ -356,8 +356,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "22"],
[0, 0, 0, "Unexpected any. Specify a different type.", "23"],
[0, 0, 0, "Unexpected any. Specify a different type.", "24"],
[0, 0, 0, "Unexpected any. Specify a different type.", "25"],
[0, 0, 0, "Unexpected any. Specify a different type.", "26"]
[0, 0, 0, "Unexpected any. Specify a different type.", "25"]
],
"packages/grafana-data/src/types/explore.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -5632,14 +5631,13 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
[0, 0, 0, "Do not use any type assertions.", "10"]
[0, 0, 0, "Do not use any type assertions.", "9"]
],
"public/app/features/visualization/data-hover/DataHoverRows.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"]

View File

@@ -282,7 +282,7 @@ abstract class DataSourceApi<
/**
* Variable query action.
*/
metricFindQuery?(query: any, options?: any): Promise<MetricFindValue[]>;
metricFindQuery?(query: any, options?: LegacyMetricFindQueryOptions): Promise<MetricFindValue[]>;
/**
* Get tag keys for adhoc filters

View File

@@ -83,7 +83,7 @@ class LegacyQueryRunner implements QueryRunner {
return getEmptyMetricFindValueObservable();
}
const queryOptions: any = getLegacyQueryOptions(variable, searchFilter, timeSrv);
const queryOptions: any = getLegacyQueryOptions(variable, searchFilter, timeSrv, request.scopedVars);
return from(datasource.metricFindQuery(variable.query, queryOptions)).pipe(
mergeMap((values) => {

View File

@@ -1,12 +1,12 @@
import { isArray, isEqual } from 'lodash';
import { UrlQueryMap, UrlQueryValue, VariableType } from '@grafana/data';
import { LegacyMetricFindQueryOptions, ScopedVars, UrlQueryMap, UrlQueryValue, VariableType } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { safeStringifyValue } from 'app/core/utils/explore';
import { getState } from '../../store/store';
import { StoreState } from '../../types';
import { getTimeSrv } from '../dashboard/services/TimeSrv';
import { TimeSrv } from '../dashboard/services/TimeSrv';
import { variableAdapters } from './adapters';
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, VARIABLE_PREFIX } from './constants';
@@ -131,8 +131,14 @@ export function getTemplatedRegex(variable: QueryVariableModel, templateSrv = ge
return templateSrv.replace(variable.regex, {}, 'regex');
}
export function getLegacyQueryOptions(variable: QueryVariableModel, searchFilter?: string, timeSrv = getTimeSrv()) {
const queryOptions: any = { range: undefined, variable, searchFilter };
export function getLegacyQueryOptions(
variable: QueryVariableModel,
searchFilter: string | undefined,
timeSrv: TimeSrv,
scopedVars: ScopedVars | undefined
): LegacyMetricFindQueryOptions {
const queryOptions: LegacyMetricFindQueryOptions = { range: undefined, variable, searchFilter, scopedVars };
if (variable.refresh === VariableRefresh.onTimeRangeChanged || variable.refresh === VariableRefresh.onDashboardLoad) {
queryOptions.range = timeSrv.timeRange();
}

View File

@@ -528,22 +528,26 @@ describe('LokiDatasource', () => {
it('should interpolate strings in the query', async () => {
const { ds } = getTestContext();
const scopedVars = { scopedVar1: { value: 'A' } };
await ds.metricFindQuery('label_names()');
await ds.metricFindQuery({
refId: 'test',
type: LokiVariableQueryType.LabelValues,
stream: '{label1="value1", label2="value2"}',
label: 'label5',
});
await ds.metricFindQuery('label_names()', { scopedVars });
await ds.metricFindQuery(
{
refId: 'test',
type: LokiVariableQueryType.LabelValues,
stream: '{label1="value1", label2="value2"}',
label: 'label5',
},
{ scopedVars }
);
expect(templateSrvStub.replace).toHaveBeenCalledWith('label_names()', undefined, expect.any(Function));
expect(templateSrvStub.replace).toHaveBeenCalledWith('label_names()', scopedVars, expect.any(Function));
expect(templateSrvStub.replace).toHaveBeenCalledWith(
'{label1="value1", label2="value2"}',
undefined,
scopedVars,
expect.any(Function)
);
expect(templateSrvStub.replace).toHaveBeenCalledWith('label5', undefined, expect.any(Function));
expect(templateSrvStub.replace).toHaveBeenCalledWith('label5', scopedVars, expect.any(Function));
});
});

View File

@@ -34,6 +34,7 @@ import {
ToggleFilterAction,
QueryFilterOptions,
renderLegendFormat,
LegacyMetricFindQueryOptions,
} from '@grafana/data';
import { intervalToMs } from '@grafana/data/src/datetime/rangeutil';
import { Duration } from '@grafana/lezer-logql';
@@ -539,20 +540,20 @@ export class LokiDatasource
return Object.values(response).every((v) => v === 0) ? null : response;
}
async metricFindQuery(query: LokiVariableQuery | string) {
async metricFindQuery(query: LokiVariableQuery | string, options?: LegacyMetricFindQueryOptions) {
if (!query) {
return Promise.resolve([]);
}
if (typeof query === 'string') {
const interpolated = this.interpolateString(query);
const interpolated = this.interpolateString(query, options?.scopedVars);
return await this.legacyProcessMetricFindQuery(interpolated);
}
const interpolatedQuery = {
...query,
label: this.interpolateString(query.label || ''),
stream: this.interpolateString(query.stream || ''),
label: this.interpolateString(query.label || '', options?.scopedVars),
stream: this.interpolateString(query.stream || '', options?.scopedVars),
};
return await this.processMetricFindQuery(interpolatedQuery);

View File

@@ -21,30 +21,36 @@ describe('LokiVariableSupport', () => {
it('should return label names for Loki', async () => {
// label_names()
const response = await lokiVariableSupport.execute({ refId: 'test', type: LokiVariableQueryType.LabelNames });
const response = await lokiVariableSupport.execute({ refId: 'test', type: LokiVariableQueryType.LabelNames }, {});
expect(response).toEqual([{ text: 'label1' }, { text: 'label2' }]);
});
it('should return label values for Loki when no matcher', async () => {
// label_values(label1)
const response = await lokiVariableSupport.execute({
refId: 'test',
type: LokiVariableQueryType.LabelValues,
label: 'label1',
});
const response = await lokiVariableSupport.execute(
{
refId: 'test',
type: LokiVariableQueryType.LabelValues,
label: 'label1',
},
{}
);
expect(response).toEqual([{ text: 'value1' }, { text: 'value2' }]);
});
it('should return label values for Loki with matcher', async () => {
// label_values({label1="value1", label2="value2"},label5)
const response = await lokiVariableSupport.execute({
refId: 'test',
type: LokiVariableQueryType.LabelValues,
stream: '{label1="value1", label2="value2"}',
label: 'label5',
});
const response = await lokiVariableSupport.execute(
{
refId: 'test',
type: LokiVariableQueryType.LabelValues,
stream: '{label1="value1", label2="value2"}',
label: 'label5',
},
{}
);
expect(response).toEqual([{ text: 'value5' }]);
});

View File

@@ -1,7 +1,7 @@
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { CustomVariableSupport, DataQueryRequest, DataQueryResponse } from '@grafana/data';
import { CustomVariableSupport, DataQueryRequest, MetricFindValue, ScopedVars } from '@grafana/data';
import { LokiVariableQueryEditor } from './components/VariableQueryEditor';
import { LokiDatasource } from './datasource';
@@ -14,12 +14,12 @@ export class LokiVariableSupport extends CustomVariableSupport<LokiDatasource, L
super();
}
async execute(query: LokiVariableQuery) {
return this.datasource.metricFindQuery(query);
async execute(query: LokiVariableQuery, scopedVars: ScopedVars) {
return this.datasource.metricFindQuery(query, { scopedVars });
}
query(request: DataQueryRequest<LokiVariableQuery>): Observable<DataQueryResponse> {
const result = this.execute(request.targets[0]);
query(request: DataQueryRequest<LokiVariableQuery>): Observable<{ data: MetricFindValue[] }> {
const result = this.execute(request.targets[0], request.scopedVars);
return from(result).pipe(map((data) => ({ data })));
}