mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Loki: Allow multiple derived fields with the same name (#24437)
This commit is contained in:
parent
0ac006edf5
commit
a50cb6aa1f
@ -106,6 +106,10 @@ class UnThemedLogDetails extends PureComponent<Props> {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all fields for log row which consists of fields we parse from the message itself and any derived fields
|
||||||
|
* setup in data source config.
|
||||||
|
*/
|
||||||
getAllFields = memoizeOne((row: LogRowModel) => {
|
getAllFields = memoizeOne((row: LogRowModel) => {
|
||||||
const fields = this.parseMessage(row.entry);
|
const fields = this.parseMessage(row.entry);
|
||||||
const derivedFields = this.getDerivedFields(row);
|
const derivedFields = this.getDerivedFields(row);
|
||||||
@ -121,18 +125,10 @@ class UnThemedLogDetails extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as { [key: string]: FieldDef });
|
}, {} as { [key: string]: FieldDef });
|
||||||
|
|
||||||
const allFields = Object.values(fieldsMap);
|
const allFields = Object.values(fieldsMap);
|
||||||
allFields.sort((fieldA, fieldB) => {
|
allFields.sort(sortFieldsLinkFirst);
|
||||||
if (fieldA.links?.length && !fieldB.links?.length) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fieldA.links?.length && fieldB.links?.length) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fieldA.key > fieldB.key ? 1 : fieldA.key < fieldB.key ? -1 : 0;
|
|
||||||
});
|
|
||||||
return allFields;
|
return allFields;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -233,5 +229,15 @@ class UnThemedLogDetails extends PureComponent<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortFieldsLinkFirst(fieldA: FieldDef, fieldB: FieldDef) {
|
||||||
|
if (fieldA.links?.length && !fieldB.links?.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!fieldA.links?.length && fieldB.links?.length) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return fieldA.key > fieldB.key ? 1 : fieldA.key < fieldB.key ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
export const LogDetails = withTheme(UnThemedLogDetails);
|
export const LogDetails = withTheme(UnThemedLogDetails);
|
||||||
LogDetails.displayName = 'LogDetails';
|
LogDetails.displayName = 'LogDetails';
|
||||||
|
@ -5,7 +5,7 @@ import { serializeStateToUrlParam } from '../../../core/utils/explore';
|
|||||||
import { getDataSourceSrv } from '@grafana/runtime';
|
import { getDataSourceSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get links from the filed of a dataframe that was given to as and in addition check if there is associated
|
* Get links from the field of a dataframe and in addition check if there is associated
|
||||||
* metadata with datasource in which case we will add onClick to open the link in new split window. This assumes
|
* metadata with datasource in which case we will add onClick to open the link in new split window. This assumes
|
||||||
* that we just supply datasource name and field value and Explore split window will know how to render that
|
* that we just supply datasource name and field value and Explore split window will know how to render that
|
||||||
* appropriately. This is for example used for transition from log with traceId to trace datasource to show that
|
* appropriately. This is for example used for transition from log with traceId to trace datasource to show that
|
||||||
|
@ -131,6 +131,11 @@ describe('enhanceDataFrame', () => {
|
|||||||
name: 'trace2',
|
name: 'trace2',
|
||||||
datasourceUid: 'uid',
|
datasourceUid: 'uid',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
matcherRegex: 'trace2=(\\w+)',
|
||||||
|
name: 'trace2',
|
||||||
|
datasourceUid: 'uid2',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(df.fields.length).toBe(3);
|
expect(df.fields.length).toBe(3);
|
||||||
@ -142,9 +147,14 @@ describe('enhanceDataFrame', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(fc.getFieldByName('trace2').values.toArray()).toEqual([null, null, 'foo']);
|
expect(fc.getFieldByName('trace2').values.toArray()).toEqual([null, null, 'foo']);
|
||||||
|
expect(fc.getFieldByName('trace2').config.links.length).toBe(2);
|
||||||
expect(fc.getFieldByName('trace2').config.links[0]).toEqual({
|
expect(fc.getFieldByName('trace2').config.links[0]).toEqual({
|
||||||
title: '',
|
title: '',
|
||||||
meta: { datasourceUid: 'uid' },
|
meta: { datasourceUid: 'uid' },
|
||||||
});
|
});
|
||||||
|
expect(fc.getFieldByName('trace2').config.links[1]).toEqual({
|
||||||
|
title: '',
|
||||||
|
meta: { datasourceUid: 'uid2' },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
ArrayVector,
|
ArrayVector,
|
||||||
MutableDataFrame,
|
MutableDataFrame,
|
||||||
findUniqueLabels,
|
findUniqueLabels,
|
||||||
FieldConfig,
|
|
||||||
DataFrameView,
|
DataFrameView,
|
||||||
DataLink,
|
DataLink,
|
||||||
Field,
|
Field,
|
||||||
@ -332,14 +331,15 @@ export const enhanceDataFrame = (dataFrame: DataFrame, config: LokiOptions | nul
|
|||||||
if (!derivedFields.length) {
|
if (!derivedFields.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const newFields = derivedFields.map(fieldFromDerivedFieldConfig);
|
const derivedFieldsGrouped = _.groupBy(derivedFields, 'name');
|
||||||
const newFieldsMap = _.keyBy(newFields, 'name');
|
|
||||||
|
const newFields = Object.values(derivedFieldsGrouped).map(fieldFromDerivedFieldConfig);
|
||||||
|
|
||||||
const view = new DataFrameView(dataFrame);
|
const view = new DataFrameView(dataFrame);
|
||||||
view.forEach((row: { line: string }) => {
|
view.forEach((row: { line: string }) => {
|
||||||
for (const field of derivedFields) {
|
for (const field of newFields) {
|
||||||
const logMatch = row.line.match(field.matcherRegex);
|
const logMatch = row.line.match(derivedFieldsGrouped[field.name][0].matcherRegex);
|
||||||
newFieldsMap[field.name].values.add(logMatch && logMatch[1]);
|
field.values.add(logMatch && logMatch[1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -349,28 +349,30 @@ export const enhanceDataFrame = (dataFrame: DataFrame, config: LokiOptions | nul
|
|||||||
/**
|
/**
|
||||||
* Transform derivedField config into dataframe field with config that contains link.
|
* Transform derivedField config into dataframe field with config that contains link.
|
||||||
*/
|
*/
|
||||||
function fieldFromDerivedFieldConfig(derivedFieldConfig: DerivedFieldConfig): Field<any, ArrayVector> {
|
function fieldFromDerivedFieldConfig(derivedFieldConfigs: DerivedFieldConfig[]): Field<any, ArrayVector> {
|
||||||
const config: FieldConfig = {};
|
const dataLinks = derivedFieldConfigs.reduce((acc, derivedFieldConfig) => {
|
||||||
if (derivedFieldConfig.url || derivedFieldConfig.datasourceUid) {
|
if (derivedFieldConfig.url || derivedFieldConfig.datasourceUid) {
|
||||||
const link: Partial<DataLink> = {
|
acc.push({
|
||||||
// We do not know what title to give here so we count on presentation layer to create a title from metadata.
|
// We do not know what title to give here so we count on presentation layer to create a title from metadata.
|
||||||
title: '',
|
title: '',
|
||||||
url: derivedFieldConfig.url,
|
url: derivedFieldConfig.url,
|
||||||
};
|
// Having field.datasourceUid means it is an internal link.
|
||||||
|
meta: derivedFieldConfig.datasourceUid
|
||||||
// Having field.datasourceUid means it is an internal link.
|
? {
|
||||||
if (derivedFieldConfig.datasourceUid) {
|
datasourceUid: derivedFieldConfig.datasourceUid,
|
||||||
link.meta = {
|
}
|
||||||
datasourceUid: derivedFieldConfig.datasourceUid,
|
: undefined,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
return acc;
|
||||||
|
}, [] as DataLink[]);
|
||||||
|
|
||||||
config.links = [link as DataLink];
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
name: derivedFieldConfig.name,
|
name: derivedFieldConfigs[0].name,
|
||||||
type: FieldType.string,
|
type: FieldType.string,
|
||||||
config,
|
config: {
|
||||||
|
links: dataLinks,
|
||||||
|
},
|
||||||
// We are adding values later on
|
// We are adding values later on
|
||||||
values: new ArrayVector<string>([]),
|
values: new ArrayVector<string>([]),
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ echo -e "Collecting code stats (typescript errors & more)"
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ERROR_COUNT_LIMIT=728
|
ERROR_COUNT_LIMIT=726
|
||||||
DIRECTIVES_LIMIT=172
|
DIRECTIVES_LIMIT=172
|
||||||
CONTROLLERS_LIMIT=139
|
CONTROLLERS_LIMIT=139
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user