From 750ea9bbdd002ab959d255a7690853298ef26e49 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 25 May 2018 16:46:38 +0200 Subject: [PATCH] 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 --- .../datasource/prometheus/datasource.ts | 20 +++++----- .../prometheus/specs/datasource.jest.ts | 25 +++++++++++- .../prometheus/specs/datasource_specs.ts | 39 ++++--------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index a52f3aefa2e..ff7dc1b150c 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/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; diff --git a/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts b/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts index 2ab2895d731..0157322da58 100644 --- a/public/app/plugins/datasource/prometheus/specs/datasource.jest.ts +++ b/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'); diff --git a/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts b/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts index ef51ff69206..c5da671b757 100644 --- a/public/app/plugins/datasource/prometheus/specs/datasource_specs.ts +++ b/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, });