mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
SSE: Mode to drop NaN/Inf/Null in Reduction operations (#43583)
Co-authored-by: Yuriy Tseretyan <yuriy.tseretyan@grafana.com> Co-authored-by: gillesdemey <gilles.de.mey@gmail.com>
This commit is contained in:
co-authored by
Yuriy Tseretyan
gillesdemey
parent
0cb3037b55
commit
040ce40113
@@ -1,7 +1,7 @@
|
||||
import React, { FC } from 'react';
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
import { InlineField, InlineFieldRow, Select } from '@grafana/ui';
|
||||
import { ExpressionQuery, reducerTypes } from '../types';
|
||||
import { InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
|
||||
import { ExpressionQuery, ExpressionQuerySettings, ReducerMode, reducerMode, reducerTypes } from '../types';
|
||||
|
||||
interface Props {
|
||||
labelWidth: number;
|
||||
@@ -21,6 +21,49 @@ export const Reduce: FC<Props> = ({ labelWidth, onChange, refIds, query }) => {
|
||||
onChange({ ...query, reducer: value.value });
|
||||
};
|
||||
|
||||
const onSettingsChanged = (settings: ExpressionQuerySettings) => {
|
||||
onChange({ ...query, settings: settings });
|
||||
};
|
||||
|
||||
const onModeChanged = (value: SelectableValue<ReducerMode>) => {
|
||||
let newSettings: ExpressionQuerySettings;
|
||||
switch (value.value) {
|
||||
case ReducerMode.ReplaceNonNumbers:
|
||||
let replaceWithNumber = 0;
|
||||
if (query.settings?.mode === ReducerMode.ReplaceNonNumbers) {
|
||||
replaceWithNumber = query.settings?.replaceWithValue ?? 0;
|
||||
}
|
||||
newSettings = {
|
||||
mode: ReducerMode.ReplaceNonNumbers,
|
||||
replaceWithValue: replaceWithNumber,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
newSettings = {
|
||||
mode: value.value,
|
||||
};
|
||||
}
|
||||
onSettingsChanged(newSettings);
|
||||
};
|
||||
|
||||
const onReplaceWithChanged = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
const value = e.currentTarget.valueAsNumber;
|
||||
onSettingsChanged({ mode: ReducerMode.ReplaceNonNumbers, replaceWithValue: value ?? 0 });
|
||||
};
|
||||
|
||||
const mode = query.settings?.mode ?? ReducerMode.Strict;
|
||||
|
||||
const replaceWithNumber = () => {
|
||||
if (mode !== ReducerMode.ReplaceNonNumbers) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<InlineField label="Replace With" labelWidth={labelWidth}>
|
||||
<Input type="number" width={10} onChange={onReplaceWithChanged} value={query.settings?.replaceWithValue ?? 0} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<InlineFieldRow>
|
||||
<InlineField label="Function" labelWidth={labelWidth}>
|
||||
@@ -29,6 +72,10 @@ export const Reduce: FC<Props> = ({ labelWidth, onChange, refIds, query }) => {
|
||||
<InlineField label="Input" labelWidth={labelWidth}>
|
||||
<Select menuShouldPortal onChange={onRefIdChange} options={refIds} value={query.expression} width={20} />
|
||||
</InlineField>
|
||||
<InlineField label="Mode" labelWidth={labelWidth}>
|
||||
<Select menuShouldPortal onChange={onModeChanged} options={reducerMode} value={mode} width={25} />
|
||||
</InlineField>
|
||||
{replaceWithNumber()}
|
||||
</InlineFieldRow>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -24,6 +24,30 @@ export const reducerTypes: Array<SelectableValue<string>> = [
|
||||
{ value: ReducerID.last, label: 'Last', description: 'Get the last value' },
|
||||
];
|
||||
|
||||
export enum ReducerMode {
|
||||
Strict = '', // backend API wants an empty string to support "strict" mode
|
||||
ReplaceNonNumbers = 'replaceNN',
|
||||
DropNonNumbers = 'dropNN',
|
||||
}
|
||||
|
||||
export const reducerMode: Array<SelectableValue<ReducerMode>> = [
|
||||
{
|
||||
value: ReducerMode.Strict,
|
||||
label: 'Strict',
|
||||
description: 'Result can be NaN if series contains non-numeric data',
|
||||
},
|
||||
{
|
||||
value: ReducerMode.DropNonNumbers,
|
||||
label: 'Drop Non-numeric Values',
|
||||
description: 'Drop NaN, +/-Inf and null from input series before reducing',
|
||||
},
|
||||
{
|
||||
value: ReducerMode.ReplaceNonNumbers,
|
||||
label: 'Replace Non-numeric Values',
|
||||
description: 'Replace NaN, +/-Inf and null with a constant value before reducing',
|
||||
},
|
||||
];
|
||||
|
||||
export const downsamplingTypes: Array<SelectableValue<string>> = [
|
||||
{ value: ReducerID.min, label: 'Min', description: 'Fill with the minimum value' },
|
||||
{ value: ReducerID.max, label: 'Max', description: 'Fill with the maximum value' },
|
||||
@@ -49,7 +73,14 @@ export interface ExpressionQuery extends DataQuery {
|
||||
downsampler?: string;
|
||||
upsampler?: string;
|
||||
conditions?: ClassicCondition[];
|
||||
settings?: ExpressionQuerySettings;
|
||||
}
|
||||
|
||||
export interface ExpressionQuerySettings {
|
||||
mode?: ReducerMode;
|
||||
replaceWithValue?: number;
|
||||
}
|
||||
|
||||
export interface ClassicCondition {
|
||||
evaluator: {
|
||||
params: number[];
|
||||
|
||||
Reference in New Issue
Block a user