Alerting: Move alert rule name to the top left in alert form (#58579)

* Move alert rule name to the top left in alert form, and add a placeholder

* Update docs

* Fix lint error
This commit is contained in:
Sonia Aguilar
2022-11-21 09:11:02 +01:00
committed by GitHub
parent 8ac197b11c
commit 97bf3c1dca
10 changed files with 87 additions and 56 deletions
@@ -23,21 +23,22 @@ Watch this video to learn more about creating alerts: {{< vimeo 720001934 >}}
1. In the Grafana menu, click the **Alerting** (bell) icon to open the Alerting page listing existing alerts.
1. Click **New alert rule**. The new alerting rule page opens where the Grafana managed alerts option is selected by default.
1. In Step 1, add queries and expressions to evaluate, and then select the alert condition.
1. In Step 1, add the rule name.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 2, add queries and expressions to evaluate, and then select the alert condition.
- For queries, select a data source from the drop-down.
- Add one or more [queries]({{< relref "../../panels-visualizations/query-transform-data/#add-a-query/" >}}) or [expressions]({{< relref "../../panels-visualizations/query-transform-data/expression-queries/" >}}).
- For each expression, select either **Classic condition** to create a single alert rule, or choose from **Math**, **Reduce**, **Resample** options to generate separate alert for each series. For details on these options, see [Single and multi dimensional rule](#single-and-multi-dimensional-rule).
- Click **Run queries** to verify that the query is successful.
- Next, select the query or expression for your alert condition.
1. In Step 2, specify the alert evaluation interval.
1. In Step 3, specify the alert evaluation interval.
- From the **Condition** drop-down, select the query or expression to trigger the alert rule.
- For **Evaluate every**, specify the frequency of evaluation. Must be a multiple of 10 seconds. For examples, `1m`, `30s`.
- For **Evaluate for**, specify the duration for which the condition must be true before an alert fires.
> **Note:** Once a condition is breached, the alert goes into the Pending state. If the condition remains breached for the duration specified, the alert transitions to the `Firing` state, otherwise it reverts back to the `Normal` state.
- In **Configure no data and error handling**, configure alerting behavior in the absence of data. Use the guidelines in [No data and error handling](#no-data-and-error-handling).
- Click **Preview alerts** to check the result of running the query at this moment. Preview excludes no data and error handling.
1. In Step 3, add the rule name, storage location, rule group, as well as additional metadata associated with the rule.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 4, add the storage location, rule group, as well as additional metadata associated with the rule.
- From the **Folder** drop-down, select the folder where you want to store the rule.
- For **Group**, specify a pre-defined group. Newly created rules are appended to the end of the group. Rules within a group are run sequentially at a regular interval, with the same evaluation time.
- Add a description and summary to customize alert messages. Use the guidelines in [Annotations and labels for alerting]({{< relref "../fundamentals/annotation-label/" >}}).
@@ -37,11 +37,12 @@ To create a Grafana Mimir or Loki managed recording rule
1. In the Grafana menu, click the **Alerting** (bell) icon to open the Alerting page listing existing alerts.
1. Click **New alert rule**. The new alerting rule page opens where the **Grafana managed alert** option is selected by default.
1. In Step 1, select **Mimir or Loki recording rule** option.
1. In Step 1, add the rule name.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 2, select **Mimir or Loki recording rule** option.
- Select your Loki or Prometheus data source, add the query to evaluate, and then select the alert condition.
- Enter a PromQL or LogQL expression. The rule fires if the evaluation result has at least one series with a value that is greater than 0. An alert is created for each series.
1. In Step 2, add the rule name, namespace, rule group, as well as additional metadata associated with the rule.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 3, add the namespace, rule group, as well as additional metadata associated with the rule.
- From the **Namespace** drop-down, select an existing rule namespace. Otherwise, click Add new and enter a name to create a new one. Namespaces can contain one or more rule groups and only have an organizational purpose. For more information, see [Grafana Mimir or Loki rule groups and namespaces]({{< relref "edit-mimir-loki-namespace-group/" >}}).
- From the **Group** drop-down, select an existing group within the selected namespace. Otherwise, click **Add new** and enter a name to create a new one. Newly created rules are appended to the end of the group. Rules within a group are run sequentially at a regular interval, with the same evaluation time.
- Add a description and summary to customize alert messages. Use the guidelines in [Annotations and labels for alerting]({{< relref "../fundamentals/annotation-label/" >}}).
@@ -52,17 +53,18 @@ To create a Grafana Mimir or Loki managed recording rule
1. In the Grafana menu, click the **Alerting** (bell) icon to open the Alerting page listing existing alerts.
1. Click **New alert rule**.
1. In Step 1, add the rule name, type, and storage location.
1. In Step 1, add the rule name.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 2, add the type, and storage location.
- From the **Rule type** drop-down, select **Mimir / Loki managed alert**.
- From the **Select data source** drop-down, select an external Prometheus, an external Loki, or a Grafana Cloud data source.
- From the **Namespace** drop-down, select an existing rule namespace. Otherwise, click **Add new** and enter a name to create a new one. Namespaces can contain one or more rule groups and only have an organizational purpose.
- From the **Group** drop-down, select an existing group within the selected namespace. Otherwise, click **Add new** and enter a name to create a new one. Newly created rules are appended to the end of the group. Rules within a group are run sequentially at a regular interval, with the same evaluation time.
{{< figure src="/static/img/docs/alerting/unified/rule-edit-mimir-alert-type-8-0.png" max-width="550px" caption="Alert details" >}}
1. In Step 2, add the query to evaluate.
1. In Step 3, add the query to evaluate.
- Enter a PromQL or LogQL expression. The rule fires if the evaluation result has at least one series with a value that is greater than 0. An alert is created for each series.
{{< figure src="/static/img/docs/alerting/unified/rule-edit-mimir-query-8-0.png" max-width="550px" caption="Alert details" >}}
1. In Step 3, add additional metadata associated with the rule.
1. In Step 4, add additional metadata associated with the rule.
- Add a description and summary to customize alert messages. Use the guidelines in [Annotations and labels for alerting]({{< relref "../fundamentals/annotation-label/" >}}).
- Add Runbook URL, panel, dashboard, and alert IDs.
- Add custom labels.
@@ -37,14 +37,15 @@ Watch this video to learn more about how to create a Mimir managed alert rule: {
1. In the Grafana menu, click the **Alerting** (bell) icon to open the Alerting page listing existing alerts.
1. Click **New alert rule**. The new alerting rule page opens where the Grafana managed alerts option is selected by default.
1. In Step 1, select **Mimir or Loki alert** option.
1. In Step 1, add the rule name.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 2, select **Mimir or Loki alert** option.
- Next, select your Loki or Prometheus data source and add the query to evaluate.
- Enter a PromQL or LogQL expression to query. The rule fires if the evaluation result has at least one series with a value that is greater than 0. An alert is created for each series.
1. In Step 2, specify the alert evaluation interval.
1. In Step 3, specify the alert evaluation interval.
- In the **For** text box, specify the duration for which the condition must be true before an alert fires. If you specify `5m`, the condition must be true for 5 minutes before the alert fires.
> **Note:** Once a condition is met, the alert goes into the `Pending` state. If the condition remains active for the duration specified, the alert transitions to the `Firing` state, else it reverts to the `Normal` state.
1. In Step 3, add the rule name, namespace, rule group, as well as additional metadata associated with the rule.
- In **Rule name**, add a descriptive name. This name is displayed in the alert rule list. It is also the `alertname` label for every alert instance that is created from this rule.
1. In Step 4, add the namespace, rule group, as well as additional metadata associated with the rule.
- From the **Namespace** drop-down, select an existing rule namespace. Otherwise, click **Add new** and enter a name to create a new one. Namespaces can contain one or more rule groups and only have an organizational purpose. For more information, see [Grafana Mimir or Loki rule groups and namespaces]({{< relref "edit-mimir-loki-namespace-group/" >}}).
- From the **Group** drop-down, select an existing group within the selected namespace. Otherwise, click **Add new** and enter a name to create a new one. Newly created rules are appended to the end of the group. Rules within a group are run sequentially at a regular interval, with the same evaluation time.
- Add a description and summary to customize alert messages. Use the guidelines in [Annotations and labels for alerting]({{< relref "../fundamentals/annotation-label/" >}}).
@@ -4,7 +4,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import { Route, Router } from 'react-router-dom';
import { selectOptionInTest } from 'test/helpers/selectOptionInTest';
import { byLabelText, byRole, byTestId, byText } from 'testing-library-selector';
import { byRole, byTestId, byText } from 'testing-library-selector';
import { DataSourceInstanceSettings } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
@@ -76,7 +76,7 @@ function renderRuleEditor(identifier?: string) {
const ui = {
inputs: {
name: byLabelText('Rule name'),
name: byRole('textbox', { name: /rule name name for the alert rule\./i }),
alertType: byTestId('alert-type-picker'),
dataSource: byTestId('datasource-picker'),
folder: byTestId('folder-picker'),
@@ -1,11 +1,11 @@
import { css } from '@emotion/css';
import React, { FC, useMemo, useState } from 'react';
import { FormProvider, useForm, UseFormWatch } from 'react-hook-form';
import { FormProvider, useForm, useFormContext, UseFormWatch } from 'react-hook-form';
import { Link } from 'react-router-dom';
import { GrafanaTheme2 } from '@grafana/data';
import { logInfo } from '@grafana/runtime';
import { Button, ConfirmModal, CustomScrollbar, Spinner, useStyles2, HorizontalGroup } from '@grafana/ui';
import { Button, ConfirmModal, CustomScrollbar, Spinner, useStyles2, HorizontalGroup, Field, Input } from '@grafana/ui';
import { useAppNotification } from 'app/core/copy/appNotification';
import { useCleanup } from 'app/core/hooks/useCleanup';
import { useQueryParams } from 'app/core/hooks/useQueryParams';
@@ -24,8 +24,57 @@ import { CloudEvaluationBehavior } from './CloudEvaluationBehavior';
import { DetailsStep } from './DetailsStep';
import { GrafanaEvaluationBehavior } from './GrafanaEvaluationBehavior';
import { NotificationsStep } from './NotificationsStep';
import { RuleEditorSection } from './RuleEditorSection';
import { RuleInspector } from './RuleInspector';
import { QueryAndExpressionsStep } from './query-and-alert-condition/QueryAndExpressionsStep';
import { checkForPathSeparator } from './util';
const recordingRuleNameValidationPattern = {
message:
'Recording rule name must be valid metric name. It may only contain letters, numbers, and colons. It may not contain whitespace.',
value: /^[a-zA-Z_:][a-zA-Z0-9_:]*$/,
};
const AlertRuleNameInput = () => {
const styles = useStyles2(getStyles);
const {
register,
watch,
formState: { errors },
} = useFormContext<RuleFormValues & { location?: string }>();
const ruleFormType = watch('type');
return (
<RuleEditorSection stepNo={1} title="Set an alert rule name">
<Field
className={styles.formInput}
label="Rule name"
description="Name for the alert rule."
error={errors?.name?.message}
invalid={!!errors.name?.message}
>
<Input
id="name"
{...register('name', {
required: { value: true, message: 'Must enter an alert name' },
pattern: ruleFormType === RuleFormType.cloudRecording ? recordingRuleNameValidationPattern : undefined,
validate: {
pathSeparator: (value: string) => {
// we use the alert rule name as the "groupname" for Grafana managed alerts, so we can't allow path separators
if (ruleFormType === RuleFormType.grafana) {
return checkForPathSeparator(value);
}
return true;
},
},
})}
placeholder="Give your alert rule a name."
/>
</Field>
</RuleEditorSection>
);
};
type Props = {
existing?: RuleWithLocation;
@@ -160,6 +209,7 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
<div className={styles.contentOuter}>
<CustomScrollbar autoHeightMin="100%" hideHorizontalTrack={true}>
<div className={styles.contentInner}>
<AlertRuleNameInput />
<QueryAndExpressionsStep editingExistingRule={!!existing} />
{showStep2 && (
<>
@@ -222,5 +272,12 @@ const getStyles = (theme: GrafanaTheme2) => {
flex-direction: row;
justify-content: flex-start;
`,
formInput: css`
width: 275px;
& + & {
margin-left: ${theme.spacing(3)};
}
`,
};
};
@@ -28,7 +28,7 @@ export const CloudEvaluationBehavior = () => {
}
return (
<RuleEditorSection stepNo={2} title="Alert evaluation behavior">
<RuleEditorSection stepNo={3} title="Alert evaluation behavior">
<Field label="For" description="Expression has to be true for this long for the alert to be fired.">
<div className={styles.flexRow}>
<Field invalid={!!errors.forTime?.message} error={errors.forTime?.message} className={styles.inlineField}>
@@ -19,12 +19,6 @@ import { RuleEditorSection } from './RuleEditorSection';
import { RuleFolderPicker, Folder, containsSlashes } from './RuleFolderPicker';
import { checkForPathSeparator } from './util';
const recordingRuleNameValidationPattern = {
message:
'Recording rule name must be valid metric name. It may only contain letters, numbers, and colons. It may not contain whitespace.',
value: /^[a-zA-Z_:][a-zA-Z0-9_:]*$/,
};
interface DetailsStepProps {
initialFolder: RuleForm | null;
}
@@ -46,7 +40,7 @@ export const DetailsStep = ({ initialFolder }: DetailsStepProps) => {
return (
<RuleEditorSection
stepNo={type === RuleFormType.cloudRecording ? 2 : 3}
stepNo={type === RuleFormType.cloudRecording ? 3 : 4}
title={
type === RuleFormType.cloudRecording ? 'Add details for your recording rule' : 'Add details for your alert'
}
@@ -56,31 +50,6 @@ export const DetailsStep = ({ initialFolder }: DetailsStepProps) => {
: 'Write a summary and add labels to help you better manage your alerts'
}
>
<Field
className={styles.formInput}
label="Rule name"
error={errors?.name?.message}
invalid={!!errors.name?.message}
>
<Input
id="name"
{...register('name', {
required: { value: true, message: 'Must enter an alert name' },
pattern: ruleFormType === RuleFormType.cloudRecording ? recordingRuleNameValidationPattern : undefined,
validate: {
pathSeparator: (value: string) => {
// we use the alert rule name as the "groupname" for Grafana managed alerts, so we can't allow path separators
if (ruleFormType === RuleFormType.grafana) {
return checkForPathSeparator(value);
}
return true;
},
},
})}
/>
</Field>
{(ruleFormType === RuleFormType.cloudRecording || ruleFormType === RuleFormType.cloudAlerting) &&
dataSourceName && <GroupAndNamespaceFields rulesSourceName={dataSourceName} />}
@@ -91,7 +91,7 @@ export const GrafanaEvaluationBehavior = () => {
return (
// TODO remove "and alert condition" for recording rules
<RuleEditorSection stepNo={2} title="Alert evaluation behavior">
<RuleEditorSection stepNo={3} title="Alert evaluation behavior">
<Field
label="Evaluate"
description="Evaluation interval applies to every rule within a group. It can overwrite the interval of an existing alert rule."
@@ -5,7 +5,7 @@ import { useFormContext } from 'react-hook-form';
import { GrafanaTheme2 } from '@grafana/data';
import { Card, Link, useStyles2, useTheme2 } from '@grafana/ui';
import { RuleFormValues } from '../../types/rule-form';
import { RuleFormType, RuleFormValues } from '../../types/rule-form';
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
import LabelsField from './LabelsField';
@@ -15,14 +15,15 @@ export const NotificationsStep = () => {
const [hideFlowChart, setHideFlowChart] = useState(false);
const styles = useStyles2(getStyles);
const theme = useTheme2();
const { watch } = useFormContext<RuleFormValues & { location?: string }>();
const { watch } = useFormContext<RuleFormValues>();
const type = watch('type');
const dataSourceName = watch('dataSourceName') ?? GRAFANA_RULES_SOURCE_NAME;
return (
<RuleEditorSection
stepNo={4}
stepNo={type === RuleFormType.cloudRecording ? 4 : 5}
title="Notifications"
description="Grafana handles the notifications for alerts by assigning labels to alerts. These labels connect alerts to contact points and silence alert instances that have matching labels."
>
@@ -147,7 +147,7 @@ export const QueryAndExpressionsStep: FC<Props> = ({ editingExistingRule }) => {
}, [condition, queries, setValue]);
return (
<RuleEditorSection stepNo={1} title="Set a query and alert condition">
<RuleEditorSection stepNo={2} title="Set a query and alert condition">
<AlertType editingExistingRule={editingExistingRule} />
{/* This is the PromQL Editor for Cloud rules and recording rules */}