mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add default input parameters for expressions (#51810)
This commit is contained in:
parent
3761e9efa8
commit
e46ee78bed
@ -328,6 +328,7 @@ describe('PanelAlertTabContent', () => {
|
||||
model: {
|
||||
refId: 'B',
|
||||
hide: false,
|
||||
expression: 'A',
|
||||
type: 'classic_conditions',
|
||||
datasource: {
|
||||
type: ExpressionDatasourceRef.type,
|
||||
|
@ -35,6 +35,7 @@ interface Props {
|
||||
interface State {
|
||||
panelDataByRefId: Record<string, PanelData>;
|
||||
}
|
||||
|
||||
export class QueryEditor extends PureComponent<Props, State> {
|
||||
private runner: AlertingQueryRunner;
|
||||
private queries: AlertQuery[];
|
||||
@ -100,12 +101,16 @@ export class QueryEditor extends PureComponent<Props, State> {
|
||||
onNewExpressionQuery = () => {
|
||||
const { queries } = this;
|
||||
|
||||
const lastQuery = queries.at(-1);
|
||||
const defaultParams = lastQuery ? [lastQuery.refId] : [];
|
||||
|
||||
this.onChangeQueries(
|
||||
addQuery(queries, {
|
||||
datasourceUid: ExpressionDatasourceUID,
|
||||
model: expressionDatasource.newQuery({
|
||||
type: ExpressionQueryType.classic,
|
||||
conditions: [defaultCondition],
|
||||
conditions: [{ ...defaultCondition, query: { params: defaultParams } }],
|
||||
expression: lastQuery?.refId,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
@ -220,6 +220,7 @@ const getDefaultExpression = (refId: string): AlertQuery => {
|
||||
},
|
||||
},
|
||||
],
|
||||
expression: 'A',
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -53,9 +53,9 @@ export class ExpressionDatasourceApi extends DataSourceWithBackend<ExpressionQue
|
||||
newQuery(query?: Partial<ExpressionQuery>): ExpressionQuery {
|
||||
return {
|
||||
refId: '--', // Replaced with query
|
||||
type: query?.type ?? ExpressionQueryType.math,
|
||||
datasource: ExpressionDatasourceRef,
|
||||
conditions: query?.conditions ?? undefined,
|
||||
type: query?.type ?? ExpressionQueryType.math,
|
||||
...query,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
import { DataSourceApi, QueryEditorProps, SelectableValue } from '@grafana/data';
|
||||
import { InlineField, Select } from '@grafana/ui';
|
||||
@ -13,15 +13,61 @@ import { getDefaults } from './utils/expressionTypes';
|
||||
type Props = QueryEditorProps<DataSourceApi<ExpressionQuery>, ExpressionQuery>;
|
||||
|
||||
const labelWidth = 14;
|
||||
export class ExpressionQueryEditor extends PureComponent<Props> {
|
||||
onSelectExpressionType = (item: SelectableValue<ExpressionQueryType>) => {
|
||||
const { query, onChange } = this.props;
|
||||
|
||||
onChange(getDefaults({ ...query, type: item.value! }));
|
||||
};
|
||||
type NonClassicExpressionType = Exclude<ExpressionQueryType, ExpressionQueryType.classic>;
|
||||
type ExpressionTypeConfigStorage = Partial<Record<NonClassicExpressionType, string>>;
|
||||
|
||||
renderExpressionType() {
|
||||
const { onChange, onRunQuery, query, queries } = this.props;
|
||||
function useExpressionsCache() {
|
||||
const expressionCache = useRef<ExpressionTypeConfigStorage>({});
|
||||
|
||||
const getCachedExpression = useCallback((queryType: ExpressionQueryType) => {
|
||||
switch (queryType) {
|
||||
case ExpressionQueryType.math:
|
||||
case ExpressionQueryType.reduce:
|
||||
case ExpressionQueryType.resample:
|
||||
return expressionCache.current[queryType];
|
||||
case ExpressionQueryType.classic:
|
||||
return undefined;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const setCachedExpression = useCallback((queryType: ExpressionQueryType, value: string | undefined) => {
|
||||
switch (queryType) {
|
||||
case ExpressionQueryType.math:
|
||||
expressionCache.current.math = value;
|
||||
break;
|
||||
|
||||
// We want to use the same value for Reduce and Resample
|
||||
case ExpressionQueryType.reduce:
|
||||
case ExpressionQueryType.resample:
|
||||
expressionCache.current.reduce = value;
|
||||
expressionCache.current.resample = value;
|
||||
break;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { getCachedExpression, setCachedExpression };
|
||||
}
|
||||
|
||||
export function ExpressionQueryEditor(props: Props) {
|
||||
const { query, queries, onRunQuery, onChange } = props;
|
||||
const { getCachedExpression, setCachedExpression } = useExpressionsCache();
|
||||
|
||||
useEffect(() => {
|
||||
setCachedExpression(query.type, query.expression);
|
||||
}, [query.expression, query.type, setCachedExpression]);
|
||||
|
||||
const onSelectExpressionType = useCallback(
|
||||
(item: SelectableValue<ExpressionQueryType>) => {
|
||||
const cachedExpression = getCachedExpression(item.value!);
|
||||
const defaults = getDefaults({ ...query, type: item.value! });
|
||||
|
||||
onChange({ ...defaults, expression: cachedExpression ?? defaults.expression });
|
||||
},
|
||||
[query, onChange, getCachedExpression]
|
||||
);
|
||||
|
||||
const renderExpressionType = () => {
|
||||
const refIds = queries!.filter((q) => query.refId !== q.refId).map((q) => ({ value: q.refId, label: q.refId }));
|
||||
|
||||
switch (query.type) {
|
||||
@ -37,19 +83,16 @@ export class ExpressionQueryEditor extends PureComponent<Props> {
|
||||
case ExpressionQueryType.classic:
|
||||
return <ClassicConditions onChange={onChange} query={query} refIds={refIds} />;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { query } = this.props;
|
||||
const selected = gelTypes.find((o) => o.value === query.type);
|
||||
const selected = gelTypes.find((o) => o.value === query.type);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<InlineField label="Operation" labelWidth={labelWidth}>
|
||||
<Select options={gelTypes} value={selected} onChange={this.onSelectExpressionType} width={25} />
|
||||
</InlineField>
|
||||
{this.renderExpressionType()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<InlineField label="Operation" labelWidth={labelWidth}>
|
||||
<Select options={gelTypes} value={selected} onChange={onSelectExpressionType} width={25} />
|
||||
</InlineField>
|
||||
{renderExpressionType()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -26,9 +26,12 @@ export const ClassicConditions: FC<Props> = ({ onChange, query, refIds }) => {
|
||||
|
||||
const onAddCondition = () => {
|
||||
if (query.conditions) {
|
||||
const lastParams = query.conditions.at(-1)?.query?.params ?? [];
|
||||
const newCondition: ClassicCondition = { ...defaultCondition, query: { params: lastParams } };
|
||||
|
||||
onChange({
|
||||
...query,
|
||||
conditions: query.conditions.length > 0 ? [...query.conditions, defaultCondition] : [defaultCondition],
|
||||
conditions: query.conditions.length > 0 ? [...query.conditions, newCondition] : [newCondition],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ export const getDefaults = (query: ExpressionQuery) => {
|
||||
if (!query.reducer) {
|
||||
query.reducer = ReducerID.mean;
|
||||
}
|
||||
query.expression = undefined;
|
||||
|
||||
break;
|
||||
|
||||
case ExpressionQueryType.resample:
|
||||
@ -24,10 +24,15 @@ export const getDefaults = (query: ExpressionQuery) => {
|
||||
query.reducer = undefined;
|
||||
break;
|
||||
|
||||
case ExpressionQueryType.math:
|
||||
query.expression = undefined;
|
||||
break;
|
||||
|
||||
case ExpressionQueryType.classic:
|
||||
if (!query.conditions) {
|
||||
query.conditions = [defaultCondition];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -159,6 +159,7 @@ export enum GrafanaAlertStateDecision {
|
||||
export interface AlertDataQuery extends DataQuery {
|
||||
maxDataPoints?: number;
|
||||
intervalMs?: number;
|
||||
expression?: string;
|
||||
}
|
||||
|
||||
export interface AlertQuery {
|
||||
|
Loading…
Reference in New Issue
Block a user