mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
stackdriver: add support for template variables
This commit is contained in:
parent
26b1cc5dcf
commit
0aeaec1ac6
@ -14,7 +14,7 @@ async function loadComponent(module) {
|
||||
}
|
||||
|
||||
/** @ngInject */
|
||||
function variableQueryEditorLoader() {
|
||||
function variableQueryEditorLoader(templateSrv) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: async (scope, elem) => {
|
||||
@ -23,6 +23,7 @@ function variableQueryEditorLoader() {
|
||||
datasource: scope.currentDatasource,
|
||||
query: scope.current.query,
|
||||
onChange: scope.onQueryChange,
|
||||
templateSrv,
|
||||
};
|
||||
ReactDOM.render(<Component {...props} />, elem[0]);
|
||||
scope.$on('$destroy', () => {
|
||||
|
@ -1,7 +1,12 @@
|
||||
import isString from 'lodash/isString';
|
||||
import { alignmentPeriods } from './constants';
|
||||
import { MetricFindQueryTypes } from './types';
|
||||
import { getMetricTypesByService, getAlignmentOptionsByMetric, getAggregationOptionsByMetric } from './functions';
|
||||
import {
|
||||
getMetricTypesByService,
|
||||
getAlignmentOptionsByMetric,
|
||||
getAggregationOptionsByMetric,
|
||||
getLabelKeys,
|
||||
} from './functions';
|
||||
|
||||
export default class StackdriverMetricFindQuery {
|
||||
constructor(private datasource) {}
|
||||
@ -37,37 +42,34 @@ export default class StackdriverMetricFindQuery {
|
||||
return [];
|
||||
}
|
||||
const metricDescriptors = await this.datasource.getMetricTypes(this.datasource.projectName);
|
||||
return getMetricTypesByService(metricDescriptors, selectedService).map(s => ({
|
||||
return getMetricTypesByService(metricDescriptors, this.datasource.templateSrv.replace(selectedService)).map(s => ({
|
||||
text: s.displayName,
|
||||
value: s.type,
|
||||
expandable: true,
|
||||
}));
|
||||
}
|
||||
|
||||
async handleLabelKeysQuery({ selectedQueryType, selectedMetricType, labelKey }) {
|
||||
async handleLabelKeysQuery({ selectedMetricType }) {
|
||||
if (!selectedMetricType) {
|
||||
return [];
|
||||
}
|
||||
const refId = 'handleLabelKeysQuery';
|
||||
const response = await this.datasource.getLabels(selectedMetricType, refId);
|
||||
const labelKeys = response.meta
|
||||
? [...Object.keys(response.meta.resourceLabels), ...Object.keys(response.meta.metricLabels)]
|
||||
: [];
|
||||
const labelKeys = await getLabelKeys(this.datasource, selectedMetricType);
|
||||
return labelKeys.map(this.toFindQueryResult);
|
||||
}
|
||||
|
||||
async handleLabelValuesQuery({ selectedQueryType, selectedMetricType, labelKey }) {
|
||||
async handleLabelValuesQuery({ selectedMetricType, labelKey }) {
|
||||
if (!selectedMetricType) {
|
||||
return [];
|
||||
}
|
||||
const refId = 'handleLabelValuesQuery';
|
||||
const response = await this.datasource.getLabels(selectedMetricType, refId);
|
||||
|
||||
const interpolatedKey = this.datasource.templateSrv.replace(labelKey);
|
||||
const [name] = interpolatedKey.split('.').reverse();
|
||||
let values = [];
|
||||
if (response.meta && response.meta.metricLabels && response.meta.metricLabels.hasOwnProperty(labelKey)) {
|
||||
values = response.meta.metricLabels[labelKey];
|
||||
} else if (response.meta && response.meta.resourceLabels && response.meta.resourceLabels.hasOwnProperty(labelKey)) {
|
||||
values = response.meta.resourceLabels[labelKey];
|
||||
if (response.meta && response.meta.metricLabels && response.meta.metricLabels.hasOwnProperty(name)) {
|
||||
values = response.meta.metricLabels[name];
|
||||
} else if (response.meta && response.meta.resourceLabels && response.meta.resourceLabels.hasOwnProperty(name)) {
|
||||
values = response.meta.resourceLabels[name];
|
||||
}
|
||||
|
||||
return values.map(this.toFindQueryResult);
|
||||
@ -87,7 +89,9 @@ export default class StackdriverMetricFindQuery {
|
||||
return [];
|
||||
}
|
||||
const metricDescriptors = await this.datasource.getMetricTypes(this.datasource.projectName);
|
||||
const { valueType, metricKind } = metricDescriptors.find(m => m.type === selectedMetricType);
|
||||
const { valueType, metricKind } = metricDescriptors.find(
|
||||
m => m.type === this.datasource.templateSrv.replace(selectedMetricType)
|
||||
);
|
||||
return getAlignmentOptionsByMetric(valueType, metricKind).map(this.toFindQueryResult);
|
||||
}
|
||||
|
||||
@ -96,7 +100,9 @@ export default class StackdriverMetricFindQuery {
|
||||
return [];
|
||||
}
|
||||
const metricDescriptors = await this.datasource.getMetricTypes(this.datasource.projectName);
|
||||
const { valueType, metricKind } = metricDescriptors.find(m => m.type === selectedMetricType);
|
||||
const { valueType, metricKind } = metricDescriptors.find(
|
||||
m => m.type === this.datasource.templateSrv.replace(selectedMetricType)
|
||||
);
|
||||
return getAggregationOptionsByMetric(valueType, metricKind).map(this.toFindQueryResult);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ const props: VariableQueryProps = {
|
||||
datasource: {
|
||||
getMetricTypes: async p => [],
|
||||
},
|
||||
templateSrv: { replace: s => s },
|
||||
};
|
||||
|
||||
describe('VariableQueryEditor', () => {
|
||||
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { VariableQueryProps } from 'app/types/plugins';
|
||||
import SimpleSelect from './SimpleSelect';
|
||||
import { getMetricTypes } from '../functions';
|
||||
import { getMetricTypes, getLabelKeys } from '../functions';
|
||||
import { MetricFindQueryTypes, VariableQueryData } from '../types';
|
||||
|
||||
export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryProps, VariableQueryData> {
|
||||
@ -40,7 +40,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
}));
|
||||
|
||||
let selectedService = '';
|
||||
if (services.some(s => s.value === this.state.selectedService)) {
|
||||
if (services.some(s => s.value === this.props.templateSrv.replace(this.state.selectedService))) {
|
||||
selectedService = this.state.selectedService;
|
||||
} else if (services && services.length > 0) {
|
||||
selectedService = services[0].value;
|
||||
@ -49,6 +49,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
const { metricTypes, selectedMetricType } = getMetricTypes(
|
||||
metricDescriptors,
|
||||
this.state.selectedMetricType,
|
||||
this.props.templateSrv.replace(this.state.selectedMetricType),
|
||||
selectedService
|
||||
);
|
||||
const state: any = {
|
||||
@ -57,7 +58,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
metricTypes,
|
||||
selectedMetricType,
|
||||
metricDescriptors,
|
||||
...await this.getLabelValues(selectedMetricType),
|
||||
...await this.getLabels(selectedMetricType),
|
||||
};
|
||||
this.setState(state);
|
||||
}
|
||||
@ -65,7 +66,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
async handleQueryTypeChange(event) {
|
||||
const state: any = {
|
||||
selectedQueryType: event.target.value,
|
||||
...await this.getLabelValues(this.state.selectedMetricType, event.target.value),
|
||||
...await this.getLabels(this.state.selectedMetricType, event.target.value),
|
||||
};
|
||||
this.setState(state);
|
||||
}
|
||||
@ -74,19 +75,20 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
const { metricTypes, selectedMetricType } = getMetricTypes(
|
||||
this.state.metricDescriptors,
|
||||
this.state.selectedMetricType,
|
||||
this.props.templateSrv.replace(this.state.selectedMetricType),
|
||||
event.target.value
|
||||
);
|
||||
const state: any = {
|
||||
selectedService: event.target.value,
|
||||
metricTypes,
|
||||
selectedMetricType,
|
||||
...await this.getLabelValues(selectedMetricType),
|
||||
...await this.getLabels(selectedMetricType),
|
||||
};
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
async onMetricTypeChange(event) {
|
||||
const state: any = { selectedMetricType: event.target.value, ...await this.getLabelValues(event.target.value) };
|
||||
const state: any = { selectedMetricType: event.target.value, ...await this.getLabels(event.target.value) };
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
@ -100,18 +102,23 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
this.props.onChange(queryModel, `Stackdriver - ${query.name}`);
|
||||
}
|
||||
|
||||
async getLabelValues(selectedMetricType, selectedQueryType = this.state.selectedQueryType) {
|
||||
async getLabels(selectedMetricType, selectedQueryType = this.state.selectedQueryType) {
|
||||
let result = { labels: this.state.labels, labelKey: this.state.labelKey };
|
||||
if (selectedMetricType && selectedQueryType === MetricFindQueryTypes.LabelValues) {
|
||||
const refId = 'StackdriverVariableQueryEditor';
|
||||
const response = await this.props.datasource.getLabels(selectedMetricType, refId);
|
||||
const labels = [...Object.keys(response.meta.resourceLabels), ...Object.keys(response.meta.metricLabels)];
|
||||
const labelKey = labels.some(l => l === this.state.labelKey) ? this.state.labelKey : labels[0];
|
||||
const labels = await getLabelKeys(this.props.datasource, selectedMetricType);
|
||||
const labelKey = labels.some(l => l === this.props.templateSrv.replace(this.state.labelKey))
|
||||
? this.state.labelKey
|
||||
: labels[0];
|
||||
result = { labels, labelKey };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
insertTemplateVariables(options) {
|
||||
const templateVariables = this.props.templateSrv.variables.map(v => ({ name: `$${v.name}`, value: `$${v.name}` }));
|
||||
return [...templateVariables, ...options];
|
||||
}
|
||||
|
||||
renderQueryTypeSwitch(queryType) {
|
||||
switch (queryType) {
|
||||
case MetricFindQueryTypes.MetricTypes:
|
||||
@ -136,14 +143,14 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
/>
|
||||
<SimpleSelect
|
||||
value={this.state.selectedMetricType}
|
||||
options={this.state.metricTypes}
|
||||
options={this.insertTemplateVariables(this.state.metricTypes)}
|
||||
onValueChange={e => this.onMetricTypeChange(e)}
|
||||
label="Metric Types"
|
||||
/>
|
||||
{queryType === MetricFindQueryTypes.LabelValues && (
|
||||
<SimpleSelect
|
||||
value={this.state.labelKey}
|
||||
options={this.state.labels.map(l => ({ value: l, name: l }))}
|
||||
options={this.insertTemplateVariables(this.state.labels.map(l => ({ value: l, name: l })))}
|
||||
onValueChange={e => this.onLabelKeyChange(e)}
|
||||
label="Label Keys"
|
||||
/>
|
||||
@ -162,7 +169,7 @@ export class StackdriverVariableQueryEditor extends PureComponent<VariableQueryP
|
||||
/>
|
||||
<SimpleSelect
|
||||
value={this.state.selectedMetricType}
|
||||
options={this.state.metricTypes}
|
||||
options={this.insertTemplateVariables(this.state.metricTypes)}
|
||||
onValueChange={e => this.onMetricTypeChange(e)}
|
||||
label="Metric Types"
|
||||
/>
|
||||
|
@ -3,12 +3,12 @@ import { alignOptions, aggOptions } from './constants';
|
||||
export const getMetricTypesByService = (metricDescriptors, service) =>
|
||||
metricDescriptors.filter(m => m.service === service);
|
||||
|
||||
export const getMetricTypes = (metricDescriptors, metricType, selectedService) => {
|
||||
export const getMetricTypes = (metricDescriptors, metricType, interpolatedMetricType, selectedService) => {
|
||||
const metricTypes = getMetricTypesByService(metricDescriptors, selectedService).map(m => ({
|
||||
value: m.type,
|
||||
name: m.displayName,
|
||||
}));
|
||||
const metricTypeExistInArray = metricTypes.some(m => m.value === metricType);
|
||||
const metricTypeExistInArray = metricTypes.some(m => m.value === interpolatedMetricType);
|
||||
const selectedMetricType = metricTypeExistInArray ? metricType : metricTypes[0].value;
|
||||
return {
|
||||
metricTypes,
|
||||
@ -31,3 +31,15 @@ export const getAggregationOptionsByMetric = (valueType, metricKind) => {
|
||||
return i.valueTypes.indexOf(valueType) !== -1 && i.metricKinds.indexOf(metricKind) !== -1;
|
||||
});
|
||||
};
|
||||
|
||||
export const getLabelKeys = async (datasource, selectedMetricType) => {
|
||||
const refId = 'handleLabelKeysQuery';
|
||||
const response = await datasource.getLabels(selectedMetricType, refId);
|
||||
const labelKeys = response.meta
|
||||
? [
|
||||
...Object.keys(response.meta.resourceLabels).map(l => `resource.label.${l}`),
|
||||
...Object.keys(response.meta.metricLabels).map(l => `metric.label.${l}`),
|
||||
]
|
||||
: [];
|
||||
return labelKeys;
|
||||
};
|
||||
|
@ -65,7 +65,9 @@ export class StackdriverAggregationCtrl {
|
||||
const selectedAlignment = this.alignOptions.find(
|
||||
ap => ap.value === this.templateSrv.replace(this.target.aggregation.perSeriesAligner)
|
||||
);
|
||||
return `${kbn.secondsToHms(this.$scope.alignmentPeriod)} interval (${selectedAlignment.text})`;
|
||||
return `${kbn.secondsToHms(this.$scope.alignmentPeriod)} interval (${
|
||||
selectedAlignment ? selectedAlignment.text : ''
|
||||
})`;
|
||||
}
|
||||
|
||||
deselectAggregationOption(notValidOptionValue: string) {
|
||||
|
@ -104,4 +104,5 @@ export interface VariableQueryProps {
|
||||
query: any;
|
||||
onChange: (query: any, definition: string) => void;
|
||||
datasource: any;
|
||||
templateSrv: any;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user