combineFrames: add support to merge transformed data frames (#81554)

* combineResponses: account for disordered frames

* tempo: undo change

* Formatting
This commit is contained in:
Matias Chomicki 2024-01-30 13:02:15 +01:00 committed by GitHub
parent 147bee4831
commit 5c3e211777
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 95 additions and 3 deletions

View File

@ -2,6 +2,7 @@ import {
DataFrame,
DataFrameType,
DataQueryResponse,
Field,
FieldType,
LoadingState,
PanelData,
@ -96,6 +97,84 @@ describe('combineResponses', () => {
});
});
it('combines logs frames with transformed fields', () => {
const { logFrameA, logFrameB } = getMockFrames();
const { logFrameB: originalLogFrameB } = getMockFrames();
// Pseudo shuffle fields
logFrameB.fields.sort((a: Field, b: Field) => (a.name < b.name ? -1 : 1));
expect(logFrameB.fields).not.toEqual(originalLogFrameB.fields);
const responseA: DataQueryResponse = {
data: [logFrameA],
};
const responseB: DataQueryResponse = {
data: [logFrameB],
};
expect(combineResponses(responseA, responseB)).toEqual({
data: [
{
fields: [
{
config: {},
name: 'Time',
type: 'time',
values: [1, 2, 3, 4],
},
{
config: {},
name: 'Line',
type: 'string',
values: ['line3', 'line4', 'line1', 'line2'],
},
{
config: {},
name: 'labels',
type: 'other',
values: [
{
otherLabel: 'other value',
},
{
label: 'value',
},
{
otherLabel: 'other value',
},
],
},
{
config: {},
name: 'tsNs',
type: 'string',
values: ['1000000', '2000000', '3000000', '4000000'],
},
{
config: {},
name: 'id',
type: 'string',
values: ['id3', 'id4', 'id1', 'id2'],
},
],
length: 4,
meta: {
custom: {
frameType: 'LabeledTimeValues',
},
stats: [
{
displayName: 'Summary: total bytes processed',
unit: 'decbytes',
value: 33,
},
],
},
refId: 'A',
},
],
});
});
it('combines metric frames', () => {
const { metricFrameA, metricFrameB } = getMockFrames();
const responseA: DataQueryResponse = {

View File

@ -57,10 +57,23 @@ export function combineResponses(currentResult: DataQueryResponse | null, newRes
}
function combineFrames(dest: DataFrame, source: DataFrame) {
const totalFields = dest.fields.length;
// `dest` and `source` might have more or less fields, we need to go through all of them
const totalFields = Math.max(dest.fields.length, source.fields.length);
for (let i = 0; i < totalFields; i++) {
dest.fields[i].values = [].concat.apply(source.fields[i].values, dest.fields[i].values);
if (source.fields[i].nanos) {
// For now, skip undefined fields that exist in the new frame
if (!dest.fields[i]) {
continue;
}
// Index is not reliable when frames have disordered fields, or an extra/missing field, so we find them by name.
// If the field has no name, we fallback to the old index version.
const sourceField = dest.fields[i].name
? source.fields.find((f) => f.name === dest.fields[i].name)
: source.fields[i];
if (!sourceField) {
continue;
}
dest.fields[i].values = [].concat.apply(sourceField.values, dest.fields[i].values);
if (sourceField.nanos) {
const nanos: number[] = dest.fields[i].nanos?.slice() || [];
dest.fields[i].nanos = source.fields[i].nanos?.concat(nanos);
}