diff --git a/.betterer.results b/.betterer.results index 4027c16c076..66d75913434 100644 --- a/.betterer.results +++ b/.betterer.results @@ -4353,9 +4353,8 @@ exports[`better eslint`] = { ], "public/app/features/query/state/PanelQueryRunner.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Do not use any type assertions.", "2"], - [0, 0, 0, "Do not use any type assertions.", "3"] + [0, 0, 0, "Do not use any type assertions.", "1"], + [0, 0, 0, "Do not use any type assertions.", "2"] ], "public/app/features/query/state/runRequest.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] diff --git a/packages/grafana-data/src/transformations/transformDataFrame.ts b/packages/grafana-data/src/transformations/transformDataFrame.ts index 14d3800e176..2c2e6e1350e 100644 --- a/packages/grafana-data/src/transformations/transformDataFrame.ts +++ b/packages/grafana-data/src/transformations/transformDataFrame.ts @@ -1,12 +1,12 @@ import { MonoTypeOperatorFunction, Observable, of } from 'rxjs'; import { map, mergeMap } from 'rxjs/operators'; -import { DataFrame, DataTransformerConfig } from '../types'; +import { DataFrame, DataTransformContext, DataTransformerConfig } from '../types'; import { standardTransformersRegistry, TransformerRegistryItem } from './standardTransformersRegistry'; const getOperator = - (config: DataTransformerConfig): MonoTypeOperatorFunction => + (config: DataTransformerConfig, ctx: DataTransformContext): MonoTypeOperatorFunction => (source) => { const info = standardTransformersRegistry.get(config.id); @@ -19,7 +19,7 @@ const getOperator = return source.pipe( mergeMap((before) => - of(before).pipe(info.transformation.operator(options, config.replace), postProcessTransform(before, info)) + of(before).pipe(info.transformation.operator(options, ctx), postProcessTransform(before, info)) ) ); }; @@ -53,7 +53,11 @@ const postProcessTransform = /** * Apply configured transformations to the input data */ -export function transformDataFrame(options: DataTransformerConfig[], data: DataFrame[]): Observable { +export function transformDataFrame( + options: DataTransformerConfig[], + data: DataFrame[], + ctx?: DataTransformContext +): Observable { const stream = of(data); if (!options.length) { @@ -61,6 +65,7 @@ export function transformDataFrame(options: DataTransformerConfig[], data: DataF } const operators: Array> = []; + const context = ctx ?? { interpolate: (str) => str }; for (let index = 0; index < options.length; index++) { const config = options[index]; @@ -69,7 +74,7 @@ export function transformDataFrame(options: DataTransformerConfig[], data: DataF continue; } - operators.push(getOperator(config)); + operators.push(getOperator(config, context)); } // @ts-ignore TypeScript has a hard time understanding this construct diff --git a/packages/grafana-data/src/transformations/transformers/calculateField.test.ts b/packages/grafana-data/src/transformations/transformers/calculateField.test.ts index aba72a8585d..62deb6ea366 100644 --- a/packages/grafana-data/src/transformations/transformers/calculateField.test.ts +++ b/packages/grafana-data/src/transformations/transformers/calculateField.test.ts @@ -1,6 +1,6 @@ import { DataFrameView } from '../../dataframe'; import { toDataFrame } from '../../dataframe/processDataFrame'; -import { ScopedVars } from '../../types'; +import { DataTransformContext, ScopedVars } from '../../types'; import { FieldType } from '../../types/dataFrame'; import { BinaryOperationID } from '../../utils'; import { mockTransformationsRegistry } from '../../utils/tests/mockTransformationsRegistry'; @@ -235,7 +235,9 @@ describe('calculateField transformer w/ timeseries', () => { }, replaceFields: true, }, - replace: (target: string | undefined, scopedVars?: ScopedVars, format?: string | Function): string => { + }; + const context: DataTransformContext = { + interpolate: (target: string | undefined, scopedVars?: ScopedVars, format?: string | Function): string => { if (!target) { return ''; } @@ -262,7 +264,7 @@ describe('calculateField transformer w/ timeseries', () => { }, }; - await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => { + await expect(transformDataFrame([cfg], [seriesA], context)).toEmitValuesWith((received) => { const data = received[0]; const filtered = data[0]; const rows = new DataFrameView(filtered).toArray(); diff --git a/packages/grafana-data/src/transformations/transformers/calculateField.ts b/packages/grafana-data/src/transformations/transformers/calculateField.ts index 9462d56d113..fd5eac8e42b 100644 --- a/packages/grafana-data/src/transformations/transformers/calculateField.ts +++ b/packages/grafana-data/src/transformations/transformers/calculateField.ts @@ -72,11 +72,15 @@ export const calculateFieldTransformer: DataTransformerInfo (outerSource) => { + operator: (options, ctx) => (outerSource) => { const operator = - options && options.timeSeries !== false ? ensureColumnsTransformer.operator(null) : noopTransformer.operator({}); + options && options.timeSeries !== false + ? ensureColumnsTransformer.operator(null, ctx) + : noopTransformer.operator({}, ctx); - options.alias = replace ? replace(options.alias) : options.alias; + if (options.alias != null) { + options.alias = ctx.interpolate(options.alias); + } return outerSource.pipe( operator, @@ -87,13 +91,12 @@ export const calculateFieldTransformer: DataTransformerInfo (source) => source.pipe(map((data) => convertFieldTypeTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => convertFieldTypeTransformer.transformer(options, ctx)(data))), transformer: (options: ConvertFieldTypeTransformerOptions) => (data: DataFrame[]) => { if (!Array.isArray(data) || data.length === 0) { diff --git a/packages/grafana-data/src/transformations/transformers/ensureColumns.ts b/packages/grafana-data/src/transformations/transformers/ensureColumns.ts index 6ec89a218f1..4968336c236 100644 --- a/packages/grafana-data/src/transformations/transformers/ensureColumns.ts +++ b/packages/grafana-data/src/transformations/transformers/ensureColumns.ts @@ -12,16 +12,20 @@ export const ensureColumnsTransformer: SynchronousDataTransformerInfo = { name: 'Ensure Columns Transformer', description: 'Will check if current data frames is series or columns. If in series it will convert to columns.', - operator: (options) => (source) => source.pipe(map((data) => ensureColumnsTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => ensureColumnsTransformer.transformer(options, ctx)(data))), - transformer: (options: any) => (frames: DataFrame[]) => { + transformer: (_options: any, ctx) => (frames: DataFrame[]) => { // Assume timeseries should first be joined by time const timeFieldName = findConsistentTimeFieldName(frames); if (frames.length > 1 && timeFieldName) { - return joinByFieldTransformer.transformer({ - byField: timeFieldName, - })(frames); + return joinByFieldTransformer.transformer( + { + byField: timeFieldName, + }, + ctx + )(frames); } return frames; }, diff --git a/packages/grafana-data/src/transformations/transformers/filter.ts b/packages/grafana-data/src/transformations/transformers/filter.ts index 4b80fe4672e..9c8758057f5 100644 --- a/packages/grafana-data/src/transformations/transformers/filter.ts +++ b/packages/grafana-data/src/transformations/transformers/filter.ts @@ -22,23 +22,21 @@ export const filterFieldsTransformer: DataTransformerInfo = { * Return a modified copy of the series. If the transform is not or should not * be applied, just return the input series */ - operator: (options: FilterOptions, replace) => (source) => { + operator: (options: FilterOptions, ctx) => (source) => { if (!options.include && !options.exclude) { - return source.pipe(noopTransformer.operator({}, replace)); + return source.pipe(noopTransformer.operator({}, ctx)); } - if (replace) { - if (typeof options.include?.options === 'string') { - options.include.options = replace(options.include?.options); - } else if (typeof options.include?.options?.pattern === 'string') { - options.include.options.pattern = replace(options.include?.options.pattern); - } + if (typeof options.include?.options === 'string') { + options.include.options = ctx.interpolate(options.include?.options); + } else if (typeof options.include?.options?.pattern === 'string') { + options.include.options.pattern = ctx.interpolate(options.include?.options.pattern); + } - if (typeof options.exclude?.options === 'string') { - options.exclude.options = replace(options.exclude?.options); - } else if (typeof options.exclude?.options?.pattern === 'string') { - options.exclude.options.pattern = replace(options.exclude?.options.pattern); - } + if (typeof options.exclude?.options === 'string') { + options.exclude.options = ctx.interpolate(options.exclude?.options); + } else if (typeof options.exclude?.options?.pattern === 'string') { + options.exclude.options.pattern = ctx.interpolate(options.exclude?.options.pattern); } return source.pipe( @@ -91,9 +89,9 @@ export const filterFramesTransformer: DataTransformerInfo = { * Return a modified copy of the series. If the transform is not or should not * be applied, just return the input series */ - operator: (options) => (source) => { + operator: (options, ctx) => (source) => { if (!options.include && !options.exclude) { - return source.pipe(noopTransformer.operator({})); + return source.pipe(noopTransformer.operator({}, ctx)); } return source.pipe( diff --git a/packages/grafana-data/src/transformations/transformers/filterByName.test.ts b/packages/grafana-data/src/transformations/transformers/filterByName.test.ts index 459154a7905..554864069d1 100644 --- a/packages/grafana-data/src/transformations/transformers/filterByName.test.ts +++ b/packages/grafana-data/src/transformations/transformers/filterByName.test.ts @@ -205,7 +205,10 @@ describe('filterByName transformer', () => { pattern: '/^$var1/', }, }, - replace: (target: string | undefined, scopedVars?: ScopedVars, format?: string | Function): string => { + }; + + const ctx = { + interpolate: (target: string | undefined, scopedVars?: ScopedVars, format?: string | Function): string => { if (!target) { return ''; } @@ -222,7 +225,7 @@ describe('filterByName transformer', () => { }, }; - await expect(transformDataFrame([cfg], [seriesWithNamesToMatch])).toEmitValuesWith((received) => { + await expect(transformDataFrame([cfg], [seriesWithNamesToMatch], ctx)).toEmitValuesWith((received) => { const data = received[0]; const filtered = data[0]; expect(filtered.fields.length).toBe(2); diff --git a/packages/grafana-data/src/transformations/transformers/filterByRefId.ts b/packages/grafana-data/src/transformations/transformers/filterByRefId.ts index 29e6f50a808..c4e0c7fcda7 100644 --- a/packages/grafana-data/src/transformations/transformers/filterByRefId.ts +++ b/packages/grafana-data/src/transformations/transformers/filterByRefId.ts @@ -19,7 +19,7 @@ export const filterFramesByRefIdTransformer: DataTransformerInfo (source) => { + operator: (options, ctx) => (source) => { const filterOptions: FilterOptions = {}; if (options.include) { filterOptions.include = { @@ -34,6 +34,6 @@ export const filterFramesByRefIdTransformer: DataTransformerInfo (source) => { + operator: (options, ctx) => (source) => { const filters = options.filters; const matchAll = options.match === FilterByValueMatch.all; const include = options.type === FilterByValueType.include; if (!Array.isArray(filters) || filters.length === 0) { - return source.pipe(noopTransformer.operator({})); + return source.pipe(noopTransformer.operator({}, ctx)); } return source.pipe( diff --git a/packages/grafana-data/src/transformations/transformers/histogram.ts b/packages/grafana-data/src/transformations/transformers/histogram.ts index 818e48dc9dd..943f46975d6 100644 --- a/packages/grafana-data/src/transformations/transformers/histogram.ts +++ b/packages/grafana-data/src/transformations/transformers/histogram.ts @@ -82,7 +82,8 @@ export const histogramTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => histogramTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => histogramTransformer.transformer(options, ctx)(data))), transformer: (options: HistogramTransformerOptions) => (data: DataFrame[]) => { if (!Array.isArray(data) || data.length === 0) { diff --git a/packages/grafana-data/src/transformations/transformers/joinByField.ts b/packages/grafana-data/src/transformations/transformers/joinByField.ts index 3b229fc7c66..e6c1d386fa6 100644 --- a/packages/grafana-data/src/transformations/transformers/joinByField.ts +++ b/packages/grafana-data/src/transformations/transformers/joinByField.ts @@ -28,7 +28,8 @@ export const joinByFieldTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => joinByFieldTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => joinByFieldTransformer.transformer(options, ctx)(data))), transformer: (options: JoinByFieldOptions) => { let joinBy: FieldMatcher | undefined = undefined; diff --git a/packages/grafana-data/src/transformations/transformers/labelsToFields.ts b/packages/grafana-data/src/transformations/transformers/labelsToFields.ts index c4814f7ecc7..92a9742dfce 100644 --- a/packages/grafana-data/src/transformations/transformers/labelsToFields.ts +++ b/packages/grafana-data/src/transformations/transformers/labelsToFields.ts @@ -28,7 +28,8 @@ export const labelsToFieldsTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => labelsToFieldsTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => labelsToFieldsTransformer.transformer(options, ctx)(data))), transformer: (options: LabelsToFieldsOptions) => (data: DataFrame[]) => { // Show each label as a field row diff --git a/packages/grafana-data/src/transformations/transformers/organize.ts b/packages/grafana-data/src/transformations/transformers/organize.ts index 3a13a0fbc47..99827803a4d 100644 --- a/packages/grafana-data/src/transformations/transformers/organize.ts +++ b/packages/grafana-data/src/transformations/transformers/organize.ts @@ -25,13 +25,16 @@ export const organizeFieldsTransformer: DataTransformerInfo (source) => + operator: (options, ctx) => (source) => source.pipe( - filterFieldsByNameTransformer.operator({ - exclude: { names: mapToExcludeArray(options.excludeByName) }, - }), - orderFieldsTransformer.operator(options), - renameFieldsTransformer.operator(options) + filterFieldsByNameTransformer.operator( + { + exclude: { names: mapToExcludeArray(options.excludeByName) }, + }, + ctx + ), + orderFieldsTransformer.operator(options, ctx), + renameFieldsTransformer.operator(options, ctx) ), }; diff --git a/packages/grafana-data/src/types/transformations.ts b/packages/grafana-data/src/types/transformations.ts index 6e97159e3e6..017a72bfc49 100644 --- a/packages/grafana-data/src/types/transformations.ts +++ b/packages/grafana-data/src/types/transformations.ts @@ -2,8 +2,15 @@ import { MonoTypeOperatorFunction } from 'rxjs'; import { RegistryItemWithOptions } from '../utils/Registry'; -import { ScopedVars } from './ScopedVars'; import { DataFrame, Field } from './dataFrame'; +import { InterpolateFunction } from './panel'; + +/** + * Context passed to transformDataFrame and to each transform operator + */ +export interface DataTransformContext { + interpolate: InterpolateFunction; +} /** * Function that transform data frames (AKA transformer) @@ -15,10 +22,7 @@ export interface DataTransformerInfo extends RegistryItemWithOpt * Function that configures transformation and returns a transformer * @param options */ - operator: ( - options: TOptions, - replace?: (target?: string, scopedVars?: ScopedVars, format?: string | Function) => string - ) => MonoTypeOperatorFunction; + operator: (options: TOptions, context: DataTransformContext) => MonoTypeOperatorFunction; } /** @@ -28,7 +32,7 @@ export interface DataTransformerInfo extends RegistryItemWithOpt * @public */ export interface SynchronousDataTransformerInfo extends DataTransformerInfo { - transformer: (options: TOptions) => (frames: DataFrame[]) => DataFrame[]; + transformer: (options: TOptions, context: DataTransformContext) => (frames: DataFrame[]) => DataFrame[]; } /** @@ -47,10 +51,6 @@ export interface DataTransformerConfig { * Options to be passed to the transformer */ options: TOptions; - /** - * Function to apply template variable substitution to the DataTransformerConfig - */ - replace?: (target?: string, scopedVars?: ScopedVars, format?: string | Function) => string; } export type FrameMatcher = (frame: DataFrame) => boolean; diff --git a/public/app/features/annotations/standardAnnotationSupport.ts b/public/app/features/annotations/standardAnnotationSupport.ts index d8997eb6df8..09b49e620aa 100644 --- a/public/app/features/annotations/standardAnnotationSupport.ts +++ b/public/app/features/annotations/standardAnnotationSupport.ts @@ -10,6 +10,7 @@ import { AnnotationSupport, DataFrame, DataSourceApi, + DataTransformContext, Field, FieldType, getFieldDisplayName, @@ -66,8 +67,12 @@ export function singleFrameFromPanelData(): OperatorFunction v, + }; + return of(data).pipe( - standardTransformers.mergeTransformer.operator({}), + standardTransformers.mergeTransformer.operator({}, ctx), map((d) => d[0]) ); }) diff --git a/public/app/features/explore/utils/decorators.ts b/public/app/features/explore/utils/decorators.ts index 9417f582875..4273fd994a0 100644 --- a/public/app/features/explore/utils/decorators.ts +++ b/public/app/features/explore/utils/decorators.ts @@ -133,13 +133,16 @@ export const decorateWithTableResult = (data: ExplorePanelData): Observable isTimeSeries(df)); + const transformContext = { + interpolate: (v: string) => v, + }; // If we have only timeseries we do join on default time column which makes more sense. If we are showing // non timeseries or some mix of data we are not trying to join on anything and just try to merge them in // single table, which may not make sense in most cases, but it's up to the user to query something sensible. const transformer = hasOnlyTimeseries - ? of(data.tableFrames).pipe(standardTransformers.joinByFieldTransformer.operator({})) - : of(data.tableFrames).pipe(standardTransformers.mergeTransformer.operator({})); + ? of(data.tableFrames).pipe(standardTransformers.joinByFieldTransformer.operator({}, transformContext)) + : of(data.tableFrames).pipe(standardTransformers.mergeTransformer.operator({}, transformContext)); return transformer.pipe( map((frames) => { @@ -183,13 +186,16 @@ export const decorateWithRawPrometheusResult = (data: ExplorePanelData): Observa }); const hasOnlyTimeseries = tableFrames.every((df) => isTimeSeries(df)); + const transformContext = { + interpolate: (v: string) => v, + }; // If we have only timeseries we do join on default time column which makes more sense. If we are showing // non timeseries or some mix of data we are not trying to join on anything and just try to merge them in // single table, which may not make sense in most cases, but it's up to the user to query something sensible. const transformer = hasOnlyTimeseries - ? of(tableFrames).pipe(standardTransformers.joinByFieldTransformer.operator({})) - : of(tableFrames).pipe(standardTransformers.mergeTransformer.operator({})); + ? of(tableFrames).pipe(standardTransformers.joinByFieldTransformer.operator({}, transformContext)) + : of(tableFrames).pipe(standardTransformers.mergeTransformer.operator({}, transformContext)); return transformer.pipe( map((frames) => { diff --git a/public/app/features/query/state/PanelQueryRunner.ts b/public/app/features/query/state/PanelQueryRunner.ts index 0c64685b224..2f0ccc8018e 100644 --- a/public/app/features/query/state/PanelQueryRunner.ts +++ b/public/app/features/query/state/PanelQueryRunner.ts @@ -14,6 +14,7 @@ import { DataSourceApi, DataSourceJsonData, DataSourceRef, + DataTransformContext, DataTransformerConfig, getDefaultTimeRange, LoadingState, @@ -187,14 +188,11 @@ export class PanelQueryRunner { return of(data); } - const replace = (option: string): string => { - return getTemplateSrv().replace(option, data?.request?.scopedVars); + const ctx: DataTransformContext = { + interpolate: (v: string) => getTemplateSrv().replace(v, data?.request?.scopedVars), }; - transformations.forEach((transform: any) => { - transform.replace = replace; - }); - return transformDataFrame(transformations, data.series).pipe(map((series) => ({ ...data, series }))); + return transformDataFrame(transformations, data.series, ctx).pipe(map((series) => ({ ...data, series }))); }) ); }; diff --git a/public/app/features/scenes/querying/SceneQueryRunner.ts b/public/app/features/scenes/querying/SceneQueryRunner.ts index fafe2cef6d6..fb17661252f 100644 --- a/public/app/features/scenes/querying/SceneQueryRunner.ts +++ b/public/app/features/scenes/querying/SceneQueryRunner.ts @@ -193,15 +193,13 @@ export const getTransformationsStream: ( return of(data); } - const replace: (option?: string) => string = (option) => { - return sceneGraph.interpolate(sceneObject, option, data?.request?.scopedVars); + const ctx = { + interpolate: (value: string) => { + return sceneGraph.interpolate(sceneObject, value, data?.request?.scopedVars); + }, }; - transformations.forEach((transform: DataTransformerConfig) => { - transform.replace = replace; - }); - - return transformDataFrame(transformations, data.series).pipe(map((series) => ({ ...data, series }))); + return transformDataFrame(transformations, data.series, ctx).pipe(map((series) => ({ ...data, series }))); }) ); }; diff --git a/public/app/features/transformers/calculateHeatmap/heatmap.ts b/public/app/features/transformers/calculateHeatmap/heatmap.ts index 6b1291cbc12..da20e34cedc 100644 --- a/public/app/features/transformers/calculateHeatmap/heatmap.ts +++ b/public/app/features/transformers/calculateHeatmap/heatmap.ts @@ -32,7 +32,8 @@ export const heatmapTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => heatmapTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => heatmapTransformer.transformer(options, ctx)(data))), transformer: (options: HeatmapTransformerOptions) => { return (data: DataFrame[]) => { diff --git a/public/app/features/transformers/editors/CalculateFieldTransformerEditor.tsx b/public/app/features/transformers/editors/CalculateFieldTransformerEditor.tsx index dd44d7fabd2..95b35007cf1 100644 --- a/public/app/features/transformers/editors/CalculateFieldTransformerEditor.tsx +++ b/public/app/features/transformers/editors/CalculateFieldTransformerEditor.tsx @@ -68,9 +68,10 @@ export class CalculateFieldTransformerEditor extends React.PureComponent< private initOptions() { const { options } = this.props; const configuredOptions = options?.reduce?.include || []; + const ctx = { interpolate: (v: string) => v }; const subscription = of(this.props.input) .pipe( - standardTransformers.ensureColumnsTransformer.operator(null), + standardTransformers.ensureColumnsTransformer.operator(null, ctx), this.extractAllNames(), this.extractNamesAndSelected(configuredOptions) ) diff --git a/public/app/features/transformers/extractFields/extractFields.test.ts b/public/app/features/transformers/extractFields/extractFields.test.ts index 949fbdf6ccc..bc810be25b6 100644 --- a/public/app/features/transformers/extractFields/extractFields.test.ts +++ b/public/app/features/transformers/extractFields/extractFields.test.ts @@ -8,12 +8,13 @@ describe('Fields from JSON', () => { source: 'line', replace: true, }; + const ctx = { interpolate: (v: string) => v }; const data = toDataFrame({ columns: ['ts', 'line'], rows: appl, }); - const frames = extractFieldsTransformer.transformer(cfg)([data]); + const frames = extractFieldsTransformer.transformer(cfg, ctx)([data]); expect(frames.length).toEqual(1); expect( frames[0].fields.reduce((acc, v) => { diff --git a/public/app/features/transformers/extractFields/extractFields.ts b/public/app/features/transformers/extractFields/extractFields.ts index ede77024b40..8aef7c62dee 100644 --- a/public/app/features/transformers/extractFields/extractFields.ts +++ b/public/app/features/transformers/extractFields/extractFields.ts @@ -26,7 +26,8 @@ export const extractFieldsTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => extractFieldsTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => extractFieldsTransformer.transformer(options, ctx)(data))), transformer: (options: ExtractFieldsOptions) => { return (data: DataFrame[]) => { diff --git a/public/app/features/transformers/joinByLabels/joinByLabels.ts b/public/app/features/transformers/joinByLabels/joinByLabels.ts index dceb6759e7c..9ebfb34c1a2 100644 --- a/public/app/features/transformers/joinByLabels/joinByLabels.ts +++ b/public/app/features/transformers/joinByLabels/joinByLabels.ts @@ -22,7 +22,8 @@ export const joinByLabelsTransformer: SynchronousDataTransformerInfo (source) => source.pipe(map((data) => joinByLabelsTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => joinByLabelsTransformer.transformer(options, ctx)(data))), transformer: (options: JoinByLabelsTransformOptions) => { return (data: DataFrame[]) => { diff --git a/public/app/features/transformers/partitionByValues/partitionByValues.test.ts b/public/app/features/transformers/partitionByValues/partitionByValues.test.ts index bf229166dc3..7b10b7b67aa 100644 --- a/public/app/features/transformers/partitionByValues/partitionByValues.test.ts +++ b/public/app/features/transformers/partitionByValues/partitionByValues.test.ts @@ -2,6 +2,10 @@ import { toDataFrame, FieldType } from '@grafana/data'; import { partitionByValuesTransformer, PartitionByValuesTransformerOptions } from './partitionByValues'; +const ctx = { + interpolate: (v: string) => v, +}; + describe('Partition by values transformer', () => { it('should partition by one field', () => { const source = [ @@ -19,7 +23,7 @@ describe('Partition by values transformer', () => { fields: ['region'], }; - let partitioned = partitionByValuesTransformer.transformer(config)(source); + let partitioned = partitionByValuesTransformer.transformer(config, ctx)(source); expect(partitioned.length).toEqual(2); @@ -55,7 +59,7 @@ describe('Partition by values transformer', () => { fields: ['region', 'status'], }; - let partitioned = partitionByValuesTransformer.transformer(config)(source); + let partitioned = partitionByValuesTransformer.transformer(config, ctx)(source); expect(partitioned.length).toEqual(4); @@ -116,7 +120,7 @@ describe('Partition by values transformer', () => { }, }; - let partitioned = partitionByValuesTransformer.transformer(config)(source); + let partitioned = partitionByValuesTransformer.transformer(config, ctx)(source); expect(partitioned[0].name).toEqual('region=Europe status=OK'); expect(partitioned[1].name).toEqual('region=Europe status=FAIL'); @@ -144,7 +148,7 @@ describe('Partition by values transformer', () => { }, }; - let partitioned = partitionByValuesTransformer.transformer(config)(source); + let partitioned = partitionByValuesTransformer.transformer(config, ctx)(source); expect(partitioned[0].name).toEqual('XYZ Europe OK'); expect(partitioned[1].name).toEqual('XYZ Europe FAIL'); @@ -173,7 +177,7 @@ describe('Partition by values transformer', () => { }, }; - let partitioned = partitionByValuesTransformer.transformer(config)(source); + let partitioned = partitionByValuesTransformer.transformer(config, ctx)(source); expect(partitioned[0].name).toEqual('XYZ region=Europe status=OK'); expect(partitioned[1].name).toEqual('XYZ region=Europe status=FAIL'); diff --git a/public/app/features/transformers/partitionByValues/partitionByValues.ts b/public/app/features/transformers/partitionByValues/partitionByValues.ts index 645c9882500..2b26be6d6b9 100644 --- a/public/app/features/transformers/partitionByValues/partitionByValues.ts +++ b/public/app/features/transformers/partitionByValues/partitionByValues.ts @@ -6,6 +6,7 @@ import { DataTransformerID, SynchronousDataTransformerInfo, getFieldMatcher, + DataTransformContext, } from '@grafana/data'; import { getMatcherConfig } from '@grafana/data/src/transformations/transformers/filterByName'; import { noopTransformer } from '@grafana/data/src/transformations/transformers/noop'; @@ -49,14 +50,14 @@ export const partitionByValuesTransformer: SynchronousDataTransformerInfo (source) => - source.pipe(map((data) => partitionByValuesTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => partitionByValuesTransformer.transformer(options, ctx)(data))), - transformer: (options: PartitionByValuesTransformerOptions) => { + transformer: (options: PartitionByValuesTransformerOptions, ctx: DataTransformContext) => { const matcherConfig = getMatcherConfig({ names: options.fields }); if (!matcherConfig) { - return noopTransformer.transformer({}); + return noopTransformer.transformer({}, ctx); } const matcher = getFieldMatcher(matcherConfig); diff --git a/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.test.ts b/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.test.ts index 7879e9a988f..250552c28c9 100644 --- a/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.test.ts +++ b/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.test.ts @@ -11,6 +11,10 @@ import { import { prepareTimeSeriesTransformer, PrepareTimeSeriesOptions, timeSeriesFormat } from './prepareTimeSeries'; +const ctx = { + interpolate: (v: string) => v, +}; + describe('Prepare time series transformer', () => { it('should transform wide to multi', () => { const source = [ @@ -29,7 +33,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([ + expect(prepareTimeSeriesTransformer.transformer(config, ctx)(source)).toEqual([ toEquableDataFrame({ name: 'wide', refId: 'A', @@ -75,7 +79,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - const frames = prepareTimeSeriesTransformer.transformer(config)(source); + const frames = prepareTimeSeriesTransformer.transformer(config, ctx)(source); expect(frames.length).toEqual(4); expect( frames.map((f) => ({ @@ -171,7 +175,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([ + expect(prepareTimeSeriesTransformer.transformer(config, ctx)(source)).toEqual([ toEquableDataFrame({ name: 'wide', refId: 'A', @@ -235,7 +239,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - expect(toEquableDataFrames(prepareTimeSeriesTransformer.transformer(config)(source))).toEqual( + expect(toEquableDataFrames(prepareTimeSeriesTransformer.transformer(config, ctx)(source))).toEqual( toEquableDataFrames( source.map((frame) => ({ ...frame, @@ -273,7 +277,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - expect(prepareTimeSeriesTransformer.transformer(config)(source)).toEqual([]); + expect(prepareTimeSeriesTransformer.transformer(config, ctx)(source)).toEqual([]); }); it('should convert long to multi', () => { @@ -293,7 +297,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMulti, }; - const frames = prepareTimeSeriesTransformer.transformer(config)(source); + const frames = prepareTimeSeriesTransformer.transformer(config, ctx)(source); expect(frames).toEqual([ toEquableDataFrame({ name: 'long', @@ -339,7 +343,7 @@ describe('Prepare time series transformer', () => { format: timeSeriesFormat.TimeSeriesMany, }; - const frames = prepareTimeSeriesTransformer.transformer(config)(source); + const frames = prepareTimeSeriesTransformer.transformer(config, ctx)(source); expect(frames).toEqual([ toEquableDataFrame({ name: 'wants-to-be-many', diff --git a/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.ts b/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.ts index e53b7a4cb60..67493eeba1d 100644 --- a/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.ts +++ b/public/app/features/transformers/prepareTimeSeries/prepareTimeSeries.ts @@ -288,8 +288,8 @@ export const prepareTimeSeriesTransformer: SynchronousDataTransformerInfo (source) => - source.pipe(map((data) => prepareTimeSeriesTransformer.transformer(options)(data))), + operator: (options, ctx) => (source) => + source.pipe(map((data) => prepareTimeSeriesTransformer.transformer(options, ctx)(data))), transformer: (options: PrepareTimeSeriesOptions) => { const format = options?.format ?? timeSeriesFormat.TimeSeriesWide;