Explore: Add transformations to correlation data links (#61799)

* bring in source from database

* bring in transformations from database

* add regex transformations to scopevar

* Consolidate types, add better example, cleanup

* Add var only if match

* Change ScopedVar to not require text, do not leak transformation-made variables between links

* Add mappings and start implementing logfmt

* Add mappings and start implementing logfmt

* Remove mappings, turn off global regex

* Add example yaml and omit transformations if empty

* Fix the yaml

* Add logfmt transformation

* Cleanup transformations and yaml

* add transformation field to FE types and use it, safeStringify logfmt values

* Add tests, only safe stringify if non-string, fix bug with safe stringify where it would return empty string with false value

* Add test for transformation field

* Do not add null transformations object

* Break out transformation logic, add tests to backend code

* Fix lint errors I understand 😅

* Fix the backend lint error

* Remove unnecessary code and mark new Transformations object as internal

* Add support for named capture groups

* Remove type assertion

* Remove variable name from transformation

* Add test for overriding regexes

* Add back variable name field, but change to mapValue

* fix go api test

* Change transformation types to enum, add better provisioning checks for bad type name and format

* Check for expression with regex transformations
This commit is contained in:
Kristina
2023-02-22 06:53:03 -06:00
committed by GitHub
parent f64b7fe8a7
commit 06dfe2156f
17 changed files with 377 additions and 21 deletions
@@ -0,0 +1,34 @@
import logfmt from 'logfmt';
import { ScopedVars, DataLinkTransformationConfig, SupportedTransformationTypes } from '@grafana/data';
import { safeStringifyValue } from 'app/core/utils/explore';
export const getTransformationVars = (
transformation: DataLinkTransformationConfig,
fieldValue: string,
fieldName: string
): ScopedVars => {
let transformationScopedVars: ScopedVars = {};
let transformVal: { [key: string]: string | boolean | null | undefined } = {};
if (transformation.type === SupportedTransformationTypes.Regex && transformation.expression) {
const regexp = new RegExp(transformation.expression, 'gi');
const matches = fieldValue.matchAll(regexp);
for (const match of matches) {
if (match.groups) {
transformVal = match.groups;
} else {
transformVal[transformation.mapValue || fieldName] = match[1] || match[0];
}
}
} else if (transformation.type === SupportedTransformationTypes.Logfmt) {
transformVal = logfmt.parse(fieldValue);
}
Object.keys(transformVal).forEach((key) => {
const transformValString =
typeof transformVal[key] === 'string' ? transformVal[key] : safeStringifyValue(transformVal[key]);
transformationScopedVars[key] = { value: transformValString };
});
return transformationScopedVars;
};
@@ -1,3 +1,5 @@
import { DataLinkTransformationConfig } from '@grafana/data';
export interface AddCorrelationResponse {
correlation: Correlation;
}
@@ -5,10 +7,12 @@ export interface AddCorrelationResponse {
export type GetCorrelationsResponse = Correlation[];
type CorrelationConfigType = 'query';
export interface CorrelationConfig {
field: string;
target: object;
type: CorrelationConfigType;
transformations?: DataLinkTransformationConfig[];
}
export interface Correlation {
@@ -39,6 +39,7 @@ const decorateDataFrameWithInternalDataLinks = (dataFrame: DataFrame, correlatio
query: correlation.config?.target,
datasourceUid: correlation.target.uid,
datasourceName: correlation.target.name,
transformations: correlation.config?.transformations,
},
url: '',
title: correlation.label || correlation.target.name,