From 3a8113889a7ed4dc67e1464c0a74de74d40d5145 Mon Sep 17 00:00:00 2001 From: Konstantin Kornienko <50887992+konstantin-kornienko@users.noreply.github.com> Date: Wed, 18 Dec 2024 23:27:07 +0300 Subject: [PATCH] Annotations: Fix `min step` parameter interpolation in Prometheus annotations query (#97734) * Fix `min step` parameter interpolation in prometheus annotations query Looks like the step is interpolated in annotationQuery, but not interpolated in processAnnotationResponse. Fixing that. * Update packages/grafana-prometheus/src/datasource.ts Co-authored-by: Brendan O'Handley * Added test for non-default step * modified tests * apply prettier manually --------- Co-authored-by: Brendan O'Handley --- .../grafana-prometheus/src/datasource.test.ts | 31 ++++++++++++++++++- packages/grafana-prometheus/src/datasource.ts | 6 +++- .../src/test/__mocks__/datasource.ts | 4 +++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/packages/grafana-prometheus/src/datasource.test.ts b/packages/grafana-prometheus/src/datasource.test.ts index 664206c9f1f..a8da9fa6ec0 100644 --- a/packages/grafana-prometheus/src/datasource.test.ts +++ b/packages/grafana-prometheus/src/datasource.test.ts @@ -1051,9 +1051,13 @@ describe('PrometheusDatasource2', () => { }, } as unknown as AnnotationQueryRequest; - async function runAnnotationQuery(data: number[][]) { + async function runAnnotationQuery(data: number[][], overrideStep?: string) { let response = createAnnotationResponse(); response.data.results['X'].frames[0].data.values = data; + if (overrideStep) { + const meta = response.data.results['X'].frames[0].schema.meta; + meta.executedQueryString = meta.executedQueryString.replace('1m0s', overrideStep); + } options.annotation.useValueForTime = false; fetchMock.mockImplementation(() => of(response)); @@ -1093,6 +1097,31 @@ describe('PrometheusDatasource2', () => { const results = await runAnnotationQuery([[2 * 60000], [1]]); expect(results.map((result) => [result.time, result.timeEnd])).toEqual([[120000, 120000]]); }); + + describe('should group annotations over wider range when the step grows larger', () => { + const data: number[][] = [ + [1 * 120000, 2 * 120000, 3 * 120000, 4 * 120000, 5 * 120000, 6 * 120000], + [1, 1, 0, 0, 1, 1], + ]; + + it('should not group annotations with the default step', async () => { + const results = await runAnnotationQuery(data); + expect(results.map((result) => [result.time, result.timeEnd])).toEqual([ + [120000, 120000], + [240000, 240000], + [600000, 600000], + [720000, 720000], + ]); + }); + + it('should group annotations with larger step', async () => { + const results = await runAnnotationQuery(data, '2m0s'); + expect(results.map((result) => [result.time, result.timeEnd])).toEqual([ + [120000, 240000], + [600000, 720000], + ]); + }); + }); }); describe('with template variables', () => { diff --git a/packages/grafana-prometheus/src/datasource.ts b/packages/grafana-prometheus/src/datasource.ts index a2e4b2bd953..c7653f5702f 100644 --- a/packages/grafana-prometheus/src/datasource.ts +++ b/packages/grafana-prometheus/src/datasource.ts @@ -537,7 +537,11 @@ export class PrometheusDatasource const annotation = options.annotation; const { tagKeys = '', titleFormat = '', textFormat = '' } = annotation; - const step = rangeUtil.intervalToSeconds(annotation.step || ANNOTATION_QUERY_STEP_DEFAULT) * 1000; + const input = frames[0].meta?.executedQueryString || ''; + const regex = /Step:\s*([\d\w]+)/; + const match = input.match(regex); + const stepValue = match ? match[1] : null; + const step = rangeUtil.intervalToSeconds(stepValue || ANNOTATION_QUERY_STEP_DEFAULT) * 1000; const tagKeysArray = tagKeys.split(','); const eventList: AnnotationEvent[] = []; diff --git a/packages/grafana-prometheus/src/test/__mocks__/datasource.ts b/packages/grafana-prometheus/src/test/__mocks__/datasource.ts index e4e4fb21e3c..6befc818c38 100644 --- a/packages/grafana-prometheus/src/test/__mocks__/datasource.ts +++ b/packages/grafana-prometheus/src/test/__mocks__/datasource.ts @@ -108,6 +108,10 @@ export function createAnnotationResponse() { schema: { name: 'bar', refId: 'X', + meta: { + typeVersion: [0, 0], + executedQueryString: 'Expr: ALERTS{}\nStep: 1m0s', + }, fields: [ { name: 'Time',