Commit 9008fcc7 by David Committed by GitHub

fix(prometheus): Change aligment of range queries (#16110)

- future alignment cause issues with rate charts and the display of last
values
- this change modifies the alignment to use the last available aligned
end date and no longer possibly requests data from the future
parent 8847da0d
...@@ -224,7 +224,8 @@ export class PrometheusDatasource implements DataSourceApi<PromQuery> { ...@@ -224,7 +224,8 @@ export class PrometheusDatasource implements DataSourceApi<PromQuery> {
query.expr = this.templateSrv.replace(expr, scopedVars, this.interpolateQueryExpr); query.expr = this.templateSrv.replace(expr, scopedVars, this.interpolateQueryExpr);
query.requestId = options.panelId + target.refId; query.requestId = options.panelId + target.refId;
// Align query interval with step // Align query interval with step to allow query caching and to ensure
// that about-same-time query results look the same.
const adjusted = alignRange(start, end, query.step); const adjusted = alignRange(start, end, query.step);
query.start = adjusted.start; query.start = adjusted.start;
query.end = adjusted.end; query.end = adjusted.end;
...@@ -497,8 +498,15 @@ export class PrometheusDatasource implements DataSourceApi<PromQuery> { ...@@ -497,8 +498,15 @@ export class PrometheusDatasource implements DataSourceApi<PromQuery> {
} }
} }
export function alignRange(start, end, step) { /**
const alignedEnd = Math.ceil(end / step) * step; * Align query range to step.
* Rounds start and end down to a multiple of step.
* @param start Timestamp marking the beginning of the range.
* @param end Timestamp marking the end of the range.
* @param step Interval to align start and end with.
*/
export function alignRange(start: number, end: number, step: number): { end: number; start: number } {
const alignedEnd = Math.floor(end / step) * step;
const alignedStart = Math.floor(start / step) * step; const alignedStart = Math.floor(start / step) * step;
return { return {
end: alignedEnd, end: alignedEnd,
......
...@@ -206,12 +206,12 @@ describe('PrometheusDatasource', () => { ...@@ -206,12 +206,12 @@ describe('PrometheusDatasource', () => {
it('does align intervals that are a multiple of steps', () => { it('does align intervals that are a multiple of steps', () => {
const range = alignRange(1, 4, 3); const range = alignRange(1, 4, 3);
expect(range.start).toEqual(0); expect(range.start).toEqual(0);
expect(range.end).toEqual(6); expect(range.end).toEqual(3);
}); });
it('does align intervals that are not a multiple of steps', () => { it('does align intervals that are not a multiple of steps', () => {
const range = alignRange(1, 5, 3); const range = alignRange(1, 5, 3);
expect(range.start).toEqual(0); expect(range.start).toEqual(0);
expect(range.end).toEqual(6); expect(range.end).toEqual(3);
}); });
}); });
...@@ -360,7 +360,7 @@ describe('PrometheusDatasource', () => { ...@@ -360,7 +360,7 @@ describe('PrometheusDatasource', () => {
}; };
// Interval alignment with step // Interval alignment with step
const urlExpected = const urlExpected =
'proxied/api/v1/query_range?query=' + encodeURIComponent('test{job="testjob"}') + '&start=60&end=240&step=60'; 'proxied/api/v1/query_range?query=' + encodeURIComponent('test{job="testjob"}') + '&start=60&end=180&step=60';
beforeEach(async () => { beforeEach(async () => {
const response = { const response = {
...@@ -788,7 +788,7 @@ describe('PrometheusDatasource', () => { ...@@ -788,7 +788,7 @@ describe('PrometheusDatasource', () => {
interval: '5s', interval: '5s',
}; };
// times get rounded up to interval // times get rounded up to interval
const urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=450&step=50'; const urlExpected = 'proxied/api/v1/query_range?query=test&start=50&end=400&step=50';
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response)); backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv); ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
await ctx.ds.query(query); await ctx.ds.query(query);
...@@ -831,7 +831,7 @@ describe('PrometheusDatasource', () => { ...@@ -831,7 +831,7 @@ describe('PrometheusDatasource', () => {
interval: '10s', interval: '10s',
}; };
// times get aligned to interval // times get aligned to interval
const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=500&step=100'; const urlExpected = 'proxied/api/v1/query_range?query=test' + '&start=0&end=400&step=100';
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response)); backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv); ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
await ctx.ds.query(query); await ctx.ds.query(query);
...@@ -996,7 +996,7 @@ describe('PrometheusDatasource', () => { ...@@ -996,7 +996,7 @@ describe('PrometheusDatasource', () => {
const urlExpected = const urlExpected =
'proxied/api/v1/query_range?query=' + 'proxied/api/v1/query_range?query=' +
encodeURIComponent('rate(test[$__interval])') + encodeURIComponent('rate(test[$__interval])') +
'&start=0&end=500&step=100'; '&start=0&end=400&step=100';
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response)); backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
templateSrv.replace = jest.fn(str => str); templateSrv.replace = jest.fn(str => str);
ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv); ctx.ds = new PrometheusDatasource(instanceSettings, q, backendSrv as any, templateSrv, timeSrv);
...@@ -1041,7 +1041,7 @@ describe('PrometheusDatasource', () => { ...@@ -1041,7 +1041,7 @@ describe('PrometheusDatasource', () => {
const urlExpected = const urlExpected =
'proxied/api/v1/query_range?query=' + 'proxied/api/v1/query_range?query=' +
encodeURIComponent('rate(test[$__interval])') + encodeURIComponent('rate(test[$__interval])') +
'&start=50&end=450&step=50'; '&start=50&end=400&step=50';
templateSrv.replace = jest.fn(str => str); templateSrv.replace = jest.fn(str => str);
backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response)); backendSrv.datasourceRequest = jest.fn(() => Promise.resolve(response));
...@@ -1166,7 +1166,7 @@ describe('PrometheusDatasource for POST', () => { ...@@ -1166,7 +1166,7 @@ describe('PrometheusDatasource for POST', () => {
const dataExpected = { const dataExpected = {
query: 'test{job="testjob"}', query: 'test{job="testjob"}',
start: 1 * 60, start: 1 * 60,
end: 3 * 60, end: 2 * 60,
step: 60, step: 60,
}; };
const query = { const query = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment