diff --git a/public/app/plugins/datasource/influxdb-ifql/datasource.ts b/public/app/plugins/datasource/influxdb-ifql/datasource.ts index bd3cb7e2d5b..654778475ca 100644 --- a/public/app/plugins/datasource/influxdb-ifql/datasource.ts +++ b/public/app/plugins/datasource/influxdb-ifql/datasource.ts @@ -54,23 +54,32 @@ export default class InfluxDatasource { this.supportMetrics = true; } - query(options) { + prepareQueries(options) { const targets = _.cloneDeep(options.targets); - const queryTargets = targets.filter(t => t.query); + const timeFilter = this.getTimeFilter(options); + options.scopedVars.range = { value: timeFilter }; + + // Filter empty queries and replace grafana variables + const queryTargets = targets.filter(t => t.query).map(t => { + const interpolated = this.templateSrv.replace(t.query, options.scopedVars); + return { + ...t, + query: interpolated, + }; + }); + + return queryTargets; + } + + query(options) { + const queryTargets = this.prepareQueries(options); if (queryTargets.length === 0) { return Promise.resolve({ data: [] }); } - // replace grafana variables - const timeFilter = this.getTimeFilter(options); - options.scopedVars.timeFilter = { value: timeFilter }; - const queries = queryTargets.map(target => { const { query, resultFormat } = target; - // TODO replace templated variables - // allQueries = this.templateSrv.replace(allQueries, scopedVars); - if (resultFormat === 'table') { return ( this._seriesQuery(query, options) @@ -224,32 +233,29 @@ export default class InfluxDatasource { } getTimeFilter(options) { - var from = this.getInfluxTime(options.rangeRaw.from, false); - var until = this.getInfluxTime(options.rangeRaw.to, true); - var fromIsAbsolute = from[from.length - 1] === 'ms'; - - if (until === 'now()' && !fromIsAbsolute) { - return 'time >= ' + from; + const from = this.getInfluxTime(options.rangeRaw.from, false); + const to = this.getInfluxTime(options.rangeRaw.to, true); + if (to === 'now') { + return `start: ${from}`; } - - return 'time >= ' + from + ' and time <= ' + until; + return `start: ${from}, stop: ${to}`; } getInfluxTime(date, roundUp) { if (_.isString(date)) { if (date === 'now') { - return 'now()'; + return date; } - var parts = /^now-(\d+)([d|h|m|s])$/.exec(date); + const parts = /^now\s*-\s*(\d+)([d|h|m|s])$/.exec(date); if (parts) { - var amount = parseInt(parts[1]); - var unit = parts[2]; - return 'now() - ' + amount + unit; + const amount = parseInt(parts[1]); + const unit = parts[2]; + return '-' + amount + unit; } date = dateMath.parse(date, roundUp); } - return date.valueOf() + 'ms'; + return date.toISOString(); } } diff --git a/public/app/plugins/datasource/influxdb-ifql/module.ts b/public/app/plugins/datasource/influxdb-ifql/module.ts index 5997a7d061b..4bbfbf7e8ac 100644 --- a/public/app/plugins/datasource/influxdb-ifql/module.ts +++ b/public/app/plugins/datasource/influxdb-ifql/module.ts @@ -1,5 +1,5 @@ import InfluxDatasource from './datasource'; -import { InfluxQueryCtrl } from './query_ctrl'; +import { InfluxIfqlQueryCtrl } from './query_ctrl'; class InfluxConfigCtrl { static templateUrl = 'partials/config.html'; @@ -11,7 +11,7 @@ class InfluxAnnotationsQueryCtrl { export { InfluxDatasource as Datasource, - InfluxQueryCtrl as QueryCtrl, + InfluxIfqlQueryCtrl as QueryCtrl, InfluxConfigCtrl as ConfigCtrl, InfluxAnnotationsQueryCtrl as AnnotationsQueryCtrl, }; diff --git a/public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts b/public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts index 950a3feb58e..edd00b37db8 100644 --- a/public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts +++ b/public/app/plugins/datasource/influxdb-ifql/query_ctrl.ts @@ -1,6 +1,12 @@ import { QueryCtrl } from 'app/plugins/sdk'; -export class InfluxQueryCtrl extends QueryCtrl { +function makeDefaultQuery(database) { + return `from(db: "${database}") + |> range($range) + |> limit(n:1000) +`; +} +export class InfluxIfqlQueryCtrl extends QueryCtrl { static templateUrl = 'partials/query.editor.html'; resultFormats: any[]; @@ -8,6 +14,10 @@ export class InfluxQueryCtrl extends QueryCtrl { /** @ngInject **/ constructor($scope, $injector) { super($scope, $injector); + + if (this.target.query === undefined) { + this.target.query = makeDefaultQuery(this.datasource.database); + } this.resultFormats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }]; } diff --git a/public/app/plugins/datasource/influxdb-ifql/specs/datasource.jest.ts b/public/app/plugins/datasource/influxdb-ifql/specs/datasource.jest.ts new file mode 100644 index 00000000000..d20e3884882 --- /dev/null +++ b/public/app/plugins/datasource/influxdb-ifql/specs/datasource.jest.ts @@ -0,0 +1,53 @@ +import moment from 'moment'; + +import { TemplateSrv } from 'app/features/templating/template_srv'; + +import Datasource from '../datasource'; + +describe('InfluxDB (IFQL)', () => { + const templateSrv = new TemplateSrv(); + const ds = new Datasource({ url: '' }, {}, templateSrv); + const DEFAULT_OPTIONS = { + rangeRaw: { to: 'now', from: 'now - 3h' }, + scopedVars: {}, + targets: [], + }; + + let queries: any[]; + + describe('prepareQueries()', () => { + it('filters empty queries', () => { + queries = ds.prepareQueries(DEFAULT_OPTIONS); + expect(queries.length).toBe(0); + + queries = ds.prepareQueries({ + ...DEFAULT_OPTIONS, + targets: [{ query: '' }], + }); + expect(queries.length).toBe(0); + }); + + it('replaces $range variable', () => { + queries = ds.prepareQueries({ + ...DEFAULT_OPTIONS, + targets: [{ query: 'from(db: "test") |> range($range)' }], + }); + expect(queries.length).toBe(1); + expect(queries[0].query).toBe('from(db: "test") |> range(start: -3h)'); + }); + + it('replaces $range variable with custom dates', () => { + const to = moment(); + const from = moment().subtract(1, 'hours'); + queries = ds.prepareQueries({ + ...DEFAULT_OPTIONS, + rangeRaw: { to, from }, + targets: [{ query: 'from(db: "test") |> range($range)' }], + }); + expect(queries.length).toBe(1); + const start = from.toISOString(); + const stop = to.toISOString(); + expect(queries[0].query).toBe(`from(db: "test") |> range(start: ${start}, stop: ${stop})`); + }); + }); +});