Alerting: fix alert groups grouping (#45012)

* fix multiple non-grouped groupings

* drop duplicate alerts

* add test for multiple groups without labels

Co-authored-by: gillesdemey <gilles.de.mey@gmail.com>
This commit is contained in:
Nathan Rodman 2022-02-28 09:50:17 -08:00 committed by GitHub
parent 4e19d7df63
commit e814e7364b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 4 deletions

View File

@ -147,4 +147,19 @@ describe('AlertGroups', () => {
expect(groups[0]).toHaveTextContent('No grouping'); expect(groups[0]).toHaveTextContent('No grouping');
expect(groups[1]).toHaveTextContent('uniqueLabel=true'); expect(groups[1]).toHaveTextContent('uniqueLabel=true');
}); });
it('should combine multiple ungrouped groups', async () => {
mocks.api.fetchAlertGroups.mockImplementation(() => {
const groups = [
mockAlertGroup({ labels: {} }),
mockAlertGroup({ labels: {}, alerts: [mockAlertmanagerAlert({ labels: { foo: 'bar' } })] }),
];
return Promise.resolve(groups);
});
renderAmNotifications();
await waitFor(() => expect(mocks.api.fetchAlertGroups).toHaveBeenCalled());
const groups = ui.group.getAll();
expect(groups).toHaveLength(1);
});
}); });

View File

@ -10,7 +10,7 @@ export const useFilteredAmGroups = (groups: AlertmanagerGroup[]) => {
const matchers = parseMatchers(filters.queryString || ''); const matchers = parseMatchers(filters.queryString || '');
return useMemo(() => { return useMemo(() => {
return groups.reduce((filteredGroup, group) => { return groups.reduce((filteredGroup: AlertmanagerGroup[], group) => {
const alerts = group.alerts.filter(({ labels, status }) => { const alerts = group.alerts.filter(({ labels, status }) => {
const labelsMatch = labelsMatchMatchers(labels, matchers); const labelsMatch = labelsMatchMatchers(labels, matchers);
const filtersMatch = filters.alertState ? status.state === filters.alertState : true; const filtersMatch = filters.alertState ? status.state === filters.alertState : true;
@ -25,6 +25,6 @@ export const useFilteredAmGroups = (groups: AlertmanagerGroup[]) => {
} }
} }
return filteredGroup; return filteredGroup;
}, [] as AlertmanagerGroup[]); }, []);
}, [groups, filters, matchers]); }, [groups, filters, matchers]);
}; };

View File

@ -1,11 +1,30 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types'; import { AlertmanagerGroup } from 'app/plugins/datasource/alertmanager/types';
import { Labels } from '@grafana/data'; import { Labels } from '@grafana/data';
import { uniqBy } from 'lodash';
export const useGroupedAlerts = (groups: AlertmanagerGroup[], groupBy: string[]) => { export const useGroupedAlerts = (groups: AlertmanagerGroup[], groupBy: string[]): AlertmanagerGroup[] => {
return useMemo(() => { return useMemo(() => {
if (groupBy.length === 0) { if (groupBy.length === 0) {
return groups; const emptyGroupings = groups.filter((group) => Object.keys(group.labels).length === 0);
if (emptyGroupings.length > 1) {
// Merges multiple ungrouped grouping
return groups.reduce((combinedGroups, group) => {
if (Object.keys(group.labels).length === 0) {
const noGroupingGroup = combinedGroups.find(({ labels }) => Object.keys(labels));
if (!noGroupingGroup) {
combinedGroups.push({ alerts: group.alerts, labels: {}, receiver: { name: 'NONE' } });
} else {
noGroupingGroup.alerts = uniqBy([...noGroupingGroup.alerts, ...group.alerts], 'labels');
}
} else {
combinedGroups.push(group);
}
return combinedGroups;
}, [] as AlertmanagerGroup[]);
} else {
return groups;
}
} }
const alerts = groups.flatMap(({ alerts }) => alerts); const alerts = groups.flatMap(({ alerts }) => alerts);
return alerts.reduce((groupings, alert) => { return alerts.reduce((groupings, alert) => {