Loki: query splitting: handle stats (#63436)

* loki: query splitting: handle stats

* update tests
This commit is contained in:
Gábor Farkas
2023-02-20 14:55:56 +01:00
committed by GitHub
parent 6e7187a042
commit 8f7b980c95
3 changed files with 103 additions and 29 deletions

View File

@@ -150,6 +150,12 @@ export function getMockFrames() {
values: new ArrayVector(['id1', 'id2']),
},
],
meta: {
stats: [
{ displayName: 'Summary: total bytes processed', value: 11 },
{ displayName: 'Ingester: total reached', value: 1 },
],
},
length: 2,
};
@@ -192,7 +198,10 @@ export function getMockFrames() {
},
],
meta: {
stats: [{ displayName: 'Ingester: total reached', value: 1 }],
stats: [
{ displayName: 'Summary: total bytes processed', value: 22 },
{ displayName: 'Ingester: total reached', value: 2 },
],
},
length: 2,
};
@@ -214,7 +223,10 @@ export function getMockFrames() {
},
],
meta: {
stats: [{ displayName: 'Ingester: total reached', value: 1 }],
stats: [
{ displayName: 'Ingester: total reached', value: 1 },
{ displayName: 'Summary: total bytes processed', value: 11 },
],
},
length: 2,
};
@@ -236,7 +248,10 @@ export function getMockFrames() {
},
],
meta: {
stats: [{ displayName: 'Ingester: total reached', value: 2 }],
stats: [
{ displayName: 'Ingester: total reached', value: 2 },
{ displayName: 'Summary: total bytes processed', value: 22 },
],
},
length: 2,
};
@@ -259,7 +274,10 @@ export function getMockFrames() {
},
],
meta: {
stats: [{ displayName: 'Ingester: total reached', value: 2 }],
stats: [
{ displayName: 'Ingester: total reached', value: 2 },
{ displayName: 'Summary: total bytes processed', value: 33 },
],
},
length: 2,
};

View File

@@ -1,4 +1,4 @@
import { ArrayVector, DataQueryResponse } from '@grafana/data';
import { ArrayVector, DataQueryResponse, QueryResultMetaStat } from '@grafana/data';
import { getMockFrames } from './mocks';
import {
@@ -368,8 +368,8 @@ describe('combineResponses', () => {
meta: {
stats: [
{
displayName: 'Ingester: total reached',
value: 1,
displayName: 'Summary: total bytes processed',
value: 33,
},
],
},
@@ -408,8 +408,8 @@ describe('combineResponses', () => {
meta: {
stats: [
{
displayName: 'Ingester: total reached',
value: 3,
displayName: 'Summary: total bytes processed',
value: 33,
},
],
},
@@ -448,8 +448,8 @@ describe('combineResponses', () => {
meta: {
stats: [
{
displayName: 'Ingester: total reached',
value: 3,
displayName: 'Summary: total bytes processed',
value: 33,
},
],
},
@@ -471,4 +471,55 @@ describe('combineResponses', () => {
expect(combineResponses(null, responseA)).not.toBe(responseA);
expect(combineResponses(null, responseB)).not.toBe(responseB);
});
describe('combine stats', () => {
const { metricFrameA } = getMockFrames();
const makeResponse = (stats?: QueryResultMetaStat[]): DataQueryResponse => ({
data: [
{
...metricFrameA,
meta: {
...metricFrameA.meta,
stats,
},
},
],
});
it('two values', () => {
const responseA = makeResponse([
{ displayName: 'Ingester: total reached', value: 1 },
{ displayName: 'Summary: total bytes processed', value: 11 },
]);
const responseB = makeResponse([
{ displayName: 'Ingester: total reached', value: 2 },
{ displayName: 'Summary: total bytes processed', value: 22 },
]);
expect(combineResponses(responseA, responseB).data[0].meta.stats).toStrictEqual([
{ displayName: 'Summary: total bytes processed', value: 33 },
]);
});
it('one value', () => {
const responseA = makeResponse([
{ displayName: 'Ingester: total reached', value: 1 },
{ displayName: 'Summary: total bytes processed', value: 11 },
]);
const responseB = makeResponse();
expect(combineResponses(responseA, responseB).data[0].meta.stats).toStrictEqual([
{ displayName: 'Summary: total bytes processed', value: 11 },
]);
expect(combineResponses(responseB, responseA).data[0].meta.stats).toStrictEqual([
{ displayName: 'Summary: total bytes processed', value: 11 },
]);
});
it('no value', () => {
const responseA = makeResponse();
const responseB = makeResponse();
expect(combineResponses(responseA, responseB).data[0].meta.stats).toHaveLength(0);
});
});
});

View File

@@ -345,28 +345,33 @@ function combineFrames(dest: DataFrame, source: DataFrame) {
);
}
dest.length += source.length;
combineMetadata(dest, source);
dest.meta = {
...dest.meta,
stats: getCombinedMetadataStats(dest.meta?.stats ?? [], source.meta?.stats ?? []),
};
}
function combineMetadata(dest: DataFrame, source: DataFrame) {
if (!source.meta?.stats) {
return;
const TOTAL_BYTES_STAT = 'Summary: total bytes processed';
function getCombinedMetadataStats(
destStats: QueryResultMetaStat[],
sourceStats: QueryResultMetaStat[]
): QueryResultMetaStat[] {
// in the current approach, we only handle a single stat
const destStat = destStats.find((s) => s.displayName === TOTAL_BYTES_STAT);
const sourceStat = sourceStats.find((s) => s.displayName === TOTAL_BYTES_STAT);
if (sourceStat != null && destStat != null) {
return [{ value: sourceStat.value + destStat.value, displayName: TOTAL_BYTES_STAT }];
}
if (!dest.meta?.stats) {
if (!dest.meta) {
dest.meta = {};
}
Object.assign(dest.meta, { stats: source.meta.stats });
return;
// maybe one of them exist
const eitherStat = sourceStat ?? destStat;
if (eitherStat != null) {
return [eitherStat];
}
dest.meta.stats.forEach((destStat: QueryResultMetaStat, i: number) => {
const sourceStat = source.meta?.stats?.find(
(sourceStat: QueryResultMetaStat) => destStat.displayName === sourceStat.displayName
);
if (sourceStat) {
destStat.value += sourceStat.value;
}
});
return [];
}
/**