mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
combineFrames: add support to merge transformed data frames (#81554)
* combineResponses: account for disordered frames * tempo: undo change * Formatting
This commit is contained in:
parent
147bee4831
commit
5c3e211777
@ -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 = {
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user