The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/features/alerting/unified/utils/notification-policies.ts

85 lines
2.7 KiB

import { AlertmanagerGroup, Route, RouteWithID } from 'app/plugins/datasource/alertmanager/types';
import { Label, normalizeMatchers, labelsMatchObjectMatchers } from './matchers';
// Match does a depth-first left-to-right search through the route tree
// and returns the matching routing nodes.
function findMatchingRoutes(root: Route, labels: Label[]): Route[] {
const matches: Route[] = [];
// If the current node is not a match, return nothing
// const normalizedMatchers = normalizeMatchers(root);
// Normalization should have happened earlier in the code
if (!root.object_matchers || !labelsMatchObjectMatchers(root.object_matchers, labels)) {
return [];
}
// If the current node matches, recurse through child nodes
if (root.routes) {
for (const child of root.routes) {
const matchingChildren = findMatchingRoutes(child, labels);
matches.push(...matchingChildren);
// we have matching children and we don't want to continue, so break here
if (matchingChildren.length && !child.continue) {
break;
}
}
}
// If no child nodes were matches, the current node itself is a match.
if (matches.length === 0) {
matches.push(root);
}
return matches;
}
// This is a performance improvement to normalize matchers only once and use the normalized version later on
export function normalizeRoute(rootRoute: RouteWithID): RouteWithID {
function normalizeRoute(route: RouteWithID) {
route.object_matchers = normalizeMatchers(route);
delete route.matchers;
delete route.match;
delete route.match_re;
route.routes?.forEach(normalizeRoute);
}
const normalizedRootRoute = structuredClone(rootRoute);
normalizeRoute(normalizedRootRoute);
return normalizedRootRoute;
}
/**
* find all of the groups that have instances that match the route, thay way we can find all instances
* (and their grouping) for the given route
*/
function findMatchingAlertGroups(
routeTree: Route,
route: Route,
alertGroups: AlertmanagerGroup[]
): AlertmanagerGroup[] {
const matchingGroups: AlertmanagerGroup[] = [];
return alertGroups.reduce((acc, group) => {
// find matching alerts in the current group
const matchingAlerts = group.alerts.filter((alert) => {
const labels = Object.entries(alert.labels);
return findMatchingRoutes(routeTree, labels).some((matchingRoute) => matchingRoute === route);
});
// if the groups has any alerts left after matching, add it to the results
if (matchingAlerts.length) {
acc.push({
...group,
alerts: matchingAlerts,
});
}
return acc;
}, matchingGroups);
}
export { findMatchingAlertGroups, findMatchingRoutes };