Alerting: allow creating/editing recording rules for Loki and Cortex (#38064)

This commit is contained in:
Domas
2021-08-24 11:31:56 +03:00
committed by GitHub
parent 309d263531
commit 9d8f61c738
12 changed files with 255 additions and 42 deletions

View File

@@ -121,7 +121,7 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
{showStep2 && (
<>
<QueryStep />
{type === RuleFormType.cloud ? <CloudConditionsStep /> : <GrafanaConditionsStep />}
{type === RuleFormType.grafana ? <GrafanaConditionsStep /> : <CloudConditionsStep />}
<DetailsStep />
</>
)}

View File

@@ -40,19 +40,24 @@ export const AlertTypeStep: FC<Props> = ({ editingExistingRule }) => {
if (contextSrv.isEditor) {
result.push({
label: 'Cortex/Loki managed alert',
value: RuleFormType.cloud,
value: RuleFormType.cloudAlerting,
description: 'Alert based on a system or application behavior. Based on Prometheus.',
});
result.push({
label: 'Cortex/Loki managed recording rule',
value: RuleFormType.cloudRecording,
description: 'Recording rule to pre-compute frequently needed or expensive calculations. Based on Prometheus.',
});
}
return result;
}, []);
return (
<RuleEditorSection stepNo={1} title="Alert type">
<RuleEditorSection stepNo={1} title="Rule type">
<Field
className={styles.formInput}
label="Alert name"
label="Rule name"
error={errors?.name?.message}
invalid={!!errors.name?.message}
>
@@ -65,7 +70,7 @@ export const AlertTypeStep: FC<Props> = ({ editingExistingRule }) => {
<div className={styles.flexRow}>
<Field
disabled={editingExistingRule}
label="Alert type"
label="Rule type"
className={styles.formInput}
error={errors.type?.message}
invalid={!!errors.type?.message}
@@ -87,7 +92,7 @@ export const AlertTypeStep: FC<Props> = ({ editingExistingRule }) => {
}}
/>
</Field>
{ruleFormType === RuleFormType.cloud && (
{(ruleFormType === RuleFormType.cloudRecording || ruleFormType === RuleFormType.cloudAlerting) && (
<Field
className={styles.formInput}
label="Select data source"
@@ -115,9 +120,9 @@ export const AlertTypeStep: FC<Props> = ({ editingExistingRule }) => {
</Field>
)}
</div>
{ruleFormType === RuleFormType.cloud && dataSourceName && (
<GroupAndNamespaceFields dataSourceName={dataSourceName} />
)}
{(ruleFormType === RuleFormType.cloudRecording || ruleFormType === RuleFormType.cloudAlerting) &&
dataSourceName && <GroupAndNamespaceFields dataSourceName={dataSourceName} />}
{ruleFormType === RuleFormType.grafana && (
<Field
label="Folder"

View File

@@ -3,7 +3,7 @@ import { css } from '@emotion/css';
import { GrafanaTheme } from '@grafana/data';
import { Field, Input, InputControl, Select, useStyles } from '@grafana/ui';
import { useFormContext } from 'react-hook-form';
import { RuleFormValues } from '../../types/rule-form';
import { RuleFormType, RuleFormValues } from '../../types/rule-form';
import { timeOptions } from '../../utils/time';
import { RuleEditorSection } from './RuleEditorSection';
import { PreviewRule } from './PreviewRule';
@@ -13,9 +13,17 @@ export const CloudConditionsStep: FC = () => {
const {
register,
control,
watch,
formState: { errors },
} = useFormContext<RuleFormValues>();
const type = watch('type');
// cloud recording rules do not have alert conditions
if (type === RuleFormType.cloudRecording) {
return null;
}
return (
<RuleEditorSection stepNo={3} title="Define alert conditions">
<Field label="For" description="Expression has to be true for this long for the alert to be fired.">

View File

@@ -2,15 +2,27 @@ import React, { FC } from 'react';
import LabelsField from './LabelsField';
import AnnotationsField from './AnnotationsField';
import { RuleEditorSection } from './RuleEditorSection';
import { useFormContext } from 'react-hook-form';
import { RuleFormType, RuleFormValues } from '../../types/rule-form';
export const DetailsStep: FC = () => {
const { watch } = useFormContext<RuleFormValues>();
const type = watch('type');
return (
<RuleEditorSection
stepNo={4}
title="Add details for your alert"
description="Write a summary and add labels to help you better manage your alerts"
stepNo={type === RuleFormType.cloudRecording ? 3 : 4}
title={
type === RuleFormType.cloudRecording ? 'Add details for your recording rule' : 'Add details for your alert'
}
description={
type === RuleFormType.cloudRecording
? 'Add labels to help you better manage your rules'
: 'Write a summary and add labels to help you better manage your alerts'
}
>
<AnnotationsField />
{type !== RuleFormType.cloudRecording && <AnnotationsField />}
<LabelsField />
</RuleEditorSection>
);

View File

@@ -18,7 +18,7 @@ export function PreviewRule(): React.ReactElement | null {
const { getValues } = useFormContext();
const [type] = getValues(fields);
if (type === RuleFormType.cloud) {
if (type === RuleFormType.cloudRecording || type === RuleFormType.cloudAlerting) {
return null;
}
@@ -60,7 +60,7 @@ function createPreviewRequest(values: any[]): PreviewRuleRequest {
const [type, dataSourceName, condition, queries, expression] = values;
switch (type) {
case RuleFormType.cloud:
case RuleFormType.cloudAlerting:
return {
dataSourceName,
expr: expression,

View File

@@ -15,8 +15,11 @@ export const QueryStep: FC = () => {
const type = watch('type');
const dataSourceName = watch('dataSourceName');
return (
<RuleEditorSection stepNo={2} title="Create a query to be alerted on">
{type === RuleFormType.cloud && dataSourceName && (
<RuleEditorSection
stepNo={2}
title={type === RuleFormType.cloudRecording ? 'Create a query to be recorded' : 'Create a query to be alerted on'}
>
{(type === RuleFormType.cloudRecording || type === RuleFormType.cloudAlerting) && dataSourceName && (
<Field error={errors.expression?.message} invalid={!!errors.expression?.message}>
<InputControl
name="expression"