Просмотр исходного кода

Changed Prometheus interval-alignment to cover whole panel range

* the existing query date alignment shifts the range forward to match
a multiple epoch of the interval, but keeps the range length the same,
the result is that the start date is shifted forward as well, leaving a
gap in the graph (or a zero-line when null-as-zero was set, issue #12024)
* this pr extends the aligned range to cover the original start date as
well
David Kaltschmidt 7 лет назад
Родитель
Сommit
750ea9bbdd

+ 10 - 10
public/app/plugins/datasource/prometheus/datasource.ts

@@ -7,6 +7,15 @@ import PrometheusMetricFindQuery from './metric_find_query';
 import { ResultTransformer } from './result_transformer';
 import { BackendSrv } from 'app/core/services/backend_srv';
 
+export function alignRange(start, end, step) {
+  const alignedEnd = Math.ceil(end / step) * step;
+  const alignedStart = Math.floor(start / step) * step;
+  return {
+    end: alignedEnd,
+    start: alignedStart,
+  };
+}
+
 export function prometheusRegularEscape(value) {
   return value.replace(/'/g, "\\\\'");
 }
@@ -109,15 +118,6 @@ export class PrometheusDatasource {
     return this.templateSrv.variableExists(target.expr);
   }
 
-  clampRange(start, end, step) {
-    const clampedEnd = Math.ceil(end / step) * step;
-    const clampedRange = Math.floor((end - start) / step) * step;
-    return {
-      end: clampedEnd,
-      start: clampedEnd - clampedRange,
-    };
-  }
-
   query(options) {
     var start = this.getPrometheusTime(options.range.from, false);
     var end = this.getPrometheusTime(options.range.to, true);
@@ -205,7 +205,7 @@ export class PrometheusDatasource {
     query.requestId = options.panelId + target.refId;
 
     // Align query interval with step
-    const adjusted = this.clampRange(start, end, query.step);
+    const adjusted = alignRange(start, end, query.step);
     query.start = adjusted.start;
     query.end = adjusted.end;
 

+ 24 - 1
public/app/plugins/datasource/prometheus/specs/datasource.jest.ts

@@ -1,7 +1,7 @@
 import _ from 'lodash';
 import moment from 'moment';
 import q from 'q';
-import { PrometheusDatasource, prometheusSpecialRegexEscape, prometheusRegularEscape } from '../datasource';
+import { alignRange, PrometheusDatasource, prometheusSpecialRegexEscape, prometheusRegularEscape } from '../datasource';
 
 describe('PrometheusDatasource', () => {
   let ctx: any = {};
@@ -142,6 +142,29 @@ describe('PrometheusDatasource', () => {
     });
   });
 
+  describe('alignRange', function() {
+    it('does not modify already aligned intervals with perfect step', function() {
+      const range = alignRange(0, 3, 3);
+      expect(range.start).toEqual(0);
+      expect(range.end).toEqual(3);
+    });
+    it('does modify end-aligned intervals to reflect number of steps possible', function() {
+      const range = alignRange(1, 6, 3);
+      expect(range.start).toEqual(0);
+      expect(range.end).toEqual(6);
+    });
+    it('does align intervals that are a multiple of steps', function() {
+      const range = alignRange(1, 4, 3);
+      expect(range.start).toEqual(0);
+      expect(range.end).toEqual(6);
+    });
+    it('does align intervals that are not a multiple of steps', function() {
+      const range = alignRange(1, 5, 3);
+      expect(range.start).toEqual(0);
+      expect(range.end).toEqual(6);
+    });
+  });
+
   describe('Prometheus regular escaping', function() {
     it('should not escape simple string', function() {
       expect(prometheusRegularEscape('cryptodepression')).toEqual('cryptodepression');

+ 8 - 31
public/app/plugins/datasource/prometheus/specs/datasource_specs.ts

@@ -44,7 +44,7 @@ describe('PrometheusDatasource', function() {
     };
     // Interval alignment with step
     var urlExpected =
-      'proxied/api/v1/query_range?query=' + encodeURIComponent('test{job="testjob"}') + '&start=120&end=240&step=60';
+      'proxied/api/v1/query_range?query=' + encodeURIComponent('test{job="testjob"}') + '&start=60&end=240&step=60';
     var response = {
       status: 'success',
       data: {
@@ -181,7 +181,7 @@ describe('PrometheusDatasource', function() {
     var urlExpected =
       'proxied/api/v1/query_range?query=' +
       encodeURIComponent('ALERTS{alertstate="firing"}') +
-      '&start=120&end=180&step=60';
+      '&start=60&end=180&step=60';
     var options = {
       annotation: {
         expr: 'ALERTS{alertstate="firing"}',
@@ -348,7 +348,7 @@ describe('PrometheusDatasource', function() {
         interval: '5s',
       };
       // times get rounded up to interval
-      var urlExpected = 'proxied/api/v1/query_range?query=test&start=100&end=450&step=50';
+      var urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=450&step=50';
       ctx.$httpBackend.expect('GET', urlExpected).respond(response);
       ctx.ds.query(query);
       ctx.$httpBackend.verifyNoOutstandingExpectation();
@@ -384,8 +384,8 @@ describe('PrometheusDatasource', function() {
         ],
         interval: '10s',
       };
-      // times get rounded up to interval
-      var urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=200&end=500&step=100';
+      // times get aligned to interval
+      var urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=500&step=100';
       ctx.$httpBackend.expect('GET', urlExpected).respond(response);
       ctx.ds.query(query);
       ctx.$httpBackend.verifyNoOutstandingExpectation();
@@ -511,7 +511,7 @@ describe('PrometheusDatasource', function() {
         },
       };
       var urlExpected =
-        'proxied/api/v1/query_range?query=' + encodeURIComponent('rate(test[100s])') + '&start=200&end=500&step=100';
+        'proxied/api/v1/query_range?query=' + encodeURIComponent('rate(test[100s])') + '&start=0&end=500&step=100';
       ctx.$httpBackend.expect('GET', urlExpected).respond(response);
       ctx.ds.query(query);
       ctx.$httpBackend.verifyNoOutstandingExpectation();
@@ -539,7 +539,7 @@ describe('PrometheusDatasource', function() {
         },
       };
       var urlExpected =
-        'proxied/api/v1/query_range?query=' + encodeURIComponent('rate(test[50s])') + '&start=100&end=450&step=50';
+        'proxied/api/v1/query_range?query=' + encodeURIComponent('rate(test[50s])') + '&start=50&end=450&step=50';
       ctx.$httpBackend.expect('GET', urlExpected).respond(response);
       ctx.ds.query(query);
       ctx.$httpBackend.verifyNoOutstandingExpectation();
@@ -613,29 +613,6 @@ describe('PrometheusDatasource', function() {
       expect(query.scopedVars.__interval_ms.value).to.be(5 * 1000);
     });
   });
-
-  describe('Step alignment of intervals', function() {
-    it('does not modify already aligned intervals with perfect step', function() {
-      const range = ctx.ds.clampRange(0, 3, 3);
-      expect(range.start).to.be(0);
-      expect(range.end).to.be(3);
-    });
-    it('does modify end-aligned intervals to reflect number of steps possible', function() {
-      const range = ctx.ds.clampRange(1, 6, 3);
-      expect(range.start).to.be(3);
-      expect(range.end).to.be(6);
-    });
-    it('does align intervals that are a multiple of steps', function() {
-      const range = ctx.ds.clampRange(1, 4, 3);
-      expect(range.start).to.be(3);
-      expect(range.end).to.be(6);
-    });
-    it('does align intervals that are not a multiple of steps', function() {
-      const range = ctx.ds.clampRange(1, 5, 3);
-      expect(range.start).to.be(3);
-      expect(range.end).to.be(6);
-    });
-  });
 });
 
 describe('PrometheusDatasource for POST', function() {
@@ -667,7 +644,7 @@ describe('PrometheusDatasource for POST', function() {
     var urlExpected = 'proxied/api/v1/query_range';
     var dataExpected = $.param({
       query: 'test{job="testjob"}',
-      start: 2 * 60,
+      start: 1 * 60,
       end: 3 * 60,
       step: 60,
     });