mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Add maxdatapoints in alert rule form (#61904)
Add maxdatapoints in alert rule form
This commit is contained in:
parent
7ebbd01688
commit
3b73b16245
@ -9,7 +9,7 @@ import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOp
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { AlertDataQuery, AlertQuery } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import { EmptyQueryWrapper, QueryWrapper } from './QueryWrapper';
|
||||
import { AlertQueryOptions, EmptyQueryWrapper, QueryWrapper } from './QueryWrapper';
|
||||
import { errorFromSeries, getThresholdsForQueries } from './util';
|
||||
|
||||
interface Props {
|
||||
@ -51,6 +51,21 @@ export class QueryRows extends PureComponent<Props> {
|
||||
);
|
||||
};
|
||||
|
||||
onChangeQueryOptions = (options: AlertQueryOptions, index: number) => {
|
||||
const { queries, onQueriesChange } = this.props;
|
||||
onQueriesChange(
|
||||
queries.map((item, itemIndex) => {
|
||||
if (itemIndex !== index) {
|
||||
return item;
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
model: { ...item.model, maxDataPoints: options.maxDataPoints },
|
||||
};
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
onChangeDataSource = (settings: DataSourceInstanceSettings, index: number) => {
|
||||
const { queries, onQueriesChange } = this.props;
|
||||
|
||||
@ -170,6 +185,7 @@ export class QueryRows extends PureComponent<Props> {
|
||||
onChangeDataSource={this.onChangeDataSource}
|
||||
onDuplicateQuery={this.props.onDuplicateQuery}
|
||||
onChangeTimeRange={this.onChangeTimeRange}
|
||||
onChangeQueryOptions={this.onChangeQueryOptions}
|
||||
thresholds={thresholdByRefId[query.refId]?.config}
|
||||
thresholdsType={thresholdByRefId[query.refId]?.mode}
|
||||
onRunQueries={this.props.onRunQueries}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import React, { FC, useState } from 'react';
|
||||
import React, { ChangeEvent, FC, useState } from 'react';
|
||||
|
||||
import {
|
||||
CoreApp,
|
||||
@ -14,7 +14,15 @@ import {
|
||||
ThresholdsConfig,
|
||||
} from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { RelativeTimeRangePicker, useStyles2, Tooltip, Icon, GraphTresholdsStyleMode } from '@grafana/ui';
|
||||
import {
|
||||
GraphTresholdsStyleMode,
|
||||
Icon,
|
||||
InlineFormLabel,
|
||||
Input,
|
||||
RelativeTimeRangePicker,
|
||||
Tooltip,
|
||||
useStyles2,
|
||||
} from '@grafana/ui';
|
||||
import { isExpressionQuery } from 'app/features/expressions/guards';
|
||||
import { QueryEditorRow } from 'app/features/query/components/QueryEditorRow';
|
||||
import { AlertQuery } from 'app/types/unified-alerting-dto';
|
||||
@ -25,6 +33,12 @@ import { AlertConditionIndicator } from '../expressions/AlertConditionIndicator'
|
||||
|
||||
import { VizWrapper } from './VizWrapper';
|
||||
|
||||
export const DEFAULT_MAX_DATA_POINTS = 43200;
|
||||
|
||||
export interface AlertQueryOptions {
|
||||
maxDataPoints?: number | undefined;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
data: PanelData;
|
||||
error?: Error;
|
||||
@ -43,6 +57,7 @@ interface Props {
|
||||
onChangeThreshold?: (thresholds: ThresholdsConfig, index: number) => void;
|
||||
condition: string | null;
|
||||
onSetCondition: (refId: string) => void;
|
||||
onChangeQueryOptions: (options: AlertQueryOptions, index: number) => void;
|
||||
}
|
||||
|
||||
export const QueryWrapper: FC<Props> = ({
|
||||
@ -63,6 +78,7 @@ export const QueryWrapper: FC<Props> = ({
|
||||
onChangeThreshold,
|
||||
condition,
|
||||
onSetCondition,
|
||||
onChangeQueryOptions,
|
||||
}) => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const isExpression = isExpressionQuery(query.model);
|
||||
@ -96,11 +112,16 @@ export const QueryWrapper: FC<Props> = ({
|
||||
|
||||
// TODO add a warning label here too when the data looks like time series data and is used as an alert condition
|
||||
function HeaderExtras({ query, error, index }: { query: AlertQuery; error?: Error; index: number }) {
|
||||
const queryOptions: AlertQueryOptions = { maxDataPoints: query.model.maxDataPoints };
|
||||
const alertQueryOptions: AlertQueryOptions = {
|
||||
maxDataPoints: queryOptions.maxDataPoints,
|
||||
};
|
||||
|
||||
if (isExpressionQuery(query.model)) {
|
||||
return null;
|
||||
} else {
|
||||
return (
|
||||
<Stack direction="row" alignItems="center" gap={1}>
|
||||
<Stack direction="row" alignItems="baseline" gap={1}>
|
||||
<SelectingDataSourceTooltip />
|
||||
{onChangeTimeRange && (
|
||||
<RelativeTimeRangePicker
|
||||
@ -108,6 +129,12 @@ export const QueryWrapper: FC<Props> = ({
|
||||
onChange={(range) => onChangeTimeRange(range, index)}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.queryOptions}>
|
||||
<MaxDataPointsOption
|
||||
options={alertQueryOptions}
|
||||
onChange={(options) => onChangeQueryOptions(options, index)}
|
||||
/>
|
||||
</div>
|
||||
<AlertConditionIndicator
|
||||
onSetCondition={() => onSetCondition(query.refId)}
|
||||
enabled={condition === query.refId}
|
||||
@ -159,6 +186,53 @@ export const EmptyQueryWrapper = ({ children }: React.PropsWithChildren<{}>) =>
|
||||
return <div className={styles.wrapper}>{children}</div>;
|
||||
};
|
||||
|
||||
function MaxDataPointsOption({
|
||||
options,
|
||||
onChange,
|
||||
}: {
|
||||
options: AlertQueryOptions;
|
||||
onChange: (options: AlertQueryOptions) => void;
|
||||
}) {
|
||||
const value = options.maxDataPoints ?? '';
|
||||
|
||||
const onMaxDataPointsBlur = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const maxDataPointsNumber = parseInt(event.target.value, 10);
|
||||
|
||||
const maxDataPoints = isNaN(maxDataPointsNumber) || maxDataPointsNumber === 0 ? undefined : maxDataPointsNumber;
|
||||
|
||||
if (maxDataPoints !== options.maxDataPoints) {
|
||||
onChange({
|
||||
...options,
|
||||
maxDataPoints,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack direction="row" alignItems="baseline" gap={1}>
|
||||
<InlineFormLabel
|
||||
width={8}
|
||||
tooltip={
|
||||
<>
|
||||
The maximum data points per series. Used directly by some data sources and used in calculation of auto
|
||||
interval. With streaming data this value is used for the rolling buffer.
|
||||
</>
|
||||
}
|
||||
>
|
||||
Max data points
|
||||
</InlineFormLabel>
|
||||
<Input
|
||||
type="number"
|
||||
className="width-6"
|
||||
placeholder={DEFAULT_MAX_DATA_POINTS.toLocaleString()}
|
||||
spellCheck={false}
|
||||
onBlur={onMaxDataPointsBlur}
|
||||
defaultValue={value}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
wrapper: css`
|
||||
label: AlertingQueryWrapper;
|
||||
@ -166,6 +240,9 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
border: 1px solid ${theme.colors.border.medium};
|
||||
border-radius: ${theme.shape.borderRadius(1)};
|
||||
`,
|
||||
queryOptions: css`
|
||||
margin-bottom: -${theme.spacing(2)};
|
||||
`,
|
||||
dsTooltip: css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createAction, createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
import { DataQuery, RelativeTimeRange, getDefaultRelativeTimeRange } from '@grafana/data';
|
||||
import { DataQuery, getDefaultRelativeTimeRange, RelativeTimeRange } from '@grafana/data';
|
||||
import { getNextRefIdChar } from 'app/core/utils/query';
|
||||
import { findDataSourceFromExpressionRecursive } from 'app/features/alerting/utils/dataSourceFromExpression';
|
||||
import {
|
||||
@ -43,6 +43,7 @@ export const updateExpressionRefId = createAction<{ oldRefId: string; newRefId:
|
||||
export const rewireExpressions = createAction<{ oldRefId: string; newRefId: string }>('rewireExpressions');
|
||||
export const updateExpressionType = createAction<{ refId: string; type: ExpressionQueryType }>('updateExpressionType');
|
||||
export const updateExpressionTimeRange = createAction('updateExpressionTimeRange');
|
||||
export const updateMaxDataPoints = createAction<{ refId: string; maxDataPoints: number }>('updateMaxDataPoints');
|
||||
|
||||
export const queriesAndExpressionsReducer = createReducer(initialState, (builder) => {
|
||||
// data queries actions
|
||||
@ -70,6 +71,19 @@ export const queriesAndExpressionsReducer = createReducer(initialState, (builder
|
||||
.addCase(setDataQueries, (state, { payload }) => {
|
||||
const expressionQueries = state.queries.filter((query) => isExpressionQuery(query.model));
|
||||
state.queries = [...payload, ...expressionQueries];
|
||||
})
|
||||
.addCase(updateMaxDataPoints, (state, action) => {
|
||||
state.queries = state.queries.map((query) => {
|
||||
return query.refId === action.payload.refId
|
||||
? {
|
||||
...query,
|
||||
model: {
|
||||
...query.model,
|
||||
maxDataPoints: action.payload.maxDataPoints,
|
||||
},
|
||||
}
|
||||
: query;
|
||||
});
|
||||
});
|
||||
|
||||
// expressions actions
|
||||
|
Loading…
Reference in New Issue
Block a user