diff --git a/public/app/features/alerting/unified/components/rule-editor/GrafanaEvaluationBehavior.tsx b/public/app/features/alerting/unified/components/rule-editor/GrafanaEvaluationBehavior.tsx index 5adcd6290ba..af7a49e0d37 100644 --- a/public/app/features/alerting/unified/components/rule-editor/GrafanaEvaluationBehavior.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/GrafanaEvaluationBehavior.tsx @@ -142,6 +142,7 @@ export function GrafanaEvaluationBehaviorStep({ getValues, formState: { errors }, control, + register, } = useFormContext(); const [group, type, isPaused, folder, evaluateEvery] = watch([ @@ -373,6 +374,29 @@ export function GrafanaEvaluationBehaviorStep({ name="execErrState" /> + + + )} diff --git a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/getPayloadToExport.test.ts b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/getPayloadToExport.test.ts index e56320efaf0..0eef7a6d641 100644 --- a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/getPayloadToExport.test.ts +++ b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/getPayloadToExport.test.ts @@ -118,6 +118,7 @@ const expectedModifiedRule2 = (uid: string) => ({ no_data_state: 'NoData', title: 'Rule2 updated', uid: uid, + missing_series_evals_to_resolve: 0, }, keep_firing_for: '1m', labels: { diff --git a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/__snapshots__/SimplifiedRuleEditor.test.tsx.snap b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/__snapshots__/SimplifiedRuleEditor.test.tsx.snap index f0d3bd665fd..9ffe68ad3b4 100644 --- a/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/__snapshots__/SimplifiedRuleEditor.test.tsx.snap +++ b/public/app/features/alerting/unified/components/rule-editor/alert-rule-form/simplifiedRouting/__snapshots__/SimplifiedRuleEditor.test.tsx.snap @@ -142,6 +142,7 @@ exports[`Can create a new grafana managed alert using simplified routing can cre ], "exec_err_state": "Error", "is_paused": false, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "notification_settings": { "receiver": "lotsa-emails", @@ -317,6 +318,7 @@ exports[`Can create a new grafana managed alert using simplified routing switch "simplified_query_and_expressions_section": false, }, }, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "title": "my great new rule", }, @@ -489,6 +491,7 @@ exports[`Can create a new grafana managed alert using simplified routing switch "simplified_query_and_expressions_section": true, }, }, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "notification_settings": { "receiver": "lotsa-emails", @@ -664,6 +667,7 @@ exports[`Can create a new grafana managed alert using simplified routing switch "simplified_query_and_expressions_section": true, }, }, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "title": "my great new rule", }, @@ -836,6 +840,7 @@ exports[`Can create a new grafana managed alert using simplified routing switch "simplified_query_and_expressions_section": false, }, }, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "notification_settings": { "receiver": "lotsa-emails", diff --git a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx index 993dd6958b9..20f4ab10263 100644 --- a/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx +++ b/public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx @@ -1,5 +1,6 @@ import { css } from '@emotion/css'; import { formatDistanceToNowStrict } from 'date-fns'; +import { isUndefined } from 'lodash'; import { GrafanaTheme2, dateTimeFormat, dateTimeFormatTimeAgo } from '@grafana/data'; import { config } from '@grafana/runtime'; @@ -77,6 +78,12 @@ export const Details = ({ rule }: DetailsProps) => { const updated = rulerRuleType.grafana.rule(rule.rulerRule) ? rule.rulerRule.grafana_alert.updated : undefined; const isPaused = rulerRuleType.grafana.rule(rule.rulerRule) && isPausedRule(rule.rulerRule); + const missingSeriesEvalsToResolve = + rulerRuleType.grafana.rule(rule.rulerRule) && + !isUndefined(rule.rulerRule.grafana_alert.missing_series_evals_to_resolve) + ? String(rule.rulerRule.grafana_alert.missing_series_evals_to_resolve) + : undefined; + const pausedIcon = ( @@ -152,7 +159,18 @@ export const Details = ({ rule }: DetailsProps) => { + )} + {missingSeriesEvalsToResolve && ( + )} diff --git a/public/app/features/alerting/unified/rule-editor/__snapshots__/RuleEditorGrafanaRules.test.tsx.snap b/public/app/features/alerting/unified/rule-editor/__snapshots__/RuleEditorGrafanaRules.test.tsx.snap index 16965687511..298f5e0542a 100644 --- a/public/app/features/alerting/unified/rule-editor/__snapshots__/RuleEditorGrafanaRules.test.tsx.snap +++ b/public/app/features/alerting/unified/rule-editor/__snapshots__/RuleEditorGrafanaRules.test.tsx.snap @@ -144,6 +144,7 @@ exports[`RuleEditor grafana managed rules can create new grafana managed alert 1 ], "exec_err_state": "Error", "is_paused": false, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "title": "my great new rule", }, @@ -252,6 +253,7 @@ exports[`RuleEditor grafana managed rules can restore grafana managed alert when "simplified_query_and_expressions_section": false, }, }, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "title": "Grafana-rule", }, diff --git a/public/app/features/alerting/unified/types/rule-form.ts b/public/app/features/alerting/unified/types/rule-form.ts index b7d02e431b4..0839b7f5b36 100644 --- a/public/app/features/alerting/unified/types/rule-form.ts +++ b/public/app/features/alerting/unified/types/rule-form.ts @@ -63,6 +63,7 @@ export interface RuleFormValues { keepFiringForTime?: number; keepFiringForTimeUnit?: string; expression: string; + missingSeriesEvalsToResolve?: number; } export type Folder = { title: string; uid: string }; diff --git a/public/app/features/alerting/unified/utils/__snapshots__/rule-form.test.ts.snap b/public/app/features/alerting/unified/utils/__snapshots__/rule-form.test.ts.snap index 4fad134846e..f29d42c4769 100644 --- a/public/app/features/alerting/unified/utils/__snapshots__/rule-form.test.ts.snap +++ b/public/app/features/alerting/unified/utils/__snapshots__/rule-form.test.ts.snap @@ -10,6 +10,7 @@ exports[`formValuesToRulerGrafanaRuleDTO should correctly convert rule form valu "exec_err_state": "Error", "is_paused": false, "metadata": undefined, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "notification_settings": undefined, "title": "", @@ -63,6 +64,7 @@ exports[`formValuesToRulerGrafanaRuleDTO should not save both instant and range "exec_err_state": "Error", "is_paused": false, "metadata": undefined, + "missing_series_evals_to_resolve": 0, "no_data_state": "NoData", "notification_settings": undefined, "title": "", diff --git a/public/app/features/alerting/unified/utils/rule-form.ts b/public/app/features/alerting/unified/utils/rule-form.ts index 94fef4b7740..ad0536595af 100644 --- a/public/app/features/alerting/unified/utils/rule-form.ts +++ b/public/app/features/alerting/unified/utils/rule-form.ts @@ -128,12 +128,14 @@ export function getNotificationSettingsForDTO( } return undefined; } + function getEditorSettingsForDTO(simplifiedEditor: SimplifiedEditor) { return { simplified_query_and_expressions_section: simplifiedEditor.simplifiedQueryEditor, simplified_notifications_section: simplifiedEditor.simplifiedNotificationEditor, }; } + export function formValuesToRulerGrafanaRuleDTO(values: RuleFormValues): PostableRuleGrafanaRuleDTO { const { name, @@ -149,6 +151,7 @@ export function formValuesToRulerGrafanaRuleDTO(values: RuleFormValues): Postabl type, metric, targetDatasourceUid, + missingSeriesEvalsToResolve, } = values; if (!condition) { throw new Error('You cannot create an alert rule without specifying the alert condition'); @@ -178,6 +181,10 @@ export function formValuesToRulerGrafanaRuleDTO(values: RuleFormValues): Postabl exec_err_state: execErrState, notification_settings: notificationSettings, metadata, + missing_series_evals_to_resolve: missingSeriesEvalsToResolve + ? Number(missingSeriesEvalsToResolve) + : // API uses 0 value to reset, as `missing_series_evals_to_resolve` cannot be 0 + 0, }, annotations, labels, @@ -315,6 +322,8 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF manualRouting: Boolean(routingSettings), editorSettings: getEditorSettingsFromDTO(ga), + + missingSeriesEvalsToResolve: ga.missing_series_evals_to_resolve, }; } else { throw new Error('Unexpected type of rule for grafana rules source'); diff --git a/public/app/types/unified-alerting-dto.ts b/public/app/types/unified-alerting-dto.ts index ca40add000d..14e350d26b6 100644 --- a/public/app/types/unified-alerting-dto.ts +++ b/public/app/types/unified-alerting-dto.ts @@ -268,6 +268,7 @@ export interface PostableGrafanaRuleDefinition { target_datasource_uid?: string; }; intervalSeconds?: number; + missing_series_evals_to_resolve?: number; } export interface GrafanaRuleDefinition extends PostableGrafanaRuleDefinition { id?: string; diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 8541acdc40e..740b481f973 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -297,6 +297,7 @@ "alert": { "alert-state": "Alert state", "annotations": "Annotations", + "description-missing-series-evaluations": "How many consecutive evaluation intervals with no data for a dimension must pass before the alert state is considered stale and automatically resolved. If no value is provided, the value will default to 2.", "evaluation": "Evaluation", "evaluation-paused": "Alert evaluation currently paused", "evaluation-paused-description": "Notifications for this rule will not fire and no alert instances will be created until the rule is un-paused.", @@ -305,6 +306,7 @@ "last-evaluation-duration": "Last evaluation duration", "last-updated-at": "Last updated at", "last-updated-by": "Last updated by", + "missing-series-resolve": "Missing series evaluations to resolve", "no-annotations": "No annotations", "pending-period": "Pending period", "rule": "Rule", @@ -923,6 +925,7 @@ "label-disable-resolved-message": "Disable resolved message" }, "grafana-evaluation-behavior-step": { + "missing-series-resolve-placeholder": "Default: 2", "or": "or", "text-configure-no-data-and-error-handling": "Configure no data and error handling", "title-set-evaluation-behavior": "Set evaluation behavior"