usePanelCombinedRules.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { SerializedError } from '@reduxjs/toolkit';
  2. import { useEffect, useMemo } from 'react';
  3. import { useDispatch } from 'react-redux';
  4. import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
  5. import { CombinedRule } from 'app/types/unified-alerting';
  6. import { fetchPromRulesAction, fetchRulerRulesAction } from '../state/actions';
  7. import { Annotation, RULE_LIST_POLL_INTERVAL_MS } from '../utils/constants';
  8. import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';
  9. import { initialAsyncRequestState } from '../utils/redux';
  10. import { useCombinedRuleNamespaces } from './useCombinedRuleNamespaces';
  11. import { useUnifiedAlertingSelector } from './useUnifiedAlertingSelector';
  12. interface Options {
  13. dashboard: DashboardModel;
  14. panel: PanelModel;
  15. poll?: boolean;
  16. }
  17. interface ReturnBag {
  18. errors: SerializedError[];
  19. rules: CombinedRule[];
  20. loading?: boolean;
  21. }
  22. export function usePanelCombinedRules({ dashboard, panel, poll = false }: Options): ReturnBag {
  23. const dispatch = useDispatch();
  24. const promRuleRequest =
  25. useUnifiedAlertingSelector((state) => state.promRules[GRAFANA_RULES_SOURCE_NAME]) ?? initialAsyncRequestState;
  26. const rulerRuleRequest =
  27. useUnifiedAlertingSelector((state) => state.rulerRules[GRAFANA_RULES_SOURCE_NAME]) ?? initialAsyncRequestState;
  28. // fetch rules, then poll every RULE_LIST_POLL_INTERVAL_MS
  29. useEffect(() => {
  30. const fetch = () => {
  31. dispatch(
  32. fetchPromRulesAction({
  33. rulesSourceName: GRAFANA_RULES_SOURCE_NAME,
  34. filter: { dashboardUID: dashboard.uid, panelId: panel.id },
  35. })
  36. );
  37. dispatch(
  38. fetchRulerRulesAction({
  39. rulesSourceName: GRAFANA_RULES_SOURCE_NAME,
  40. filter: { dashboardUID: dashboard.uid, panelId: panel.id },
  41. })
  42. );
  43. };
  44. fetch();
  45. if (poll) {
  46. const interval = setInterval(fetch, RULE_LIST_POLL_INTERVAL_MS);
  47. return () => {
  48. clearInterval(interval);
  49. };
  50. }
  51. return () => {};
  52. }, [dispatch, poll, panel.id, dashboard.uid]);
  53. const loading = promRuleRequest.loading || rulerRuleRequest.loading;
  54. const errors = [promRuleRequest.error, rulerRuleRequest.error].filter(
  55. (err: SerializedError | undefined): err is SerializedError => !!err
  56. );
  57. const combinedNamespaces = useCombinedRuleNamespaces(GRAFANA_RULES_SOURCE_NAME);
  58. // filter out rules that are relevant to this panel
  59. const rules = useMemo(
  60. (): CombinedRule[] =>
  61. combinedNamespaces
  62. .flatMap((ns) => ns.groups)
  63. .flatMap((group) => group.rules)
  64. .filter(
  65. (rule) =>
  66. rule.annotations[Annotation.dashboardUID] === dashboard.uid &&
  67. rule.annotations[Annotation.panelID] === String(panel.id)
  68. ),
  69. [combinedNamespaces, dashboard, panel]
  70. );
  71. return {
  72. rules,
  73. errors,
  74. loading,
  75. };
  76. }