diff --git a/docs/sources/datasources/loki/configure-loki-data-source.md b/docs/sources/datasources/loki/configure-loki-data-source.md index b667c8e1bf8..8dc6eb1670c 100644 --- a/docs/sources/datasources/loki/configure-loki-data-source.md +++ b/docs/sources/datasources/loki/configure-loki-data-source.md @@ -114,9 +114,13 @@ Each derived field consists of the following: - **Type** - Defines the type of the derived field. It can be either: - - **Regex**: A regular expression to parse a part of the log message and capture it as the value of the new field. Can contain only one capture group. +{{% admonition type="caution" %}} +Using complex regular expressions in either type can impact browser performance when processing large volumes of logs. Consider using simpler patterns when possible. +{{% /admonition %}} + +- **Regex**: A regular expression to parse a part of the log message and capture it as the value of the new field. Can contain only one capture group. - - **Label**: A label from the selected log line. This can be any type of label - indexed, parsed or structured metadata. The label's value will be used as the value of the derived field. +- **Label**: A label from the selected log line. This can be any type of label - indexed, parsed or structured metadata. When using this type, the input will match as a regular expression against label keys, allowing you to match variations like `traceid` and `trace_id` with a single regex pattern like `trace[_]?id`. The value of the matched label will be used as the value of the derived field. - **URL/query** Sets the full link URL if the link is external, or a query for the target data source if the link is internal. You can interpolate the value from the field with the `${__value.raw}` macro. diff --git a/public/app/plugins/datasource/loki/getDerivedFields.test.ts b/public/app/plugins/datasource/loki/getDerivedFields.test.ts index 674d95cea91..7b56f5a5751 100644 --- a/public/app/plugins/datasource/loki/getDerivedFields.test.ts +++ b/public/app/plugins/datasource/loki/getDerivedFields.test.ts @@ -192,4 +192,28 @@ describe('getDerivedFields', () => { title: '', }); }); + + it('matches label keys using regex when matcherType is label', () => { + const df = createDataFrame({ + fields: [ + { name: 'labels', values: [{ traceId: 'abc' }, { traceID: 'xyz' }] }, + { name: 'line', values: ['log1', 'log2'] }, + ], + }); + const newFields = getDerivedFields(df, [ + { + matcherRegex: 'traceI(d|D)', + name: 'traceIdFromLabel', + url: 'http://localhost/${__value.raw}', + matcherType: 'label', + }, + ]); + expect(newFields.length).toBe(1); + const traceId = newFields.find((f) => f.name === 'traceIdFromLabel'); + expect(traceId!.values).toEqual(['abc', 'xyz']); + expect(traceId!.config.links![0]).toEqual({ + url: 'http://localhost/${__value.raw}', + title: '', + }); + }); }); diff --git a/public/app/plugins/datasource/loki/getDerivedFields.ts b/public/app/plugins/datasource/loki/getDerivedFields.ts index e28c697adfc..8a23e1d54ff 100644 --- a/public/app/plugins/datasource/loki/getDerivedFields.ts +++ b/public/app/plugins/datasource/loki/getDerivedFields.ts @@ -30,10 +30,11 @@ export function getDerivedFields(dataFrame: DataFrame, derivedFieldConfigs: Deri if (derivedFieldsGrouped[field.name][0].matcherType === 'label' && labelFields) { const label = labelFields.values[i]; if (label) { - // Find the key that matches both, the `matcherRegex` and the label key - const intersectingKey = Object.keys(label).find( - (key) => derivedFieldsGrouped[field.name][0].matcherRegex === key - ); + // Find the key that matches the regex pattern in `matcherRegex` + const intersectingKey = Object.keys(label).find((key) => { + const regex = new RegExp(derivedFieldsGrouped[field.name][0].matcherRegex); + return regex.test(key); + }); if (intersectingKey) { field.values.push(label[intersectingKey]);