From 1c358de1902923e060a1fc190be89fa57cbc11e7 Mon Sep 17 00:00:00 2001 From: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com> Date: Thu, 20 Jul 2023 07:09:40 -0500 Subject: [PATCH] Prometheus: Fix heatmap query format (#71971) Check first numeric field instead of name: Value --------- Co-authored-by: ismail simsek --- packages/grafana-data/src/types/dataFrame.ts | 1 + .../prometheus/result_transformer.test.ts | 80 ++++++++++++++----- .../prometheus/result_transformer.ts | 9 ++- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/packages/grafana-data/src/types/dataFrame.ts b/packages/grafana-data/src/types/dataFrame.ts index b46e912a5f0..2ef26c3eea8 100644 --- a/packages/grafana-data/src/types/dataFrame.ts +++ b/packages/grafana-data/src/types/dataFrame.ts @@ -266,6 +266,7 @@ export interface DataFrameDTO extends QueryResultBase { export interface FieldCalcs extends Record {} +/** @deprecated check data plane docs: https://grafana.github.io/dataplane/heatmap **/ export const TIME_SERIES_VALUE_FIELD_NAME = 'Value'; export const TIME_SERIES_TIME_FIELD_NAME = 'Time'; export const TIME_SERIES_METRIC_FIELD_NAME = 'Metric'; diff --git a/public/app/plugins/datasource/prometheus/result_transformer.test.ts b/public/app/plugins/datasource/prometheus/result_transformer.test.ts index b251c89a1be..f44856d27af 100644 --- a/public/app/plugins/datasource/prometheus/result_transformer.test.ts +++ b/public/app/plugins/datasource/prometheus/result_transformer.test.ts @@ -91,7 +91,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [1, 2, 3] }, { - name: 'Value', type: FieldType.number, values: [4, 5, 6], config: { @@ -108,7 +107,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [1, 2, 3] }, { - name: 'Value', type: FieldType.number, values: [7, 8, 9], config: { @@ -362,7 +360,7 @@ describe('Prometheus Result Transformer', () => { expect(series.data[1].meta?.preferredVisualisationType).toEqual('rawPrometheus' as PreferredVisualisationType); }); - it('results with heatmap format should be correctly transformed', () => { + it('results with deprecated heatmap format should be correctly transformed', () => { const options = { targets: [ { @@ -422,6 +420,63 @@ describe('Prometheus Result Transformer', () => { expect(series.data[0].fields[2].name).toEqual('2'); expect(series.data[0].fields[3].name).toEqual('+Inf'); }); + it('results with heatmap format should be correctly transformed', () => { + const options = { + targets: [ + { + format: 'heatmap', + refId: 'A', + }, + ], + } as unknown as DataQueryRequest; + const response = { + state: 'Done', + data: [ + createDataFrame({ + refId: 'A', + fields: [ + { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, + { + type: FieldType.number, + values: [10, 10, 0], + labels: { le: '1' }, + }, + ], + }), + createDataFrame({ + refId: 'A', + fields: [ + { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, + { + type: FieldType.number, + values: [30, 10, 40], + labels: { le: '+Inf' }, + }, + ], + }), + createDataFrame({ + refId: 'A', + fields: [ + { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, + { + type: FieldType.number, + values: [20, 10, 30], + labels: { le: '2' }, + }, + ], + }), + ], + } as unknown as DataQueryResponse; + + const series = transformV2(response, options, {}); + expect(series.data[0].fields.length).toEqual(4); + expect(series.data[0].fields[1].values).toEqual([10, 10, 0]); + expect(series.data[0].fields[2].values).toEqual([10, 0, 30]); + expect(series.data[0].fields[3].values).toEqual([10, 0, 10]); + expect(series.data[0].fields[1].name).toEqual('1'); + expect(series.data[0].fields[2].name).toEqual('2'); + expect(series.data[0].fields[3].name).toEqual('+Inf'); + }); it('results with heatmap format from multiple queries should be correctly transformed', () => { const options = { @@ -444,7 +499,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [10, 10, 0], labels: { le: '1' }, @@ -456,7 +510,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [20, 10, 30], labels: { le: '2' }, @@ -468,7 +521,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 40], labels: { le: '+Inf' }, @@ -480,7 +532,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [10, 10, 0], labels: { le: '1' }, @@ -492,7 +543,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [20, 10, 30], labels: { le: '2' }, @@ -504,7 +554,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 40], labels: { le: '+Inf' }, @@ -539,7 +588,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [10, 10, 0], labels: { le: '1', additionalProperty: '10' }, @@ -551,7 +599,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [20, 10, 30], labels: { le: '2', additionalProperty: '10' }, @@ -563,7 +610,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 40], labels: { le: '+Inf', additionalProperty: '10' }, @@ -576,7 +622,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [0, 10, 10], labels: { le: '1', additionalProperty: '20' }, @@ -588,7 +633,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [20, 10, 40], labels: { le: '2', additionalProperty: '20' }, @@ -600,7 +644,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 60], labels: { le: '+Inf', additionalProperty: '20' }, @@ -613,7 +656,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 30, 60], labels: { le: '1', additionalProperty: '30' }, @@ -625,7 +667,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [30, 40, 60], labels: { le: '2', additionalProperty: '30' }, @@ -637,7 +678,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [40, 40, 60], labels: { le: '+Inf', additionalProperty: '30' }, @@ -679,7 +719,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [10, 10, 0], labels: { le: '1' }, @@ -697,7 +736,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4, 3, 2, 1] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 40, 90, 14, 21], labels: { le: '6' }, @@ -729,7 +767,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4] }, { - name: 'Value', type: FieldType.number, values: [10, 10, 0], labels: { le: '1' }, @@ -747,7 +784,6 @@ describe('Prometheus Result Transformer', () => { fields: [ { name: 'Time', type: FieldType.time, values: [6, 5, 4, 3, 2, 1] }, { - name: 'Value', type: FieldType.number, values: [30, 10, 40, 90, 14, 21], labels: { le: '6' }, diff --git a/public/app/plugins/datasource/prometheus/result_transformer.ts b/public/app/plugins/datasource/prometheus/result_transformer.ts index cef8a15ae80..e22193cd452 100644 --- a/public/app/plugins/datasource/prometheus/result_transformer.ts +++ b/public/app/plugins/datasource/prometheus/result_transformer.ts @@ -121,7 +121,7 @@ export function transformV2( // this works around the fact that we only get back frame.name with le buckets when legendFormat == {{le}}...which is not the default heatmapResults.forEach((df) => { if (df.name == null) { - let f = df.fields.find((f) => f.name === 'Value'); + let f = df.fields.find((f) => f.type === FieldType.number); if (f) { let le = f.labels?.le; @@ -150,7 +150,7 @@ export function transformV2( // Create a new grouping by iterating through the data frames... const heatmapResultsGroupedByValues = groupBy(heatmapResultsGroup, (dataFrame) => { // Each data frame has `Time` and `Value` properties, we want to get the values - const values = dataFrame.fields.find((field) => field.name === TIME_SERIES_VALUE_FIELD_NAME); + const values = dataFrame.fields.find((field) => field.type === FieldType.number); // Specific functionality for special "le" quantile heatmap value, we know if this value exists, that we do not want to calculate the heatmap density across data frames from the same quartile if (values?.labels && HISTOGRAM_QUANTILE_LABEL_NAME in values.labels) { const { le, ...notLE } = values?.labels; @@ -653,9 +653,10 @@ function transformToHistogramOverTime(seriesList: DataFrame[]) { le20 20 10 30 => 10 0 30 le30 30 10 35 => 10 0 5 */ + for (let i = seriesList.length - 1; i > 0; i--) { - const topSeries = seriesList[i].fields.find((s) => s.name === TIME_SERIES_VALUE_FIELD_NAME); - const bottomSeries = seriesList[i - 1].fields.find((s) => s.name === TIME_SERIES_VALUE_FIELD_NAME); + const topSeries = seriesList[i].fields.find((s) => s.type === FieldType.number); + const bottomSeries = seriesList[i - 1].fields.find((s) => s.type === FieldType.number); if (!topSeries || !bottomSeries) { throw new Error('Prometheus heatmap transform error: data should be a time series'); }