mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 09:33:34 -06:00
Transformers: Add template variable substitution (#44486)
* Transformers: Add template variable replacement to transformer operator * Transformers: Add template variable replacement to calculateField transformer * Transformers: Add scopedVars to transformer template replacement * Transformers: Add calculateField template variable test * Transformers: Fix 'undefined' is not assignable to type 'string' * Transformers: Fix lint-frontend bug * Fix lint check * Fix lint
This commit is contained in:
parent
52bd7618dd
commit
ea7d5a6185
@ -17,7 +17,9 @@ const getOperator =
|
||||
const options = { ...defaultOptions, ...config.options };
|
||||
|
||||
return source.pipe(
|
||||
mergeMap((before) => of(before).pipe(info.transformation.operator(options), postProcessTransform(before, info)))
|
||||
mergeMap((before) =>
|
||||
of(before).pipe(info.transformation.operator(options, config.replace), postProcessTransform(before, info))
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { transformDataFrame } from '../transformDataFrame';
|
||||
import { CalculateFieldMode, calculateFieldTransformer, ReduceOptions } from './calculateField';
|
||||
import { DataFrameView } from '../../dataframe';
|
||||
import { BinaryOperationID } from '../../utils';
|
||||
import { ScopedVars } from '../../types';
|
||||
|
||||
const seriesA = toDataFrame({
|
||||
fields: [
|
||||
@ -219,4 +220,63 @@ describe('calculateField transformer w/ timeseries', () => {
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
it('uses template variable substituion', async () => {
|
||||
const cfg = {
|
||||
id: DataTransformerID.calculateField,
|
||||
options: {
|
||||
alias: '$var1',
|
||||
mode: CalculateFieldMode.BinaryOperation,
|
||||
binary: {
|
||||
left: 'A',
|
||||
operator: BinaryOperationID.Add,
|
||||
right: '$var2',
|
||||
},
|
||||
replaceFields: true,
|
||||
},
|
||||
replace: (target: string | undefined, scopedVars?: ScopedVars, format?: string | Function): string => {
|
||||
if (!target) {
|
||||
return '';
|
||||
}
|
||||
const variables: ScopedVars = {
|
||||
var1: {
|
||||
value: 'Test',
|
||||
text: 'Test',
|
||||
},
|
||||
var2: {
|
||||
value: 5,
|
||||
text: '5',
|
||||
},
|
||||
__interval: {
|
||||
value: 10000,
|
||||
text: '10000',
|
||||
},
|
||||
};
|
||||
for (const key of Object.keys(variables)) {
|
||||
if (target === `$${key}`) {
|
||||
return variables[key].value + '';
|
||||
}
|
||||
}
|
||||
return target;
|
||||
},
|
||||
};
|
||||
|
||||
await expect(transformDataFrame([cfg], [seriesA])).toEmitValuesWith((received) => {
|
||||
const data = received[0];
|
||||
const filtered = data[0];
|
||||
const rows = new DataFrameView(filtered).toArray();
|
||||
expect(rows).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"Test": 6,
|
||||
"TheTime": 1000,
|
||||
},
|
||||
Object {
|
||||
"Test": 105,
|
||||
"TheTime": 2000,
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -71,10 +71,12 @@ export const calculateFieldTransformer: DataTransformerInfo<CalculateFieldTransf
|
||||
reducer: ReducerID.sum,
|
||||
},
|
||||
},
|
||||
operator: (options) => (outerSource) => {
|
||||
operator: (options, replace) => (outerSource) => {
|
||||
const operator =
|
||||
options && options.timeSeries !== false ? ensureColumnsTransformer.operator(null) : noopTransformer.operator({});
|
||||
|
||||
options.alias = replace ? replace(options.alias) : options.alias;
|
||||
|
||||
return outerSource.pipe(
|
||||
operator,
|
||||
map((data) => {
|
||||
@ -84,7 +86,14 @@ export const calculateFieldTransformer: DataTransformerInfo<CalculateFieldTransf
|
||||
if (mode === CalculateFieldMode.ReduceRow) {
|
||||
creator = getReduceRowCreator(defaults(options.reduce, defaultReduceOptions), data);
|
||||
} else if (mode === CalculateFieldMode.BinaryOperation) {
|
||||
creator = getBinaryCreator(defaults(options.binary, defaultBinaryOptions), data);
|
||||
const binaryOptions = replace
|
||||
? {
|
||||
...options.binary,
|
||||
left: replace ? replace(options.binary?.left) : options.binary?.left,
|
||||
right: replace ? replace(options.binary?.right) : options.binary?.right,
|
||||
}
|
||||
: options.binary;
|
||||
creator = getBinaryCreator(defaults(binaryOptions, defaultBinaryOptions), data);
|
||||
}
|
||||
|
||||
// Nothing configured
|
||||
|
@ -2,6 +2,7 @@ import { MonoTypeOperatorFunction } from 'rxjs';
|
||||
|
||||
import { DataFrame, Field } from './dataFrame';
|
||||
import { RegistryItemWithOptions } from '../utils/Registry';
|
||||
import { ScopedVars } from './ScopedVars';
|
||||
|
||||
/**
|
||||
* Function that transform data frames (AKA transformer)
|
||||
@ -13,7 +14,10 @@ export interface DataTransformerInfo<TOptions = any> extends RegistryItemWithOpt
|
||||
* Function that configures transformation and returns a transformer
|
||||
* @param options
|
||||
*/
|
||||
operator: (options: TOptions) => MonoTypeOperatorFunction<DataFrame[]>;
|
||||
operator: (
|
||||
options: TOptions,
|
||||
replace?: (target?: string, scopedVars?: ScopedVars, format?: string | Function) => string
|
||||
) => MonoTypeOperatorFunction<DataFrame[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,6 +46,10 @@ export interface DataTransformerConfig<TOptions = any> {
|
||||
* 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;
|
||||
|
@ -183,6 +183,13 @@ export class PanelQueryRunner {
|
||||
return of(data);
|
||||
}
|
||||
|
||||
const replace = (option: string): string => {
|
||||
return getTemplateSrv().replace(option, data?.request?.scopedVars);
|
||||
};
|
||||
transformations.forEach((transform: any) => {
|
||||
transform.replace = replace;
|
||||
});
|
||||
|
||||
return transformDataFrame(transformations, data.series).pipe(map((series) => ({ ...data, series })));
|
||||
})
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user