diff --git a/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx b/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx index 94521041416..c3bd9212b21 100644 --- a/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx +++ b/public/app/plugins/datasource/stackdriver/components/QueryEditor.tsx @@ -10,21 +10,21 @@ import { Alignments } from './Alignments'; import { AlignmentPeriods } from './AlignmentPeriods'; import { AliasBy } from './AliasBy'; import { Help } from './Help'; -import { Target, MetricDescriptor } from '../types'; +import { StackdriverQuery, MetricDescriptor } from '../types'; import { getAlignmentPickerData } from '../functions'; import StackdriverDatasource from '../datasource'; import { SelectOptionItem } from '@grafana/ui'; export interface Props { - onQueryChange: (target: Target) => void; + onQueryChange: (target: StackdriverQuery) => void; onExecuteQuery: () => void; - target: Target; + target: StackdriverQuery; events: any; datasource: StackdriverDatasource; templateSrv: TemplateSrv; } -interface State extends Target { +interface State extends StackdriverQuery { alignOptions: SelectOptionItem[]; lastQuery: string; lastQueryError: string; diff --git a/public/app/plugins/datasource/stackdriver/datasource.ts b/public/app/plugins/datasource/stackdriver/datasource.ts index 025955105a7..4c1f07e0a06 100644 --- a/public/app/plugins/datasource/stackdriver/datasource.ts +++ b/public/app/plugins/datasource/stackdriver/datasource.ts @@ -2,9 +2,10 @@ import { stackdriverUnitMappings } from './constants'; import appEvents from 'app/core/app_events'; import _ from 'lodash'; import StackdriverMetricFindQuery from './StackdriverMetricFindQuery'; -import { MetricDescriptor } from './types'; +import { StackdriverQuery, MetricDescriptor } from './types'; +import { DataSourceApi, DataQueryOptions } from '@grafana/ui/src/types'; -export default class StackdriverDatasource { +export default class StackdriverDatasource implements DataSourceApi { id: number; url: string; baseUrl: string; @@ -39,9 +40,7 @@ export default class StackdriverDatasource { alignmentPeriod: this.templateSrv.replace(t.alignmentPeriod, options.scopedVars || {}), groupBys: this.interpolateGroupBys(t.groupBys, options.scopedVars), view: t.view || 'FULL', - filters: (t.filters || []).map(f => { - return this.templateSrv.replace(f, options.scopedVars || {}); - }), + filters: this.interpolateFilters(t.filters, options.scopedVars), aliasBy: this.templateSrv.replace(t.aliasBy, options.scopedVars || {}), type: 'timeSeriesQuery', }; @@ -63,7 +62,13 @@ export default class StackdriverDatasource { } } - async getLabels(metricType, refId) { + interpolateFilters(filters: string[], scopedVars: object) { + return (filters || []).map(f => { + return this.templateSrv.replace(f, scopedVars || {}, 'regex'); + }); + } + + async getLabels(metricType: string, refId: string) { const response = await this.getTimeSeries({ targets: [ { @@ -103,7 +108,7 @@ export default class StackdriverDatasource { return unit; } - async query(options) { + async query(options: DataQueryOptions) { const result = []; const data = await this.getTimeSeries(options); if (data.results) { diff --git a/public/app/plugins/datasource/stackdriver/query_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_ctrl.ts index c6a8a4d9782..3a2d0bb970a 100644 --- a/public/app/plugins/datasource/stackdriver/query_ctrl.ts +++ b/public/app/plugins/datasource/stackdriver/query_ctrl.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import { QueryCtrl } from 'app/plugins/sdk'; -import { Target } from './types'; +import { StackdriverQuery } from './types'; import { TemplateSrv } from 'app/features/templating/template_srv'; export class StackdriverQueryCtrl extends QueryCtrl { @@ -16,7 +16,7 @@ export class StackdriverQueryCtrl extends QueryCtrl { this.onExecuteQuery = this.onExecuteQuery.bind(this); } - onQueryChange(target: Target) { + onQueryChange(target: StackdriverQuery) { Object.assign(this.target, target); } diff --git a/public/app/plugins/datasource/stackdriver/specs/datasource.test.ts b/public/app/plugins/datasource/stackdriver/specs/datasource.test.ts index 46cdd77b7a9..032f10d8ca5 100644 --- a/public/app/plugins/datasource/stackdriver/specs/datasource.test.ts +++ b/public/app/plugins/datasource/stackdriver/specs/datasource.test.ts @@ -1,7 +1,8 @@ import StackdriverDataSource from '../datasource'; import { metricDescriptors } from './testData'; import moment from 'moment'; -import { TemplateSrvStub } from 'test/specs/helpers'; +import { TemplateSrv } from 'app/features/templating/template_srv'; +import { CustomVariable } from 'app/features/templating/all'; describe('StackdriverDataSource', () => { const instanceSettings = { @@ -9,7 +10,7 @@ describe('StackdriverDataSource', () => { defaultProject: 'testproject', }, }; - const templateSrv = new TemplateSrvStub(); + const templateSrv = new TemplateSrv(); const timeSrv = {}; describe('when performing testDataSource', () => { @@ -154,15 +155,41 @@ describe('StackdriverDataSource', () => { }); }); + describe('when interpolating a template variable for the filter', () => { + let interpolated; + describe('and is single value variable', () => { + beforeEach(() => { + const filterTemplateSrv = initTemplateSrv('filtervalue1'); + const ds = new StackdriverDataSource(instanceSettings, {}, filterTemplateSrv, timeSrv); + interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '${test}'], {}); + }); + + it('should replace the variable with the value', () => { + expect(interpolated.length).toBe(3); + expect(interpolated[2]).toBe('filtervalue1'); + }); + }); + + describe('and is multi value variable', () => { + beforeEach(() => { + const filterTemplateSrv = initTemplateSrv(['filtervalue1', 'filtervalue2'], true); + const ds = new StackdriverDataSource(instanceSettings, {}, filterTemplateSrv, timeSrv); + interpolated = ds.interpolateFilters(['resource.label.zone', '=~', '[[test]]'], {}); + }); + + it('should replace the variable with a regex expression', () => { + expect(interpolated[2]).toBe('(filtervalue1|filtervalue2)'); + }); + }); + }); + describe('when interpolating a template variable for group bys', () => { let interpolated; describe('and is single value variable', () => { beforeEach(() => { - templateSrv.data = { - test: 'groupby1', - }; - const ds = new StackdriverDataSource(instanceSettings, {}, templateSrv, timeSrv); + const groupByTemplateSrv = initTemplateSrv('groupby1'); + const ds = new StackdriverDataSource(instanceSettings, {}, groupByTemplateSrv, timeSrv); interpolated = ds.interpolateGroupBys(['[[test]]'], {}); }); @@ -174,10 +201,8 @@ describe('StackdriverDataSource', () => { describe('and is multi value variable', () => { beforeEach(() => { - templateSrv.data = { - test: 'groupby1,groupby2', - }; - const ds = new StackdriverDataSource(instanceSettings, {}, templateSrv, timeSrv); + const groupByTemplateSrv = initTemplateSrv(['groupby1', 'groupby2'], true); + const ds = new StackdriverDataSource(instanceSettings, {}, groupByTemplateSrv, timeSrv); interpolated = ds.interpolateGroupBys(['[[test]]'], {}); }); @@ -241,3 +266,19 @@ describe('StackdriverDataSource', () => { }); }); }); +function initTemplateSrv(values: any, multi = false) { + const templateSrv = new TemplateSrv(); + templateSrv.init([ + new CustomVariable( + { + name: 'test', + current: { + value: values, + }, + multi: multi, + }, + {} + ), + ]); + return templateSrv; +} diff --git a/public/app/plugins/datasource/stackdriver/types.ts b/public/app/plugins/datasource/stackdriver/types.ts index 29b12b4289d..b9a6893d4bd 100644 --- a/public/app/plugins/datasource/stackdriver/types.ts +++ b/public/app/plugins/datasource/stackdriver/types.ts @@ -1,3 +1,5 @@ +import { DataQuery } from '@grafana/ui/src/types'; + export enum MetricFindQueryTypes { Services = 'services', MetricTypes = 'metricTypes', @@ -20,20 +22,22 @@ export interface VariableQueryData { services: Array<{ value: string; name: string }>; } -export interface Target { - defaultProject: string; - unit: string; +export interface StackdriverQuery extends DataQuery { + defaultProject?: string; + unit?: string; metricType: string; - service: string; + service?: string; refId: string; crossSeriesReducer: string; - alignmentPeriod: string; + alignmentPeriod?: string; perSeriesAligner: string; - groupBys: string[]; - filters: string[]; - aliasBy: string; + groupBys?: string[]; + filters?: string[]; + aliasBy?: string; metricKind: string; valueType: string; + datasourceId?: number; + view?: string; } export interface AnnotationTarget {