mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Transformations: Simple fix for labels to fields problem with time series field names (#23828)
* Simple fix for labels to fields transform problem * Added unit test
This commit is contained in:
parent
fb8a555f19
commit
59bea141f2
@ -43,6 +43,38 @@ describe('Labels as Columns', () => {
|
|||||||
expect(result[0].fields).toEqual(expected);
|
expect(result[0].fields).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('data frames where frame name is same as value field name replace field name with name Value', () => {
|
||||||
|
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
|
||||||
|
id: DataTransformerID.labelsToFields,
|
||||||
|
options: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const oneValueOneLabelA = toDataFrame({
|
||||||
|
name: 'A',
|
||||||
|
fields: [
|
||||||
|
{ name: 'time', type: FieldType.time, values: [1000] },
|
||||||
|
{ name: 'A', type: FieldType.number, values: [1], labels: { location: 'inside' } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const oneValueOneLabelB = toDataFrame({
|
||||||
|
name: 'B',
|
||||||
|
fields: [
|
||||||
|
{ name: 'time', type: FieldType.time, values: [2000] },
|
||||||
|
{ name: 'B', type: FieldType.number, values: [-1], labels: { location: 'outside' } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = transformDataFrame([cfg], [oneValueOneLabelA, oneValueOneLabelB]);
|
||||||
|
const expected: Field[] = [
|
||||||
|
{ name: 'time', type: FieldType.time, values: new ArrayVector([1000, 2000]), config: {} },
|
||||||
|
{ name: 'location', type: FieldType.string, values: new ArrayVector(['inside', 'outside']), config: {} },
|
||||||
|
{ name: 'Value', type: FieldType.number, values: new ArrayVector([1, -1]), config: {} },
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(result[0].fields).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
it('data frame with 2 values and 1 label', () => {
|
it('data frame with 2 values and 1 label', () => {
|
||||||
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
|
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
|
||||||
id: DataTransformerID.labelsToFields,
|
id: DataTransformerID.labelsToFields,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DataFrame, DataTransformerInfo, FieldType } from '../../types';
|
import { DataFrame, DataTransformerInfo, FieldType, Field } from '../../types';
|
||||||
import { DataTransformerID } from './ids';
|
import { DataTransformerID } from './ids';
|
||||||
import { MutableDataFrame } from '../../dataframe';
|
import { MutableDataFrame } from '../../dataframe';
|
||||||
import { ArrayVector } from '../../vector';
|
import { ArrayVector } from '../../vector';
|
||||||
@ -21,7 +21,8 @@ export const labelsToFieldsTransformer: DataTransformerInfo<LabelsToFieldsOption
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const framesWithoutTimeField = filterFieldsTransformer.transformer({ exclude: { id: FieldMatcherID.time } })(data);
|
// get frames with only value fields
|
||||||
|
const framesWithoutTimeField = getFramesWithOnlyValueFields(data);
|
||||||
if (!framesWithoutTimeField.length || !framesWithoutTimeField[0].fields.length) {
|
if (!framesWithoutTimeField.length || !framesWithoutTimeField[0].fields.length) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -64,6 +65,46 @@ export const labelsToFieldsTransformer: DataTransformerInfo<LabelsToFieldsOption
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getFramesWithOnlyValueFields(data: DataFrame[]): DataFrame[] {
|
||||||
|
const processed: DataFrame[] = [];
|
||||||
|
|
||||||
|
for (const series of data) {
|
||||||
|
const fields: Field[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < series.fields.length; i++) {
|
||||||
|
const field = series.fields[i];
|
||||||
|
if (field.type !== FieldType.number) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we transform a time series to DataFrame we put series name in field name.
|
||||||
|
// This casues problems for this transformer that want all time series values in a Value column
|
||||||
|
// So here we change field names that have same name as DataFrame to just Value
|
||||||
|
if (field.name === series.name) {
|
||||||
|
fields.push({
|
||||||
|
...field,
|
||||||
|
name: 'Value',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fields.push(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fields.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const copy = {
|
||||||
|
...series, // all the other properties
|
||||||
|
fields, // but a different set of fields
|
||||||
|
};
|
||||||
|
|
||||||
|
processed.push(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
}
|
||||||
|
|
||||||
function addOrAppendMapItem(args: { map: Map; series: number; column: string; type: FieldType; isValue?: boolean }) {
|
function addOrAppendMapItem(args: { map: Map; series: number; column: string; type: FieldType; isValue?: boolean }) {
|
||||||
const { map, column, type, series, isValue = false } = args;
|
const { map, column, type, series, isValue = false } = args;
|
||||||
// we're using the fact that the series (number) will automatically become a string prop on the object
|
// we're using the fact that the series (number) will automatically become a string prop on the object
|
||||||
@ -85,6 +126,7 @@ function createColumnsMap(framesWithTimeField: DataFrame[], framesWithoutTimeFie
|
|||||||
const timeFrame = framesWithTimeField[frameIndex];
|
const timeFrame = framesWithTimeField[frameIndex];
|
||||||
const otherFrame = framesWithoutTimeField[frameIndex];
|
const otherFrame = framesWithoutTimeField[frameIndex];
|
||||||
const timeField = timeFrame.fields[0];
|
const timeField = timeFrame.fields[0];
|
||||||
|
|
||||||
addOrAppendMapItem({ map, column: timeField.name, series: frameIndex, type: timeField.type });
|
addOrAppendMapItem({ map, column: timeField.name, series: frameIndex, type: timeField.type });
|
||||||
|
|
||||||
for (let valueIndex = 0; valueIndex < timeFrame.length; valueIndex++) {
|
for (let valueIndex = 0; valueIndex < timeFrame.length; valueIndex++) {
|
||||||
|
@ -10,10 +10,10 @@ export const LabelsAsFieldsTransformerEditor: React.FC<TransformerUIProps<Labels
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const labelsAsFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
|
export const labelsToFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
|
||||||
id: DataTransformerID.labelsToFields,
|
id: DataTransformerID.labelsToFields,
|
||||||
editor: LabelsAsFieldsTransformerEditor,
|
editor: LabelsAsFieldsTransformerEditor,
|
||||||
transformation: standardTransformers.labelsToFieldsTransformer,
|
transformation: standardTransformers.labelsToFieldsTransformer,
|
||||||
name: 'Labels as fields',
|
name: 'Labels to fields',
|
||||||
description: 'Groups series by time and return labels as fields',
|
description: 'Groups series by time and return labels or tags as fields',
|
||||||
};
|
};
|
@ -5,7 +5,7 @@ import { filterFramesByRefIdTransformRegistryItem } from '../components/Transfor
|
|||||||
import { organizeFieldsTransformRegistryItem } from '../components/TransformersUI/OrganizeFieldsTransformerEditor';
|
import { organizeFieldsTransformRegistryItem } from '../components/TransformersUI/OrganizeFieldsTransformerEditor';
|
||||||
import { seriesToFieldsTransformerRegistryItem } from '../components/TransformersUI/SeriesToFieldsTransformerEditor';
|
import { seriesToFieldsTransformerRegistryItem } from '../components/TransformersUI/SeriesToFieldsTransformerEditor';
|
||||||
import { calculateFieldTransformRegistryItem } from '../components/TransformersUI/CalculateFieldTransformerEditor';
|
import { calculateFieldTransformRegistryItem } from '../components/TransformersUI/CalculateFieldTransformerEditor';
|
||||||
import { labelsAsFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsAsFieldsTransformerEditor';
|
import { labelsToFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsToFieldsTransformerEditor';
|
||||||
|
|
||||||
export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> => {
|
export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> => {
|
||||||
return [
|
return [
|
||||||
@ -15,6 +15,6 @@ export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> =>
|
|||||||
organizeFieldsTransformRegistryItem,
|
organizeFieldsTransformRegistryItem,
|
||||||
seriesToFieldsTransformerRegistryItem,
|
seriesToFieldsTransformerRegistryItem,
|
||||||
calculateFieldTransformRegistryItem,
|
calculateFieldTransformRegistryItem,
|
||||||
labelsAsFieldsTransformerRegistryItem,
|
labelsToFieldsTransformerRegistryItem,
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user