mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -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,
|
DataFrame,
|
||||||
DataFrameType,
|
DataFrameType,
|
||||||
DataQueryResponse,
|
DataQueryResponse,
|
||||||
|
Field,
|
||||||
FieldType,
|
FieldType,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
PanelData,
|
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', () => {
|
it('combines metric frames', () => {
|
||||||
const { metricFrameA, metricFrameB } = getMockFrames();
|
const { metricFrameA, metricFrameB } = getMockFrames();
|
||||||
const responseA: DataQueryResponse = {
|
const responseA: DataQueryResponse = {
|
||||||
|
@ -57,10 +57,23 @@ export function combineResponses(currentResult: DataQueryResponse | null, newRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
function combineFrames(dest: DataFrame, source: DataFrame) {
|
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++) {
|
for (let i = 0; i < totalFields; i++) {
|
||||||
dest.fields[i].values = [].concat.apply(source.fields[i].values, dest.fields[i].values);
|
// For now, skip undefined fields that exist in the new frame
|
||||||
if (source.fields[i].nanos) {
|
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() || [];
|
const nanos: number[] = dest.fields[i].nanos?.slice() || [];
|
||||||
dest.fields[i].nanos = source.fields[i].nanos?.concat(nanos);
|
dest.fields[i].nanos = source.fields[i].nanos?.concat(nanos);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user