Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prometheus: fix incorrect baseline in classic histogram #83863

Merged
108 changes: 105 additions & 3 deletions packages/grafana-prometheus/src/result_transformer.test.ts
@@ -1,10 +1,11 @@
import {
cacheFieldDisplayNames,
createDataFrame,
DataQueryRequest,
DataQueryResponse,
FieldType,
PreferredVisualisationType,
type DataFrame,
type DataQueryRequest,
type DataQueryResponse,
type PreferredVisualisationType,
} from '@grafana/data';

import { parseSampleValue, sortSeriesByLabel, transformDFToTable, transformV2 } from './result_transformer';
Expand Down Expand Up @@ -404,6 +405,7 @@ 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 (with metric name) should be correctly transformed', () => {
const options = {
targets: [
Expand Down Expand Up @@ -925,6 +927,106 @@ describe('Prometheus Result Transformer', () => {
expect(traceField).toBeDefined();
expect(traceField!.config.links?.length).toBe(0);
});

it('should convert values less than 1e-9 to 0', () => {
const options = {
targets: [
{
format: 'heatmap',
refId: 'A',
},
],
} as unknown as DataQueryRequest<PromQuery>;
const response = {
state: 'Done',
data: [
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [10, 10, 0],
labels: { le: '1' },
},
],
}),
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [20, 10, 30],
labels: { le: '2' },
},
],
}),
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [30, 10, 40],
labels: { le: '+Inf' },
},
],
}),
],
} as unknown as DataQueryResponse & { data: DataFrame[] };

// Create a situation where the series subtraction in histogram transformation results in a value less than 1e-9
response.data[1].fields[1].values[1] += 0.0000000001;
response.data[2].fields[1].values[1] += 0.00000000015;

const series = transformV2(response, options, {});

expect(
series.data
.at(0)
?.fields.find((field) => field.name === '2')
?.values.at(1)
).toBe(0);
expect(
series.data
.at(0)
?.fields.find((field) => field.name === '+Inf')
?.values.at(1)
).toBe(0);
});

it('should throw an error if the series does not contain number-type values', () => {
const response = {
state: 'Done',
data: [
['10', '10', '0'],
['20', '10', '30'],
['20', '10', '35'],
].map((values) =>
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{ name: 'Value', type: FieldType.string, values },
],
})
),
} as unknown as DataQueryResponse;
const request = {
targets: [
{
format: 'heatmap',
refId: 'A',
},
],
} as unknown as DataQueryRequest<PromQuery>;

expect(() => transformV2(response, request, {})).toThrow();
});
});

describe('transformDFToTable', () => {
Expand Down
6 changes: 5 additions & 1 deletion packages/grafana-prometheus/src/result_transformer.ts
Expand Up @@ -359,7 +359,7 @@ function mergeHeatmapFrames(frames: DataFrame[]): DataFrame[] {
];
}

function transformToHistogramOverTime(seriesList: DataFrame[]) {
function transformToHistogramOverTime(seriesList: DataFrame[]): DataFrame[] {
/* t1 = timestamp1, t2 = timestamp2 etc.
t1 t2 t3 t1 t2 t3
le10 10 10 0 => 10 10 0
Expand All @@ -377,6 +377,10 @@ function transformToHistogramOverTime(seriesList: DataFrame[]) {
for (let j = 0; j < topSeries.values.length; j++) {
const bottomPoint = bottomSeries.values[j] || [0];
topSeries.values[j] -= bottomPoint;

if (topSeries.values[j] < 1e-9) {
topSeries.values[j] = 0;
}
}
}

Expand Down
108 changes: 105 additions & 3 deletions public/app/plugins/datasource/prometheus/result_transformer.test.ts
@@ -1,10 +1,11 @@
import {
cacheFieldDisplayNames,
createDataFrame,
DataQueryRequest,
DataQueryResponse,
FieldType,
PreferredVisualisationType,
type DataFrame,
type DataQueryRequest,
type DataQueryResponse,
type PreferredVisualisationType,
} from '@grafana/data';

import { parseSampleValue, sortSeriesByLabel, transformDFToTable, transformV2 } from './result_transformer';
Expand Down Expand Up @@ -404,6 +405,7 @@ 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 (with metric name) should be correctly transformed', () => {
const options = {
targets: [
Expand Down Expand Up @@ -925,6 +927,106 @@ describe('Prometheus Result Transformer', () => {
expect(traceField).toBeDefined();
expect(traceField!.config.links?.length).toBe(0);
});

it('should convert values less than 1e-9 to 0', () => {
const options = {
targets: [
{
format: 'heatmap',
refId: 'A',
},
],
} as unknown as DataQueryRequest<PromQuery>;
const response = {
state: 'Done',
data: [
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [10, 10, 0],
labels: { le: '1' },
},
],
}),
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [20, 10, 30],
labels: { le: '2' },
},
],
}),
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{
name: 'Value',
type: FieldType.number,
values: [30, 10, 40],
labels: { le: '+Inf' },
},
],
}),
],
} as unknown as DataQueryResponse & { data: DataFrame[] };

// Create a situation where the series subtraction in histogram transformation results in a value less than 1e-9
response.data[1].fields[1].values[1] += 0.0000000001;
response.data[2].fields[1].values[1] += 0.00000000015;

const series = transformV2(response, options, {});

expect(
series.data
.at(0)
?.fields.find((field) => field.name === '2')
?.values.at(1)
).toBe(0);
expect(
series.data
.at(0)
?.fields.find((field) => field.name === '+Inf')
?.values.at(1)
).toBe(0);
});

it('should throw an error if the series does not contain number-type values', () => {
const response = {
state: 'Done',
data: [
['10', '10', '0'],
['20', '10', '30'],
['20', '10', '35'],
].map((values) =>
createDataFrame({
refId: 'A',
fields: [
{ name: 'Time', type: FieldType.time, values: [6, 5, 4] },
{ name: 'Value', type: FieldType.string, values },
],
})
),
} as unknown as DataQueryResponse;
const request = {
targets: [
{
format: 'heatmap',
refId: 'A',
},
],
} as unknown as DataQueryRequest<PromQuery>;

expect(() => transformV2(response, request, {})).toThrow();
});
});

describe('transformDFToTable', () => {
Expand Down
Expand Up @@ -359,7 +359,7 @@ function mergeHeatmapFrames(frames: DataFrame[]): DataFrame[] {
];
}

function transformToHistogramOverTime(seriesList: DataFrame[]) {
function transformToHistogramOverTime(seriesList: DataFrame[]): DataFrame[] {
/* t1 = timestamp1, t2 = timestamp2 etc.
t1 t2 t3 t1 t2 t3
le10 10 10 0 => 10 10 0
Expand All @@ -377,6 +377,10 @@ function transformToHistogramOverTime(seriesList: DataFrame[]) {
for (let j = 0; j < topSeries.values.length; j++) {
const bottomPoint = bottomSeries.values[j] || [0];
topSeries.values[j] -= bottomPoint;

if (topSeries.values[j] < 1e-9) {
topSeries.values[j] = 0;
}
NWRichmond marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down