From df4922ea7880d2e90f8e073bcf8a155629ca20a4 Mon Sep 17 00:00:00 2001 From: Matias Chomicki Date: Fri, 24 Oct 2025 11:25:02 +0200 Subject: [PATCH] mergeResponses: use map to find frames to combine (#112855) * mergeResponses: use map to find frames to combine * Remove console --- .../plugins/datasource/loki/mergeResponses.ts | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/datasource/loki/mergeResponses.ts b/public/app/plugins/datasource/loki/mergeResponses.ts index d37413650fc..3c98892df55 100644 --- a/public/app/plugins/datasource/loki/mergeResponses.ts +++ b/public/app/plugins/datasource/loki/mergeResponses.ts @@ -13,18 +13,52 @@ import { import { LOADING_FRAME_NAME } from './querySplitting'; +function getFrameKey(frame: DataFrame): string | undefined { + // Metric range query data + if (frame.meta?.type === DataFrameType.TimeSeriesMulti) { + const field = frame.fields.find((f) => f.type === FieldType.number); + if (!field) { + throw new Error(`Unable to find number field on sharded dataframe!`); + } + let key = ''; + if (frame.refId) { + key += frame.refId; + } + if (frame.name) { + key += frame.name; + } + if (field.labels) { + key += JSON.stringify(field.labels); + } + return key !== '' ? key : undefined; + } + return frame.refId ?? frame.name; +} + export function combineResponses(currentResponse: DataQueryResponse | null, newResponse: DataQueryResponse) { if (!currentResponse) { return cloneQueryResponse(newResponse); } - newResponse.data.forEach((newFrame) => { - const currentFrame = currentResponse.data.find((frame) => shouldCombine(frame, newFrame)); - if (!currentFrame) { + const currentResponseLabelsMap = new Map(); + currentResponse.data.forEach((frame: DataFrame) => { + const key = getFrameKey(frame); + // It is expected that all frames contain a refId or a name, but since the type allows for it + // we need to account for possibly undefined cases. + if (key) { + currentResponseLabelsMap.set(key, frame); + } + }); + + newResponse.data.forEach((newFrame: DataFrame) => { + let currentFrame: DataFrame | undefined = undefined; + const key = getFrameKey(newFrame); + if (key !== undefined && currentResponseLabelsMap.has(key)) { + currentFrame = currentResponseLabelsMap.get(key); + mergeFrames(currentFrame!, newFrame); + } else { currentResponse.data.push(cloneDataFrame(newFrame)); - return; } - mergeFrames(currentFrame, newFrame); }); const mergedErrors = [...(currentResponse.errors ?? []), ...(newResponse.errors ?? [])];