123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- import { isArray, reduce } from 'lodash';
- import { QueryPartDef, QueryPart } from 'app/features/alerting/state/query_part';
- const alertQueryDef = new QueryPartDef({
- type: 'query',
- params: [
- { name: 'queryRefId', type: 'string', dynamicLookup: true },
- {
- name: 'from',
- type: 'string',
- options: ['10s', '1m', '5m', '10m', '15m', '1h', '2h', '6h', '12h', '24h', '48h'],
- },
- { name: 'to', type: 'string', options: ['now', 'now-1m', 'now-5m', 'now-10m', 'now-1h'] },
- ],
- defaultParams: ['#A', '15m', 'now', 'avg'],
- });
- const conditionTypes = [{ text: 'Query', value: 'query' }];
- const alertStateSortScore = {
- alerting: 1,
- firing: 1,
- no_data: 2,
- pending: 3,
- ok: 4,
- paused: 5,
- inactive: 5,
- };
- export enum EvalFunction {
- 'IsAbove' = 'gt',
- 'IsBelow' = 'lt',
- 'IsOutsideRange' = 'outside_range',
- 'IsWithinRange' = 'within_range',
- 'HasNoValue' = 'no_value',
- }
- const evalFunctions = [
- { value: EvalFunction.IsAbove, text: 'IS ABOVE' },
- { value: EvalFunction.IsBelow, text: 'IS BELOW' },
- { value: EvalFunction.IsOutsideRange, text: 'IS OUTSIDE RANGE' },
- { value: EvalFunction.IsWithinRange, text: 'IS WITHIN RANGE' },
- { value: EvalFunction.HasNoValue, text: 'HAS NO VALUE' },
- ];
- const evalOperators = [
- { text: 'OR', value: 'or' },
- { text: 'AND', value: 'and' },
- ];
- const reducerTypes = [
- { text: 'avg()', value: 'avg' },
- { text: 'min()', value: 'min' },
- { text: 'max()', value: 'max' },
- { text: 'sum()', value: 'sum' },
- { text: 'count()', value: 'count' },
- { text: 'last()', value: 'last' },
- { text: 'median()', value: 'median' },
- { text: 'diff()', value: 'diff' },
- { text: 'diff_abs()', value: 'diff_abs' },
- { text: 'percent_diff()', value: 'percent_diff' },
- { text: 'percent_diff_abs()', value: 'percent_diff_abs' },
- { text: 'count_non_null()', value: 'count_non_null' },
- ];
- const noDataModes = [
- { text: 'Alerting', value: 'alerting' },
- { text: 'No Data', value: 'no_data' },
- { text: 'Keep Last State', value: 'keep_state' },
- { text: 'Ok', value: 'ok' },
- ];
- const executionErrorModes = [
- { text: 'Alerting', value: 'alerting' },
- { text: 'Keep Last State', value: 'keep_state' },
- ];
- function createReducerPart(model: any) {
- const def = new QueryPartDef({ type: model.type, defaultParams: [] });
- return new QueryPart(model, def);
- }
- // state can also contain a "Reason", ie. "Alerting (NoData)" which indicates that the actual state is "Alerting" but
- // the reason it is set to "Alerting" is "NoData"; a lack of data points to evaluate.
- function normalizeAlertState(state: string) {
- return state.toLowerCase().replace(/_/g, '').split(' ')[0];
- }
- function getStateDisplayModel(state: string) {
- const normalizedState = normalizeAlertState(state);
- switch (normalizedState) {
- case 'normal':
- case 'ok': {
- return {
- text: 'OK',
- iconClass: 'heart',
- stateClass: 'alert-state-ok',
- };
- }
- case 'alerting': {
- return {
- text: 'ALERTING',
- iconClass: 'heart-break',
- stateClass: 'alert-state-critical',
- };
- }
- case 'nodata': {
- return {
- text: 'NO DATA',
- iconClass: 'question-circle',
- stateClass: 'alert-state-warning',
- };
- }
- case 'paused': {
- return {
- text: 'PAUSED',
- iconClass: 'pause',
- stateClass: 'alert-state-paused',
- };
- }
- case 'pending': {
- return {
- text: 'PENDING',
- iconClass: 'hourglass',
- stateClass: 'alert-state-warning',
- };
- }
- case 'firing': {
- return {
- text: 'FIRING',
- iconClass: 'fire',
- stateClass: '',
- };
- }
- case 'inactive': {
- return {
- text: 'INACTIVE',
- iconClass: 'check',
- stateClass: '',
- };
- }
- case 'error': {
- return {
- text: 'ERROR',
- iconClass: 'heart-break',
- stateClass: 'alert-state-critical',
- };
- }
- case 'unknown':
- default: {
- return {
- text: 'UNKNOWN',
- iconClass: 'question-circle',
- stateClass: '.alert-state-paused',
- };
- }
- }
- }
- function joinEvalMatches(matches: any, separator: string) {
- return reduce(
- matches,
- (res, ev) => {
- if (ev.metric !== undefined && ev.value !== undefined) {
- res.push(ev.metric + '=' + ev.value);
- }
- // For backwards compatibility . Should be be able to remove this after ~2017-06-01
- if (ev.Metric !== undefined && ev.Value !== undefined) {
- res.push(ev.Metric + '=' + ev.Value);
- }
- return res;
- },
- [] as string[]
- ).join(separator);
- }
- function getAlertAnnotationInfo(ah: any) {
- // backward compatibility, can be removed in grafana 5.x
- // old way stored evalMatches in data property directly,
- // new way stores it in evalMatches property on new data object
- if (isArray(ah.data)) {
- return joinEvalMatches(ah.data, ', ');
- } else if (isArray(ah.data.evalMatches)) {
- return joinEvalMatches(ah.data.evalMatches, ', ');
- }
- if (ah.data.error) {
- return 'Error: ' + ah.data.error;
- }
- return '';
- }
- export default {
- alertQueryDef: alertQueryDef,
- getStateDisplayModel: getStateDisplayModel,
- conditionTypes: conditionTypes,
- evalFunctions: evalFunctions,
- evalOperators: evalOperators,
- noDataModes: noDataModes,
- executionErrorModes: executionErrorModes,
- reducerTypes: reducerTypes,
- createReducerPart: createReducerPart,
- getAlertAnnotationInfo: getAlertAnnotationInfo,
- alertStateSortScore: alertStateSortScore,
- };
|