mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Hide reducer hint for alert creation editor (#98410)
This commit is contained in:
parent
bc96da3a95
commit
0e4b503352
@ -122,5 +122,9 @@ describe('Directed acyclic graph', () => {
|
|||||||
expect(() => dag.link('A', 'B')).toThrow('cannot link A to B since it would create a cycle');
|
expect(() => dag.link('A', 'B')).toThrow('cannot link A to B since it would create a cycle');
|
||||||
expect(() => dag.link('A', 'E')).toThrow('cannot link A to E since it would create a cycle');
|
expect(() => dag.link('A', 'E')).toThrow('cannot link A to E since it would create a cycle');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return undefined for unknown node id', () => {
|
||||||
|
expect(dag.getNode('404')).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -252,7 +252,7 @@ export class Graph {
|
|||||||
return new Edge();
|
return new Edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
getNode(name: string): Node {
|
getNode(name: string): Node | undefined {
|
||||||
return this.nodes[name];
|
return this.nodes[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,15 @@ import { uniqueId } from 'lodash';
|
|||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
|
||||||
import { DataFrame, GrafanaTheme2, LoadingState, PanelData, dateTimeFormat, isTimeSeriesFrames } from '@grafana/data';
|
import {
|
||||||
|
CoreApp,
|
||||||
|
DataFrame,
|
||||||
|
GrafanaTheme2,
|
||||||
|
LoadingState,
|
||||||
|
PanelData,
|
||||||
|
dateTimeFormat,
|
||||||
|
isTimeSeriesFrames,
|
||||||
|
} from '@grafana/data';
|
||||||
import { Alert, AutoSizeInput, Button, IconButton, Stack, Text, clearButtonStyles, useStyles2 } from '@grafana/ui';
|
import { Alert, AutoSizeInput, Button, IconButton, Stack, Text, clearButtonStyles, useStyles2 } from '@grafana/ui';
|
||||||
import { ClassicConditions } from 'app/features/expressions/components/ClassicConditions';
|
import { ClassicConditions } from 'app/features/expressions/components/ClassicConditions';
|
||||||
import { Math } from 'app/features/expressions/components/Math';
|
import { Math } from 'app/features/expressions/components/Math';
|
||||||
@ -95,7 +103,15 @@ export const Expression: FC<ExpressionProps> = ({
|
|||||||
return <Math onChange={onChangeQuery} query={query} labelWidth={'auto'} onRunQuery={() => {}} />;
|
return <Math onChange={onChangeQuery} query={query} labelWidth={'auto'} onRunQuery={() => {}} />;
|
||||||
|
|
||||||
case ExpressionQueryType.reduce:
|
case ExpressionQueryType.reduce:
|
||||||
return <Reduce onChange={onChangeQuery} refIds={availableRefIds} labelWidth={'auto'} query={query} />;
|
return (
|
||||||
|
<Reduce
|
||||||
|
onChange={onChangeQuery}
|
||||||
|
refIds={availableRefIds}
|
||||||
|
labelWidth={'auto'}
|
||||||
|
app={CoreApp.UnifiedAlerting}
|
||||||
|
query={query}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
case ExpressionQueryType.resample:
|
case ExpressionQueryType.resample:
|
||||||
return <Resample onChange={onChangeQuery} query={query} labelWidth={'auto'} refIds={availableRefIds} />;
|
return <Resample onChange={onChangeQuery} query={query} labelWidth={'auto'} refIds={availableRefIds} />;
|
||||||
|
@ -56,21 +56,21 @@ describe('working with dag', () => {
|
|||||||
dag.getNode('D');
|
dag.getNode('D');
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
|
|
||||||
expect(dag.getNode('A').inputEdges).toHaveLength(0);
|
expect(dag.getNode('A')!.inputEdges).toHaveLength(0);
|
||||||
expect(dag.getNode('A').outputEdges).toHaveLength(0);
|
expect(dag.getNode('A')!.outputEdges).toHaveLength(0);
|
||||||
|
|
||||||
expect(dag.getNode('B').inputEdges).toHaveLength(0);
|
expect(dag.getNode('B')!.inputEdges).toHaveLength(0);
|
||||||
expect(dag.getNode('B').outputEdges).toHaveLength(2);
|
expect(dag.getNode('B')!.outputEdges).toHaveLength(2);
|
||||||
expect(dag.getNode('B').outputEdges[0].outputNode).toHaveProperty('name', 'C');
|
expect(dag.getNode('B')!.outputEdges[0].outputNode).toHaveProperty('name', 'C');
|
||||||
expect(dag.getNode('B').outputEdges[1].outputNode).toHaveProperty('name', 'D');
|
expect(dag.getNode('B')!.outputEdges[1].outputNode).toHaveProperty('name', 'D');
|
||||||
|
|
||||||
expect(dag.getNode('C').inputEdges).toHaveLength(1);
|
expect(dag.getNode('C')!.inputEdges).toHaveLength(1);
|
||||||
expect(dag.getNode('C').inputEdges[0].inputNode).toHaveProperty('name', 'B');
|
expect(dag.getNode('C')!.inputEdges[0].inputNode).toHaveProperty('name', 'B');
|
||||||
expect(dag.getNode('C').outputEdges).toHaveLength(0);
|
expect(dag.getNode('C')!.outputEdges).toHaveLength(0);
|
||||||
|
|
||||||
expect(dag.getNode('D').inputEdges).toHaveLength(1);
|
expect(dag.getNode('D')!.inputEdges).toHaveLength(1);
|
||||||
expect(dag.getNode('D').inputEdges[0].inputNode).toHaveProperty('name', 'B');
|
expect(dag.getNode('D')!.inputEdges[0].inputNode).toHaveProperty('name', 'B');
|
||||||
expect(dag.getNode('D').outputEdges).toHaveLength(0);
|
expect(dag.getNode('D')!.outputEdges).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('data queries cannot have references', () => {
|
test('data queries cannot have references', () => {
|
||||||
|
@ -66,6 +66,9 @@ export const getDescendants = memoize(_getDescendants, (refId, graph) => refId +
|
|||||||
|
|
||||||
export function _getOriginsOfRefId(refId: string, graph: Graph): string[] {
|
export function _getOriginsOfRefId(refId: string, graph: Graph): string[] {
|
||||||
const node = graph.getNode(refId);
|
const node = graph.getNode(refId);
|
||||||
|
if (!node) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const origins: Node[] = [];
|
const origins: Node[] = [];
|
||||||
|
|
||||||
@ -92,6 +95,10 @@ export function _getOriginsOfRefId(refId: string, graph: Graph): string[] {
|
|||||||
// get all children (and children's children etc) from a given node
|
// get all children (and children's children etc) from a given node
|
||||||
export function _getDescendants(refId: string, graph: Graph): string[] {
|
export function _getDescendants(refId: string, graph: Graph): string[] {
|
||||||
const node = graph.getNode(refId);
|
const node = graph.getNode(refId);
|
||||||
|
if (!node) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const descendants: Node[] = [];
|
const descendants: Node[] = [];
|
||||||
|
|
||||||
// recurse through "node > outputEdges > outputNode"
|
// recurse through "node > outputEdges > outputNode"
|
||||||
|
@ -58,7 +58,7 @@ function useExpressionsCache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ExpressionQueryEditor(props: Props) {
|
export function ExpressionQueryEditor(props: Props) {
|
||||||
const { query, queries, onRunQuery, onChange } = props;
|
const { query, queries, onRunQuery, onChange, app } = props;
|
||||||
const { getCachedExpression, setCachedExpression } = useExpressionsCache();
|
const { getCachedExpression, setCachedExpression } = useExpressionsCache();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -83,7 +83,7 @@ export function ExpressionQueryEditor(props: Props) {
|
|||||||
return <Math onChange={onChange} query={query} labelWidth={labelWidth} onRunQuery={onRunQuery} />;
|
return <Math onChange={onChange} query={query} labelWidth={labelWidth} onRunQuery={onRunQuery} />;
|
||||||
|
|
||||||
case ExpressionQueryType.reduce:
|
case ExpressionQueryType.reduce:
|
||||||
return <Reduce refIds={refIds} onChange={onChange} labelWidth={labelWidth} query={query} />;
|
return <Reduce refIds={refIds} onChange={onChange} labelWidth={labelWidth} query={query} app={app} />;
|
||||||
|
|
||||||
case ExpressionQueryType.resample:
|
case ExpressionQueryType.resample:
|
||||||
return <Resample query={query} labelWidth={labelWidth} onChange={onChange} refIds={refIds} />;
|
return <Resample query={query} labelWidth={labelWidth} onChange={onChange} refIds={refIds} />;
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { CoreApp, SelectableValue } from '@grafana/data';
|
||||||
import { InlineField, InlineFieldRow, Input, Select, Alert } from '@grafana/ui';
|
import { Alert, InlineField, InlineFieldRow, Input, Select, TextLink } from '@grafana/ui';
|
||||||
import { Trans, t } from 'app/core/internationalization';
|
import { Trans, t } from 'app/core/internationalization';
|
||||||
|
|
||||||
import { ExpressionQuery, ExpressionQuerySettings, ReducerMode, reducerModes, reducerTypes } from '../types';
|
import { ExpressionQuery, ExpressionQuerySettings, ReducerMode, reducerModes, reducerTypes } from '../types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
app?: CoreApp;
|
||||||
labelWidth?: number | 'auto';
|
labelWidth?: number | 'auto';
|
||||||
refIds: Array<SelectableValue<string>>;
|
refIds: Array<SelectableValue<string>>;
|
||||||
query: ExpressionQuery;
|
query: ExpressionQuery;
|
||||||
onChange: (query: ExpressionQuery) => void;
|
onChange: (query: ExpressionQuery) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Reduce = ({ labelWidth = 'auto', onChange, refIds, query }: Props) => {
|
export const Reduce = ({ labelWidth = 'auto', onChange, app, refIds, query }: Props) => {
|
||||||
const reducer = reducerTypes.find((o) => o.value === query.reducer);
|
const reducer = reducerTypes.find((o) => o.value === query.reducer);
|
||||||
|
|
||||||
const onRefIdChange = (value: SelectableValue<string>) => {
|
const onRefIdChange = (value: SelectableValue<string>) => {
|
||||||
@ -72,22 +73,21 @@ export const Reduce = ({ labelWidth = 'auto', onChange, refIds, query }: Props)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// for Alerting we really don't want to add additional confusing messages that would be unhelpful to the majority of our users
|
||||||
const strictModeNotification = () => {
|
const strictModeNotification = () => {
|
||||||
if (mode !== ReducerMode.Strict) {
|
const isWithinAlerting = app === CoreApp.UnifiedAlerting;
|
||||||
|
if (mode !== ReducerMode.Strict || isWithinAlerting) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert title={t('reduce.strictMode.title', 'Strict Mode Behaviour')} severity="info">
|
<Alert title={t('reduce.strictMode.title', 'Strict Mode Behaviour')} severity="info">
|
||||||
<Trans i18nKey="reduce.strictMode.description">
|
<Trans i18nKey="reduce.strictMode.description">
|
||||||
When <code>Reduce Strict mode</code> is used, the <code>fill(null)</code> function (InfluxQL) will result in{' '}
|
When <code>Reduce Strict mode</code> is used, the <code>fill(null)</code> function (InfluxQL) will result in{' '}
|
||||||
<code>NaN</code>.{' '}
|
<code>NaN</code>.{' '}
|
||||||
<a
|
<TextLink href="https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/expression-queries/#reduction-modes">
|
||||||
href="https://grafana.com/docs/grafana/latest/panels-visualizations/query-transform-data/expression-queries/#sum"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
See the documentation for more details.
|
See the documentation for more details.
|
||||||
</a>
|
</TextLink>
|
||||||
</Trans>
|
</Trans>
|
||||||
</Alert>
|
</Alert>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user