mirror of
https://github.com/grafana/grafana.git
synced 2024-11-23 09:26:43 -06:00
Alerting: misc fixes (#33070)
This commit is contained in:
parent
41f6af96c4
commit
382cab6406
@ -125,6 +125,11 @@ describe('RuleList', () => {
|
||||
groups: [
|
||||
mockPromRuleGroup({
|
||||
name: 'grafana-group',
|
||||
rules: [
|
||||
mockPromAlertingRule({
|
||||
query: '[]',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
|
@ -17,6 +17,7 @@ import RulesFilter from './components/rules/RulesFilter';
|
||||
import { RuleListGroupView } from './components/rules/RuleListGroupView';
|
||||
import { RuleListStateView } from './components/rules/RuleListStateView';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
const VIEWS = {
|
||||
groups: RuleListGroupView,
|
||||
@ -105,13 +106,15 @@ export const RuleList: FC = () => {
|
||||
)}
|
||||
{promReqeustErrors.map(({ dataSource, error }) => (
|
||||
<div key={dataSource.name}>
|
||||
Failed to load rules state from <a href={`datasources/edit/${dataSource.id}`}>{dataSource.name}</a>:{' '}
|
||||
Failed to load rules state from{' '}
|
||||
<a href={`${config.appSubUrl ?? ''}/datasources/edit/${dataSource.id}`}>{dataSource.name}</a>:{' '}
|
||||
{error.message || 'Unknown error.'}
|
||||
</div>
|
||||
))}
|
||||
{rulerRequestErrors.map(({ dataSource, error }) => (
|
||||
<div key={dataSource.name}>
|
||||
Failed to load rules config from <a href={`datasources/edit/${dataSource.id}`}>{dataSource.name}</a>:{' '}
|
||||
Failed to load rules config from{' '}
|
||||
<a href={`${config.appSubUrl ?? ''}/datasources/edit/${dataSource.id}`}>{dataSource.name}</a>:{' '}
|
||||
{error.message || 'Unknown error.'}
|
||||
</div>
|
||||
))}
|
||||
@ -123,19 +126,19 @@ export const RuleList: FC = () => {
|
||||
<div className={styles.break} />
|
||||
<div className={styles.buttonsContainer}>
|
||||
<ButtonGroup>
|
||||
<a href={urlUtil.renderUrl('/alerting/list', { ...queryParams, view: 'group' })}>
|
||||
<a href={urlUtil.renderUrl(`${config.appSubUrl ?? ''}/alerting/list`, { ...queryParams, view: 'group' })}>
|
||||
<ToolbarButton variant={view === 'groups' ? 'active' : 'default'} icon="folder">
|
||||
Groups
|
||||
</ToolbarButton>
|
||||
</a>
|
||||
<a href={urlUtil.renderUrl('/alerting/list', { ...queryParams, view: 'state' })}>
|
||||
<a href={urlUtil.renderUrl(`${config.appSubUrl ?? ''}/alerting/list`, { ...queryParams, view: 'state' })}>
|
||||
<ToolbarButton variant={view === 'state' ? 'active' : 'default'} icon="heart-rate">
|
||||
State
|
||||
</ToolbarButton>
|
||||
</a>
|
||||
</ButtonGroup>
|
||||
<div />
|
||||
<a href="/alerting/new">
|
||||
<a href={`${config.appSubUrl ?? ''}/alerting/new`}>
|
||||
<Button icon="plus">New alert rule</Button>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -18,6 +18,7 @@ import { useDispatch } from 'react-redux';
|
||||
import { useCleanup } from 'app/core/hooks/useCleanup';
|
||||
import { rulerRuleToFormValues, defaultFormValues } from '../../utils/rule-form';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
type Props = {
|
||||
existing?: RuleWithLocation;
|
||||
@ -56,6 +57,7 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
dispatch(
|
||||
saveRuleFormAction({
|
||||
values: {
|
||||
...defaultValues,
|
||||
...values,
|
||||
annotations: values.annotations?.filter(({ key }) => !!key) ?? [],
|
||||
labels: values.labels?.filter(({ key }) => !!key) ?? [],
|
||||
@ -70,7 +72,7 @@ export const AlertRuleForm: FC<Props> = ({ existing }) => {
|
||||
<FormContext {...formAPI}>
|
||||
<form onSubmit={handleSubmit((values) => submit(values, false))} className={styles.form}>
|
||||
<PageToolbar title="Create alert rule" pageIcon="bell" className={styles.toolbar}>
|
||||
<Link to="/alerting/list">
|
||||
<Link to={`${config.appSubUrl ?? ''}/alerting/list`}>
|
||||
<ToolbarButton variant="default" disabled={submitState.loading} type="button">
|
||||
Cancel
|
||||
</ToolbarButton>
|
||||
|
@ -1,11 +1,12 @@
|
||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||
import React, { FC } from 'react';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
export const NoRulesSplash: FC = () => (
|
||||
<EmptyListCTA
|
||||
title="You haven`t created any alert rules yet"
|
||||
buttonIcon="bell"
|
||||
buttonLink="/alerting/new"
|
||||
buttonLink={`${config.appSubUrl ?? ''}/alerting/new`}
|
||||
buttonTitle="New alert rule"
|
||||
proTip="you can also create alert rules from existing panels and queries."
|
||||
proTipLink="https://grafana.com/docs/"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CombinedRule, RulesSource } from 'app/types/unified-alerting';
|
||||
import React, { FC } from 'react';
|
||||
import React, { FC, useMemo } from 'react';
|
||||
import { useStyles } from '@grafana/ui';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
@ -10,6 +10,7 @@ import { AlertLabels } from '../AlertLabels';
|
||||
import { AlertInstancesTable } from './AlertInstancesTable';
|
||||
import { DetailsField } from './DetailsField';
|
||||
import { RuleQuery } from './RuleQuery';
|
||||
import { getDataSourceSrv } from '@grafana/runtime';
|
||||
|
||||
interface Props {
|
||||
rule: CombinedRule;
|
||||
@ -23,6 +24,23 @@ export const RuleDetails: FC<Props> = ({ rule, rulesSource }) => {
|
||||
|
||||
const annotations = Object.entries(rule.annotations);
|
||||
|
||||
const dataSources: Array<{ name: string; icon?: string }> = useMemo(() => {
|
||||
if (isCloudRulesSource(rulesSource)) {
|
||||
return [{ name: rulesSource.name, icon: rulesSource.meta.info.logos.small }];
|
||||
} else if (rule.queries) {
|
||||
return rule.queries
|
||||
.map(({ datasource }) => {
|
||||
const ds = getDataSourceSrv().getInstanceSettings(datasource);
|
||||
if (ds) {
|
||||
return { name: ds.name, icon: ds.meta.info.logos.small };
|
||||
}
|
||||
return { name: datasource };
|
||||
})
|
||||
.filter(({ name }) => name !== '__expr__');
|
||||
}
|
||||
return [];
|
||||
}, [rule, rulesSource]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.wrapper}>
|
||||
@ -42,9 +60,18 @@ export const RuleDetails: FC<Props> = ({ rule, rulesSource }) => {
|
||||
))}
|
||||
</div>
|
||||
<div className={styles.rightSide}>
|
||||
{isCloudRulesSource(rulesSource) && (
|
||||
{!!dataSources.length && (
|
||||
<DetailsField label="Data source">
|
||||
<img className={styles.dataSourceIcon} src={rulesSource.meta.info.logos.small} /> {rulesSource.name}
|
||||
{dataSources.map(({ name, icon }) => (
|
||||
<div key={name}>
|
||||
{icon && (
|
||||
<>
|
||||
<img className={styles.dataSourceIcon} src={icon} />{' '}
|
||||
</>
|
||||
)}
|
||||
{name}
|
||||
</div>
|
||||
))}
|
||||
</DetailsField>
|
||||
)}
|
||||
</div>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
import { CombinedRule, CombinedRuleNamespace } from 'app/types/unified-alerting';
|
||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||
import React, { FC, useMemo } from 'react';
|
||||
import { getFiltersFromUrlParams } from '../../utils/misc';
|
||||
import { isAlertingRule } from '../../utils/rules';
|
||||
import { RuleListStateSection } from './RuleListSateSection';
|
||||
|
||||
@ -11,6 +13,8 @@ interface Props {
|
||||
type GroupedRules = Record<PromAlertingRuleState, CombinedRule[]>;
|
||||
|
||||
export const RuleListStateView: FC<Props> = ({ namespaces }) => {
|
||||
const filters = getFiltersFromUrlParams(useQueryParams()[0]);
|
||||
|
||||
const groupedRules = useMemo(() => {
|
||||
const result: GroupedRules = {
|
||||
[PromAlertingRuleState.Firing]: [],
|
||||
@ -34,13 +38,22 @@ export const RuleListStateView: FC<Props> = ({ namespaces }) => {
|
||||
}, [namespaces]);
|
||||
return (
|
||||
<>
|
||||
<RuleListStateSection state={PromAlertingRuleState.Firing} rules={groupedRules[PromAlertingRuleState.Firing]} />
|
||||
<RuleListStateSection state={PromAlertingRuleState.Pending} rules={groupedRules[PromAlertingRuleState.Pending]} />
|
||||
<RuleListStateSection
|
||||
defaultCollapsed={true}
|
||||
state={PromAlertingRuleState.Inactive}
|
||||
rules={groupedRules[PromAlertingRuleState.Inactive]}
|
||||
/>
|
||||
{(!filters.alertState || filters.alertState === PromAlertingRuleState.Firing) && (
|
||||
<RuleListStateSection state={PromAlertingRuleState.Firing} rules={groupedRules[PromAlertingRuleState.Firing]} />
|
||||
)}
|
||||
{(!filters.alertState || filters.alertState === PromAlertingRuleState.Pending) && (
|
||||
<RuleListStateSection
|
||||
state={PromAlertingRuleState.Pending}
|
||||
rules={groupedRules[PromAlertingRuleState.Pending]}
|
||||
/>
|
||||
)}
|
||||
{(!filters.alertState || filters.alertState === PromAlertingRuleState.Inactive) && (
|
||||
<RuleListStateSection
|
||||
defaultCollapsed={filters.alertState !== PromAlertingRuleState.Inactive}
|
||||
state={PromAlertingRuleState.Inactive}
|
||||
rules={groupedRules[PromAlertingRuleState.Inactive]}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import React, { FC, useMemo, useState, Fragment } from 'react';
|
||||
import { Icon, Tooltip, useStyles } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { css } from '@emotion/css';
|
||||
import { isAlertingRule } from '../../utils/rules';
|
||||
import { isAlertingRule, isGrafanaRulerRule } from '../../utils/rules';
|
||||
import { PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||
import { StateColoredText } from '../StateColoredText';
|
||||
import { CollapseToggle } from '../CollapseToggle';
|
||||
@ -12,6 +12,9 @@ import { GRAFANA_RULES_SOURCE_NAME, isCloudRulesSource } from '../../utils/datas
|
||||
import { ActionIcon } from './ActionIcon';
|
||||
import pluralize from 'pluralize';
|
||||
import { useHasRuler } from '../../hooks/useHasRuler';
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
interface Props {
|
||||
namespace: CombinedRuleNamespace;
|
||||
group: CombinedRuleGroup;
|
||||
@ -60,11 +63,28 @@ export const RulesGroup: FC<Props> = React.memo(({ group, namespace }) => {
|
||||
}
|
||||
|
||||
const actionIcons: React.ReactNode[] = [];
|
||||
if (hasRuler(rulesSource)) {
|
||||
actionIcons.push(<ActionIcon key="edit" icon="pen" tooltip="edit" />);
|
||||
}
|
||||
|
||||
// for grafana, link to folder views
|
||||
if (rulesSource === GRAFANA_RULES_SOURCE_NAME) {
|
||||
actionIcons.push(<ActionIcon key="manage-perms" icon="lock" tooltip="manage permissions" />);
|
||||
const rulerRule = group.rules[0]?.rulerRule;
|
||||
const folderUID = rulerRule && isGrafanaRulerRule(rulerRule) && rulerRule.grafana_alert.namespace_uid;
|
||||
if (folderUID) {
|
||||
const baseUrl = `${config.appSubUrl ?? ''}/dashboards/f/${folderUID}/${kbn.slugifyForUrl(namespace.name)}`;
|
||||
actionIcons.push(
|
||||
<ActionIcon key="edit" icon="pen" tooltip="edit" href={baseUrl + '/settings'} target="__blank" />
|
||||
);
|
||||
actionIcons.push(
|
||||
<ActionIcon
|
||||
key="manage-perms"
|
||||
icon="lock"
|
||||
tooltip="manage permissions"
|
||||
href={baseUrl + '/permissions'}
|
||||
target="__blank"
|
||||
/>
|
||||
);
|
||||
} else if (hasRuler(rulesSource)) {
|
||||
actionIcons.push(<ActionIcon key="edit" icon="pen" tooltip="edit" />); // @TODO
|
||||
}
|
||||
}
|
||||
|
||||
const groupName = isCloudRulesSource(rulesSource) ? `${namespace.name} > ${group.name}` : namespace.name;
|
||||
|
@ -14,6 +14,7 @@ import { useDispatch } from 'react-redux';
|
||||
import { deleteRuleAction } from '../../state/actions';
|
||||
import { useHasRuler } from '../../hooks/useHasRuler';
|
||||
import { CombinedRule } from 'app/types/unified-alerting';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
interface Props {
|
||||
rules: CombinedRule[];
|
||||
@ -145,7 +146,7 @@ export const RulesTable: FC<Props> = ({
|
||||
<ActionIcon
|
||||
icon="pen"
|
||||
tooltip="edit rule"
|
||||
href={`/alerting/${encodeURIComponent(
|
||||
href={`${config.appSubUrl ?? ''}/alerting/${encodeURIComponent(
|
||||
stringifyRuleIdentifier(
|
||||
getRuleIdentifier(getRulesSourceName(rulesSource), namespace.name, group.name, rulerRule)
|
||||
)
|
||||
|
@ -120,6 +120,7 @@ function promRuleToCombinedRule(rule: Rule, namespace: CombinedRuleNamespace, gr
|
||||
return {
|
||||
name: rule.name,
|
||||
query: rule.query,
|
||||
queries: rule.query && isGrafanaRulesSource(namespace.rulesSource) ? JSON.parse(rule.query) : undefined,
|
||||
labels: rule.labels || {},
|
||||
annotations: isAlertingRule(rule) ? rule.annotations || {} : {},
|
||||
promRule: rule,
|
||||
@ -155,9 +156,10 @@ function rulerRuleToCombinedRule(
|
||||
}
|
||||
: {
|
||||
name: rule.grafana_alert.title,
|
||||
queries: rule.grafana_alert.data.map((d) => d.model),
|
||||
query: '',
|
||||
labels: rule.grafana_alert.labels || {},
|
||||
annotations: rule.grafana_alert.annotations || {},
|
||||
labels: rule.labels || {},
|
||||
annotations: rule.annotations || {},
|
||||
rulerRule: rule,
|
||||
namespace,
|
||||
group,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { CombinedRuleGroup, CombinedRuleNamespace, RuleFilterState } from 'app/types/unified-alerting';
|
||||
import { isCloudRulesSource } from '../utils/datasource';
|
||||
import { isCloudRulesSource, isGrafanaRulesSource } from '../utils/datasource';
|
||||
import { isAlertingRule } from '../utils/rules';
|
||||
import { getFiltersFromUrlParams } from '../utils/misc';
|
||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||
@ -45,7 +45,13 @@ const reduceNamespaces = (filters: RuleFilterState) => {
|
||||
const reduceGroups = (filters: RuleFilterState) => {
|
||||
return (groupAcc: CombinedRuleGroup[], group: CombinedRuleGroup) => {
|
||||
const rules = group.rules.filter((rule) => {
|
||||
let shouldKeep = true;
|
||||
if (
|
||||
filters.dataSource &&
|
||||
isGrafanaRulesSource(rule.namespace.rulesSource) &&
|
||||
!rule.queries?.find(({ datasource }) => datasource === filters.dataSource)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
// Query strings can match alert name, label keys, and label values
|
||||
if (filters.queryString) {
|
||||
const normalizedQueryString = filters.queryString.toLocaleLowerCase();
|
||||
@ -56,16 +62,17 @@ const reduceGroups = (filters: RuleFilterState) => {
|
||||
key.toLocaleLowerCase().includes(normalizedQueryString) ||
|
||||
value.toLocaleLowerCase().includes(normalizedQueryString)
|
||||
);
|
||||
shouldKeep = doesNameContainsQueryString || doLabelsContainQueryString;
|
||||
if (!(doesNameContainsQueryString || doLabelsContainQueryString)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (filters.alertState) {
|
||||
const matchesAlertState = Boolean(
|
||||
rule.promRule && isAlertingRule(rule.promRule) && rule.promRule.state === filters.alertState
|
||||
);
|
||||
|
||||
shouldKeep = shouldKeep && matchesAlertState;
|
||||
if (
|
||||
filters.alertState &&
|
||||
!(rule.promRule && isAlertingRule(rule.promRule) && rule.promRule.state === filters.alertState)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return shouldKeep;
|
||||
return true;
|
||||
});
|
||||
// Add rules to the group that match the rule list filters
|
||||
if (rules.length) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { AppEvents } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { locationService, config } from '@grafana/runtime';
|
||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||
import { appEvents } from 'app/core/core';
|
||||
import { AlertManagerCortexConfig, Silence } from 'app/plugins/datasource/alertmanager/types';
|
||||
@ -159,7 +159,8 @@ export function deleteRuleAction(ruleIdentifier: RuleIdentifier): ThunkResult<vo
|
||||
}
|
||||
await deleteRule(ruleWithLocation);
|
||||
// refetch rules for this rules source
|
||||
return dispatch(fetchRulerRulesAction(ruleWithLocation.ruleSourceName));
|
||||
dispatch(fetchRulerRulesAction(ruleWithLocation.ruleSourceName));
|
||||
dispatch(fetchPromRulesAction(ruleWithLocation.ruleSourceName));
|
||||
};
|
||||
}
|
||||
|
||||
@ -295,10 +296,12 @@ export const saveRuleFormAction = createAsyncThunk(
|
||||
throw new Error('Unexpected rule form type');
|
||||
}
|
||||
if (exitOnSave) {
|
||||
locationService.push('/alerting/list');
|
||||
locationService.push(`${config.appSubUrl ?? ''}/alerting/list`);
|
||||
} else {
|
||||
// redirect to edit page
|
||||
const newLocation = `/alerting/${encodeURIComponent(stringifyRuleIdentifier(identifier))}/edit`;
|
||||
const newLocation = `${config.appSubUrl ?? ''}/alerting/${encodeURIComponent(
|
||||
stringifyRuleIdentifier(identifier)
|
||||
)}/edit`;
|
||||
if (locationService.getLocation().pathname !== newLocation) {
|
||||
locationService.replace(newLocation);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { describeInterval, secondsToHms } from '@grafana/data/src/datetime/rangeutil';
|
||||
import { RuleWithLocation } from 'app/types/unified-alerting';
|
||||
import {
|
||||
Annotations,
|
||||
@ -55,11 +54,6 @@ function parseInterval(value: string): [number, string] {
|
||||
throw new Error(`Invalid interval description: ${value}`);
|
||||
}
|
||||
|
||||
function intervalToSeconds(interval: string): number {
|
||||
const { sec, count } = describeInterval(interval);
|
||||
return sec * count;
|
||||
}
|
||||
|
||||
function listifyLabelsOrAnnotations(item: Labels | Annotations | undefined): Array<{ key: string; value: string }> {
|
||||
return [...recordToArray(item || {}), { key: '', value: '' }];
|
||||
}
|
||||
@ -71,13 +65,13 @@ export function formValuesToRulerGrafanaRuleDTO(values: RuleFormValues): Postabl
|
||||
grafana_alert: {
|
||||
title: name,
|
||||
condition,
|
||||
for: intervalToSeconds(evaluateFor), // @TODO provide raw string once backend supports it
|
||||
no_data_state: noDataState,
|
||||
exec_err_state: execErrState,
|
||||
data: queries,
|
||||
annotations: arrayToRecord(values.annotations || []),
|
||||
labels: arrayToRecord(values.labels || []),
|
||||
},
|
||||
for: evaluateFor,
|
||||
annotations: arrayToRecord(values.annotations || []),
|
||||
labels: arrayToRecord(values.labels || []),
|
||||
};
|
||||
}
|
||||
throw new Error('Cannot create rule without specifying alert condition');
|
||||
@ -93,14 +87,14 @@ export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleF
|
||||
name: ga.title,
|
||||
type: RuleFormType.threshold,
|
||||
dataSourceName: ga.data[0]?.model.datasource,
|
||||
evaluateFor: secondsToHms(ga.for),
|
||||
evaluateFor: rule.for,
|
||||
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
||||
noDataState: ga.no_data_state,
|
||||
execErrState: ga.exec_err_state,
|
||||
queries: ga.data,
|
||||
condition: ga.condition,
|
||||
annotations: listifyLabelsOrAnnotations(ga.annotations),
|
||||
labels: listifyLabelsOrAnnotations(ga.labels),
|
||||
annotations: listifyLabelsOrAnnotations(rule.annotations),
|
||||
labels: listifyLabelsOrAnnotations(rule.labels),
|
||||
folder: { title: namespace, id: -1 },
|
||||
};
|
||||
} else {
|
||||
|
@ -113,12 +113,9 @@ export interface PostableGrafanaRuleDefinition {
|
||||
uid?: string;
|
||||
title: string;
|
||||
condition: string;
|
||||
for: number; //@TODO Sofia will update to accept string
|
||||
no_data_state: GrafanaAlertState;
|
||||
exec_err_state: GrafanaAlertState;
|
||||
data: GrafanaQuery[];
|
||||
annotations: Annotations;
|
||||
labels: Labels;
|
||||
}
|
||||
export interface GrafanaRuleDefinition extends PostableGrafanaRuleDefinition {
|
||||
uid: string;
|
||||
@ -127,12 +124,16 @@ export interface GrafanaRuleDefinition extends PostableGrafanaRuleDefinition {
|
||||
|
||||
export interface RulerGrafanaRuleDTO {
|
||||
grafana_alert: GrafanaRuleDefinition;
|
||||
// labels?: Labels; @TODO to be discussed
|
||||
// annotations?: Annotations;
|
||||
for: string;
|
||||
annotations: Annotations;
|
||||
labels: Labels;
|
||||
}
|
||||
|
||||
export interface PostableRuleGrafanaRuleDTO {
|
||||
grafana_alert: PostableGrafanaRuleDefinition;
|
||||
for: string;
|
||||
annotations: Annotations;
|
||||
labels: Labels;
|
||||
}
|
||||
|
||||
export type RulerRuleDTO = RulerAlertingRuleDTO | RulerRecordingRuleDTO | RulerGrafanaRuleDTO;
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
Labels,
|
||||
Annotations,
|
||||
RulerRuleGroupDTO,
|
||||
GrafanaQueryModel,
|
||||
} from './unified-alerting-dto';
|
||||
|
||||
export type Alert = {
|
||||
@ -81,6 +82,7 @@ export interface CombinedRule {
|
||||
rulerRule?: RulerRuleDTO;
|
||||
group: CombinedRuleGroup;
|
||||
namespace: CombinedRuleNamespace;
|
||||
queries?: GrafanaQueryModel[];
|
||||
}
|
||||
|
||||
export interface CombinedRuleGroup {
|
||||
|
Loading…
Reference in New Issue
Block a user