CloudMonitoring: Fixes broken variable queries that use group bys (#43914)

This commit is contained in:
Erik Sundell 2022-01-17 15:51:24 +01:00 committed by GitHub
parent 9fb8339f87
commit 715166baf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 10 deletions

View File

@ -100,7 +100,10 @@ export default class CloudMonitoringMetricFindQuery {
return [];
}
const refId = 'handleLabelValuesQuery';
const labels = await this.datasource.getLabels(selectedMetricType, refId, projectName, [labelKey]);
const labels = await this.datasource.getLabels(selectedMetricType, refId, projectName, {
groupBys: [labelKey],
crossSeriesReducer: 'REDUCE_MEAN',
});
const interpolatedKey = this.datasource.templateSrv.replace(labelKey);
const values = labels.hasOwnProperty(interpolatedKey) ? labels[interpolatedKey] : [];
return values.map(this.toFindQueryResult);

View File

@ -61,15 +61,15 @@ function Editor({
variableOptionGroup,
}: React.PropsWithChildren<Props>) {
const [state, setState] = useState<State>(defaultState);
const { projectName, metricType, groupBys, editorMode } = query;
const { projectName, metricType, groupBys, editorMode, crossSeriesReducer } = query;
useEffect(() => {
if (projectName && metricType) {
datasource
.getLabels(metricType, refId, projectName, groupBys)
.getLabels(metricType, refId, projectName, { groupBys, crossSeriesReducer })
.then((labels) => setState((prevState) => ({ ...prevState, labels })));
}
}, [datasource, groupBys, metricType, projectName, refId]);
}, [datasource, groupBys, metricType, projectName, refId, crossSeriesReducer]);
const onChange = useCallback(
(metricQuery: MetricQuery | SLOQuery) => {

View File

@ -20,6 +20,7 @@ import {
MetricDescriptor,
QueryType,
PostResponse,
Aggregation,
} from './types';
import { CloudMonitoringVariableSupport } from './variables';
@ -136,7 +137,7 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
};
}
async getLabels(metricType: string, refId: string, projectName: string, groupBys?: string[]) {
async getLabels(metricType: string, refId: string, projectName: string, aggregation?: Aggregation) {
const options = {
targets: [
{
@ -146,8 +147,8 @@ export default class CloudMonitoringDatasource extends DataSourceWithBackend<
metricQuery: {
projectName: this.templateSrv.replace(projectName),
metricType: this.templateSrv.replace(metricType),
groupBys: this.interpolateGroupBys(groupBys || [], {}),
crossSeriesReducer: 'REDUCE_NONE',
groupBys: this.interpolateGroupBys(aggregation?.groupBys || [], {}),
crossSeriesReducer: aggregation?.crossSeriesReducer ?? 'REDUCE_NONE',
view: 'HEADERS',
},
},

View File

@ -17,6 +17,8 @@ jest.mock('@grafana/runtime', () => ({
type Args = { response?: any; throws?: boolean; templateSrv?: TemplateSrv };
const fetchMock = jest.spyOn(backendSrv, 'fetch');
function getTestcontext({ response = {}, throws = false, templateSrv = new TemplateSrv() }: Args = {}) {
jest.clearAllMocks();
@ -26,9 +28,12 @@ function getTestcontext({ response = {}, throws = false, templateSrv = new Templ
},
} as unknown) as DataSourceInstanceSettings<CloudMonitoringOptions>;
const timeSrv = {} as TimeSrv;
const fetchMock = jest.spyOn(backendSrv, 'fetch');
const timeSrv = {
timeRange: () => ({
from: toUtc('2017-08-22T20:00:00Z'),
to: toUtc('2017-08-22T23:59:00Z'),
}),
} as TimeSrv;
throws
? fetchMock.mockImplementation(() => throwError(response))
@ -82,6 +87,41 @@ describe('CloudMonitoringDataSource', () => {
});
});
describe('When loading labels', () => {
describe('and no aggregation was specified', () => {
it('should use default values', async () => {
const { ds } = getTestcontext();
await ds.getLabels('cpu', 'a', 'default-proj');
await expect(fetchMock.mock.calls[0][0].data.queries[0].metricQuery).toMatchObject({
crossSeriesReducer: 'REDUCE_NONE',
groupBys: [],
metricType: 'cpu',
projectName: 'default-proj',
view: 'HEADERS',
});
});
});
describe('and an aggregation was specified', () => {
it('should use the provided aggregation', async () => {
const { ds } = getTestcontext();
await ds.getLabels('sql', 'b', 'default-proj', {
crossSeriesReducer: 'REDUCE_MEAN',
groupBys: ['metadata.system_label.name'],
});
await expect(fetchMock.mock.calls[0][0].data.queries[0].metricQuery).toMatchObject({
crossSeriesReducer: 'REDUCE_MEAN',
groupBys: ['metadata.system_label.name'],
metricType: 'sql',
projectName: 'default-proj',
view: 'HEADERS',
});
});
});
});
describe('when interpolating a template variable for the filter', () => {
describe('and is single value variable', () => {
it('should replace the variable with the value', () => {

View File

@ -53,6 +53,11 @@ export interface VariableQueryData {
loading: boolean;
}
export interface Aggregation {
crossSeriesReducer?: string;
groupBys?: string[];
}
export enum QueryType {
METRICS = 'metrics',
SLO = 'slo',