AlertGroups.tsx 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { css } from '@emotion/css';
  2. import React, { useEffect } from 'react';
  3. import { useDispatch } from 'react-redux';
  4. import { GrafanaTheme2 } from '@grafana/data';
  5. import { Alert, LoadingPlaceholder, useStyles2 } from '@grafana/ui';
  6. import { useQueryParams } from 'app/core/hooks/useQueryParams';
  7. import { AlertingPageWrapper } from './components/AlertingPageWrapper';
  8. import { NoAlertManagerWarning } from './components/NoAlertManagerWarning';
  9. import { AlertGroup } from './components/alert-groups/AlertGroup';
  10. import { AlertGroupFilter } from './components/alert-groups/AlertGroupFilter';
  11. import { useAlertManagerSourceName } from './hooks/useAlertManagerSourceName';
  12. import { useAlertManagersByPermission } from './hooks/useAlertManagerSources';
  13. import { useFilteredAmGroups } from './hooks/useFilteredAmGroups';
  14. import { useGroupedAlerts } from './hooks/useGroupedAlerts';
  15. import { useUnifiedAlertingSelector } from './hooks/useUnifiedAlertingSelector';
  16. import { fetchAlertGroupsAction } from './state/actions';
  17. import { NOTIFICATIONS_POLL_INTERVAL_MS } from './utils/constants';
  18. import { getFiltersFromUrlParams } from './utils/misc';
  19. import { initialAsyncRequestState } from './utils/redux';
  20. const AlertGroups = () => {
  21. const alertManagers = useAlertManagersByPermission('instance');
  22. const [alertManagerSourceName] = useAlertManagerSourceName(alertManagers);
  23. const dispatch = useDispatch();
  24. const [queryParams] = useQueryParams();
  25. const { groupBy = [] } = getFiltersFromUrlParams(queryParams);
  26. const styles = useStyles2(getStyles);
  27. const alertGroups = useUnifiedAlertingSelector((state) => state.amAlertGroups);
  28. const {
  29. loading,
  30. error,
  31. result: results = [],
  32. } = alertGroups[alertManagerSourceName || ''] ?? initialAsyncRequestState;
  33. const groupedAlerts = useGroupedAlerts(results, groupBy);
  34. const filteredAlertGroups = useFilteredAmGroups(groupedAlerts);
  35. useEffect(() => {
  36. function fetchNotifications() {
  37. if (alertManagerSourceName) {
  38. dispatch(fetchAlertGroupsAction(alertManagerSourceName));
  39. }
  40. }
  41. fetchNotifications();
  42. const interval = setInterval(fetchNotifications, NOTIFICATIONS_POLL_INTERVAL_MS);
  43. return () => {
  44. clearInterval(interval);
  45. };
  46. }, [dispatch, alertManagerSourceName]);
  47. if (!alertManagerSourceName) {
  48. return (
  49. <AlertingPageWrapper pageId="groups">
  50. <NoAlertManagerWarning availableAlertManagers={alertManagers} />
  51. </AlertingPageWrapper>
  52. );
  53. }
  54. return (
  55. <AlertingPageWrapper pageId="groups">
  56. <AlertGroupFilter groups={results} />
  57. {loading && <LoadingPlaceholder text="Loading notifications" />}
  58. {error && !loading && (
  59. <Alert title={'Error loading notifications'} severity={'error'}>
  60. {error.message || 'Unknown error'}
  61. </Alert>
  62. )}
  63. {results &&
  64. filteredAlertGroups.map((group, index) => {
  65. return (
  66. <React.Fragment key={`${JSON.stringify(group.labels)}-group-${index}`}>
  67. {((index === 1 && Object.keys(filteredAlertGroups[0].labels).length === 0) ||
  68. (index === 0 && Object.keys(group.labels).length > 0)) && (
  69. <p className={styles.groupingBanner}>Grouped by: {Object.keys(group.labels).join(', ')}</p>
  70. )}
  71. <AlertGroup alertManagerSourceName={alertManagerSourceName || ''} group={group} />
  72. </React.Fragment>
  73. );
  74. })}
  75. {results && !filteredAlertGroups.length && <p>No results.</p>}
  76. </AlertingPageWrapper>
  77. );
  78. };
  79. const getStyles = (theme: GrafanaTheme2) => ({
  80. groupingBanner: css`
  81. margin: ${theme.spacing(2, 0)};
  82. `,
  83. });
  84. export default AlertGroups;