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);
|
||||
});
|
||||
|
||||
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', () => {
|
||||
const cfg: DataTransformerConfig<LabelsToFieldsOptions> = {
|
||||
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 { MutableDataFrame } from '../../dataframe';
|
||||
import { ArrayVector } from '../../vector';
|
||||
@ -21,7 +21,8 @@ export const labelsToFieldsTransformer: DataTransformerInfo<LabelsToFieldsOption
|
||||
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) {
|
||||
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 }) {
|
||||
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
|
||||
@ -85,6 +126,7 @@ function createColumnsMap(framesWithTimeField: DataFrame[], framesWithoutTimeFie
|
||||
const timeFrame = framesWithTimeField[frameIndex];
|
||||
const otherFrame = framesWithoutTimeField[frameIndex];
|
||||
const timeField = timeFrame.fields[0];
|
||||
|
||||
addOrAppendMapItem({ map, column: timeField.name, series: frameIndex, type: timeField.type });
|
||||
|
||||
for (let valueIndex = 0; valueIndex < timeFrame.length; valueIndex++) {
|
||||
|
@ -10,10 +10,10 @@ export const LabelsAsFieldsTransformerEditor: React.FC<TransformerUIProps<Labels
|
||||
return null;
|
||||
};
|
||||
|
||||
export const labelsAsFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
|
||||
export const labelsToFieldsTransformerRegistryItem: TransformerRegistyItem<LabelsToFieldsOptions> = {
|
||||
id: DataTransformerID.labelsToFields,
|
||||
editor: LabelsAsFieldsTransformerEditor,
|
||||
transformation: standardTransformers.labelsToFieldsTransformer,
|
||||
name: 'Labels as fields',
|
||||
description: 'Groups series by time and return labels as fields',
|
||||
name: 'Labels to 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 { seriesToFieldsTransformerRegistryItem } from '../components/TransformersUI/SeriesToFieldsTransformerEditor';
|
||||
import { calculateFieldTransformRegistryItem } from '../components/TransformersUI/CalculateFieldTransformerEditor';
|
||||
import { labelsAsFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsAsFieldsTransformerEditor';
|
||||
import { labelsToFieldsTransformerRegistryItem } from '../components/TransformersUI/LabelsToFieldsTransformerEditor';
|
||||
|
||||
export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> => {
|
||||
return [
|
||||
@ -15,6 +15,6 @@ export const getStandardTransformers = (): Array<TransformerRegistyItem<any>> =>
|
||||
organizeFieldsTransformRegistryItem,
|
||||
seriesToFieldsTransformerRegistryItem,
|
||||
calculateFieldTransformRegistryItem,
|
||||
labelsAsFieldsTransformerRegistryItem,
|
||||
labelsToFieldsTransformerRegistryItem,
|
||||
];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user