Browse Source

IFQL range variable expansion

David Kaltschmidt 7 years ago
parent
commit
1d587450b3

+ 29 - 23
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();
   }
 }

+ 2 - 2
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,
 };

+ 11 - 1
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' }];
   }
 

+ 53 - 0
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})`);
+    });
+  });
+});