2021-05-04 22:31:25 +08:00
|
|
|
import { getDefaultTimeRange, rangeUtil } from '@grafana/data';
|
|
|
|
|
import { getDataSourceSrv } from '@grafana/runtime';
|
|
|
|
|
import { ExpressionDatasourceID, ExpressionDatasourceUID } from 'app/features/expressions/ExpressionDatasource';
|
|
|
|
|
import { ExpressionQuery, ExpressionQueryType } from 'app/features/expressions/types';
|
2021-04-16 16:08:26 +08:00
|
|
|
import { RuleWithLocation } from 'app/types/unified-alerting';
|
|
|
|
|
import {
|
|
|
|
|
Annotations,
|
|
|
|
|
GrafanaAlertState,
|
2021-05-04 22:31:25 +08:00
|
|
|
GrafanaQuery,
|
2021-04-16 16:08:26 +08:00
|
|
|
Labels,
|
|
|
|
|
PostableRuleGrafanaRuleDTO,
|
|
|
|
|
RulerAlertingRuleDTO,
|
|
|
|
|
} from 'app/types/unified-alerting-dto';
|
2021-05-04 22:31:25 +08:00
|
|
|
import { EvalFunction } from '../../state/alertDef';
|
2021-04-16 16:08:26 +08:00
|
|
|
import { RuleFormType, RuleFormValues } from '../types/rule-form';
|
|
|
|
|
import { isGrafanaRulesSource } from './datasource';
|
|
|
|
|
import { arrayToRecord, recordToArray } from './misc';
|
|
|
|
|
import { isAlertingRulerRule, isGrafanaRulerRule } from './rules';
|
2021-05-04 21:57:11 +08:00
|
|
|
import { parseInterval } from './time';
|
2021-04-16 16:08:26 +08:00
|
|
|
|
|
|
|
|
export const defaultFormValues: RuleFormValues = Object.freeze({
|
|
|
|
|
name: '',
|
|
|
|
|
labels: [{ key: '', value: '' }],
|
|
|
|
|
annotations: [{ key: '', value: '' }],
|
|
|
|
|
dataSourceName: null,
|
|
|
|
|
|
|
|
|
|
// threshold
|
|
|
|
|
folder: null,
|
2021-05-04 22:31:25 +08:00
|
|
|
queries: [],
|
2021-04-16 16:08:26 +08:00
|
|
|
condition: '',
|
|
|
|
|
noDataState: GrafanaAlertState.NoData,
|
|
|
|
|
execErrState: GrafanaAlertState.Alerting,
|
|
|
|
|
evaluateEvery: '1m',
|
|
|
|
|
evaluateFor: '5m',
|
|
|
|
|
|
|
|
|
|
// system
|
2021-04-16 19:57:33 +08:00
|
|
|
group: '',
|
|
|
|
|
namespace: '',
|
2021-04-16 16:08:26 +08:00
|
|
|
expression: '',
|
|
|
|
|
forTime: 1,
|
|
|
|
|
forTimeUnit: 'm',
|
|
|
|
|
});
|
2021-04-14 20:57:36 +08:00
|
|
|
|
|
|
|
|
export function formValuesToRulerAlertingRuleDTO(values: RuleFormValues): RulerAlertingRuleDTO {
|
|
|
|
|
const { name, expression, forTime, forTimeUnit } = values;
|
|
|
|
|
return {
|
|
|
|
|
alert: name,
|
|
|
|
|
for: `${forTime}${forTimeUnit}`,
|
|
|
|
|
annotations: arrayToRecord(values.annotations || []),
|
|
|
|
|
labels: arrayToRecord(values.labels || []),
|
|
|
|
|
expr: expression,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-16 16:08:26 +08:00
|
|
|
function listifyLabelsOrAnnotations(item: Labels | Annotations | undefined): Array<{ key: string; value: string }> {
|
|
|
|
|
return [...recordToArray(item || {}), { key: '', value: '' }];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function formValuesToRulerGrafanaRuleDTO(values: RuleFormValues): PostableRuleGrafanaRuleDTO {
|
2021-04-14 20:57:36 +08:00
|
|
|
const { name, condition, noDataState, execErrState, evaluateFor, queries } = values;
|
|
|
|
|
if (condition) {
|
|
|
|
|
return {
|
|
|
|
|
grafana_alert: {
|
|
|
|
|
title: name,
|
|
|
|
|
condition,
|
|
|
|
|
no_data_state: noDataState,
|
|
|
|
|
exec_err_state: execErrState,
|
|
|
|
|
data: queries,
|
|
|
|
|
},
|
2021-04-19 17:53:02 +08:00
|
|
|
for: evaluateFor,
|
|
|
|
|
annotations: arrayToRecord(values.annotations || []),
|
|
|
|
|
labels: arrayToRecord(values.labels || []),
|
2021-04-14 20:57:36 +08:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
throw new Error('Cannot create rule without specifying alert condition');
|
|
|
|
|
}
|
2021-04-16 16:08:26 +08:00
|
|
|
|
|
|
|
|
export function rulerRuleToFormValues(ruleWithLocation: RuleWithLocation): RuleFormValues {
|
|
|
|
|
const { ruleSourceName, namespace, group, rule } = ruleWithLocation;
|
|
|
|
|
if (isGrafanaRulesSource(ruleSourceName)) {
|
|
|
|
|
if (isGrafanaRulerRule(rule)) {
|
|
|
|
|
const ga = rule.grafana_alert;
|
|
|
|
|
return {
|
|
|
|
|
...defaultFormValues,
|
|
|
|
|
name: ga.title,
|
|
|
|
|
type: RuleFormType.threshold,
|
2021-04-19 17:53:02 +08:00
|
|
|
evaluateFor: rule.for,
|
2021-04-16 16:08:26 +08:00
|
|
|
evaluateEvery: group.interval || defaultFormValues.evaluateEvery,
|
|
|
|
|
noDataState: ga.no_data_state,
|
|
|
|
|
execErrState: ga.exec_err_state,
|
|
|
|
|
queries: ga.data,
|
|
|
|
|
condition: ga.condition,
|
2021-04-19 17:53:02 +08:00
|
|
|
annotations: listifyLabelsOrAnnotations(rule.annotations),
|
|
|
|
|
labels: listifyLabelsOrAnnotations(rule.labels),
|
2021-04-16 16:08:26 +08:00
|
|
|
folder: { title: namespace, id: -1 },
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error('Unexpected type of rule for grafana rules source');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (isAlertingRulerRule(rule)) {
|
|
|
|
|
const [forTime, forTimeUnit] = rule.for
|
|
|
|
|
? parseInterval(rule.for)
|
|
|
|
|
: [defaultFormValues.forTime, defaultFormValues.forTimeUnit];
|
|
|
|
|
return {
|
|
|
|
|
...defaultFormValues,
|
|
|
|
|
name: rule.alert,
|
|
|
|
|
type: RuleFormType.system,
|
|
|
|
|
dataSourceName: ruleSourceName,
|
2021-04-16 19:57:33 +08:00
|
|
|
namespace,
|
|
|
|
|
group: group.name,
|
2021-04-16 16:08:26 +08:00
|
|
|
expression: rule.expr,
|
|
|
|
|
forTime,
|
|
|
|
|
forTimeUnit,
|
|
|
|
|
annotations: listifyLabelsOrAnnotations(rule.annotations),
|
|
|
|
|
labels: listifyLabelsOrAnnotations(rule.labels),
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
throw new Error('Editing recording rules not supported (yet)');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-04 22:31:25 +08:00
|
|
|
|
|
|
|
|
export const getDefaultQueries = (): GrafanaQuery[] => {
|
|
|
|
|
const dataSource = getDataSourceSrv().getInstanceSettings('default');
|
|
|
|
|
|
|
|
|
|
if (!dataSource) {
|
|
|
|
|
return [getDefaultExpression('A')];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const timeRange = getDefaultTimeRange();
|
|
|
|
|
const relativeTimeRange = rangeUtil.timeRangeToRelative(timeRange);
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
refId: 'A',
|
|
|
|
|
datasourceUid: dataSource.uid,
|
|
|
|
|
queryType: '',
|
|
|
|
|
relativeTimeRange,
|
|
|
|
|
model: {
|
|
|
|
|
refId: 'A',
|
|
|
|
|
hide: false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
getDefaultExpression('B'),
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getDefaultExpression = (refId: string): GrafanaQuery => {
|
|
|
|
|
const model: ExpressionQuery = {
|
|
|
|
|
refId,
|
|
|
|
|
hide: false,
|
|
|
|
|
type: ExpressionQueryType.classic,
|
|
|
|
|
datasource: ExpressionDatasourceID,
|
|
|
|
|
conditions: [
|
|
|
|
|
{
|
|
|
|
|
type: 'query',
|
|
|
|
|
evaluator: {
|
|
|
|
|
params: [3],
|
|
|
|
|
type: EvalFunction.IsAbove,
|
|
|
|
|
},
|
|
|
|
|
operator: {
|
|
|
|
|
type: 'and',
|
|
|
|
|
},
|
|
|
|
|
query: {
|
|
|
|
|
params: ['A'],
|
|
|
|
|
},
|
|
|
|
|
reducer: {
|
|
|
|
|
params: [],
|
|
|
|
|
type: 'last',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
refId,
|
|
|
|
|
datasourceUid: ExpressionDatasourceUID,
|
|
|
|
|
queryType: '',
|
|
|
|
|
model,
|
|
|
|
|
};
|
|
|
|
|
};
|