Alerting: misc fixes (#33070)

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