alertDef.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import { isArray, reduce } from 'lodash';
  2. import { QueryPartDef, QueryPart } from 'app/features/alerting/state/query_part';
  3. const alertQueryDef = new QueryPartDef({
  4. type: 'query',
  5. params: [
  6. { name: 'queryRefId', type: 'string', dynamicLookup: true },
  7. {
  8. name: 'from',
  9. type: 'string',
  10. options: ['10s', '1m', '5m', '10m', '15m', '1h', '2h', '6h', '12h', '24h', '48h'],
  11. },
  12. { name: 'to', type: 'string', options: ['now', 'now-1m', 'now-5m', 'now-10m', 'now-1h'] },
  13. ],
  14. defaultParams: ['#A', '15m', 'now', 'avg'],
  15. });
  16. const conditionTypes = [{ text: 'Query', value: 'query' }];
  17. const alertStateSortScore = {
  18. alerting: 1,
  19. firing: 1,
  20. no_data: 2,
  21. pending: 3,
  22. ok: 4,
  23. paused: 5,
  24. inactive: 5,
  25. };
  26. export enum EvalFunction {
  27. 'IsAbove' = 'gt',
  28. 'IsBelow' = 'lt',
  29. 'IsOutsideRange' = 'outside_range',
  30. 'IsWithinRange' = 'within_range',
  31. 'HasNoValue' = 'no_value',
  32. }
  33. const evalFunctions = [
  34. { value: EvalFunction.IsAbove, text: 'IS ABOVE' },
  35. { value: EvalFunction.IsBelow, text: 'IS BELOW' },
  36. { value: EvalFunction.IsOutsideRange, text: 'IS OUTSIDE RANGE' },
  37. { value: EvalFunction.IsWithinRange, text: 'IS WITHIN RANGE' },
  38. { value: EvalFunction.HasNoValue, text: 'HAS NO VALUE' },
  39. ];
  40. const evalOperators = [
  41. { text: 'OR', value: 'or' },
  42. { text: 'AND', value: 'and' },
  43. ];
  44. const reducerTypes = [
  45. { text: 'avg()', value: 'avg' },
  46. { text: 'min()', value: 'min' },
  47. { text: 'max()', value: 'max' },
  48. { text: 'sum()', value: 'sum' },
  49. { text: 'count()', value: 'count' },
  50. { text: 'last()', value: 'last' },
  51. { text: 'median()', value: 'median' },
  52. { text: 'diff()', value: 'diff' },
  53. { text: 'diff_abs()', value: 'diff_abs' },
  54. { text: 'percent_diff()', value: 'percent_diff' },
  55. { text: 'percent_diff_abs()', value: 'percent_diff_abs' },
  56. { text: 'count_non_null()', value: 'count_non_null' },
  57. ];
  58. const noDataModes = [
  59. { text: 'Alerting', value: 'alerting' },
  60. { text: 'No Data', value: 'no_data' },
  61. { text: 'Keep Last State', value: 'keep_state' },
  62. { text: 'Ok', value: 'ok' },
  63. ];
  64. const executionErrorModes = [
  65. { text: 'Alerting', value: 'alerting' },
  66. { text: 'Keep Last State', value: 'keep_state' },
  67. ];
  68. function createReducerPart(model: any) {
  69. const def = new QueryPartDef({ type: model.type, defaultParams: [] });
  70. return new QueryPart(model, def);
  71. }
  72. // state can also contain a "Reason", ie. "Alerting (NoData)" which indicates that the actual state is "Alerting" but
  73. // the reason it is set to "Alerting" is "NoData"; a lack of data points to evaluate.
  74. function normalizeAlertState(state: string) {
  75. return state.toLowerCase().replace(/_/g, '').split(' ')[0];
  76. }
  77. function getStateDisplayModel(state: string) {
  78. const normalizedState = normalizeAlertState(state);
  79. switch (normalizedState) {
  80. case 'normal':
  81. case 'ok': {
  82. return {
  83. text: 'OK',
  84. iconClass: 'heart',
  85. stateClass: 'alert-state-ok',
  86. };
  87. }
  88. case 'alerting': {
  89. return {
  90. text: 'ALERTING',
  91. iconClass: 'heart-break',
  92. stateClass: 'alert-state-critical',
  93. };
  94. }
  95. case 'nodata': {
  96. return {
  97. text: 'NO DATA',
  98. iconClass: 'question-circle',
  99. stateClass: 'alert-state-warning',
  100. };
  101. }
  102. case 'paused': {
  103. return {
  104. text: 'PAUSED',
  105. iconClass: 'pause',
  106. stateClass: 'alert-state-paused',
  107. };
  108. }
  109. case 'pending': {
  110. return {
  111. text: 'PENDING',
  112. iconClass: 'hourglass',
  113. stateClass: 'alert-state-warning',
  114. };
  115. }
  116. case 'firing': {
  117. return {
  118. text: 'FIRING',
  119. iconClass: 'fire',
  120. stateClass: '',
  121. };
  122. }
  123. case 'inactive': {
  124. return {
  125. text: 'INACTIVE',
  126. iconClass: 'check',
  127. stateClass: '',
  128. };
  129. }
  130. case 'error': {
  131. return {
  132. text: 'ERROR',
  133. iconClass: 'heart-break',
  134. stateClass: 'alert-state-critical',
  135. };
  136. }
  137. case 'unknown':
  138. default: {
  139. return {
  140. text: 'UNKNOWN',
  141. iconClass: 'question-circle',
  142. stateClass: '.alert-state-paused',
  143. };
  144. }
  145. }
  146. }
  147. function joinEvalMatches(matches: any, separator: string) {
  148. return reduce(
  149. matches,
  150. (res, ev) => {
  151. if (ev.metric !== undefined && ev.value !== undefined) {
  152. res.push(ev.metric + '=' + ev.value);
  153. }
  154. // For backwards compatibility . Should be be able to remove this after ~2017-06-01
  155. if (ev.Metric !== undefined && ev.Value !== undefined) {
  156. res.push(ev.Metric + '=' + ev.Value);
  157. }
  158. return res;
  159. },
  160. [] as string[]
  161. ).join(separator);
  162. }
  163. function getAlertAnnotationInfo(ah: any) {
  164. // backward compatibility, can be removed in grafana 5.x
  165. // old way stored evalMatches in data property directly,
  166. // new way stores it in evalMatches property on new data object
  167. if (isArray(ah.data)) {
  168. return joinEvalMatches(ah.data, ', ');
  169. } else if (isArray(ah.data.evalMatches)) {
  170. return joinEvalMatches(ah.data.evalMatches, ', ');
  171. }
  172. if (ah.data.error) {
  173. return 'Error: ' + ah.data.error;
  174. }
  175. return '';
  176. }
  177. export default {
  178. alertQueryDef: alertQueryDef,
  179. getStateDisplayModel: getStateDisplayModel,
  180. conditionTypes: conditionTypes,
  181. evalFunctions: evalFunctions,
  182. evalOperators: evalOperators,
  183. noDataModes: noDataModes,
  184. executionErrorModes: executionErrorModes,
  185. reducerTypes: reducerTypes,
  186. createReducerPart: createReducerPart,
  187. getAlertAnnotationInfo: getAlertAnnotationInfo,
  188. alertStateSortScore: alertStateSortScore,
  189. };