grafana/public/app/features/alerting/unified/routeGroupsMatcher.ts
Konrad Lalik fbdd27c237
Alerting: Add support for UTF-8 characters in notification policies and silences (#81455)
* Add label matcher validation to support UTF-8 characters

* Add double quotes wrapping and escaping on displating matcher form inputs

* Apply matchers encoding and decoding on the RTKQ layer

* Fix unescaping order

* Revert "Apply matchers encoding and decoding on the RTKQ layer"

This reverts commit 4d963c43b5.

* Add matchers formatter

* Fix code organization to prevent breaking worker

* Add matcher formatter to Policy and Modal components

* Unquote matchers when finding matching policy instances

* Add tests for quoting and unquoting

* Rename cloud matcher formatter

* Revert unintended change

* Allow empty matcher values

* fix test
2024-02-09 15:46:28 +01:00

68 lines
2.0 KiB
TypeScript

import { AlertmanagerGroup, RouteWithID } from '../../../plugins/datasource/alertmanager/types';
import { Labels } from '../../../types/unified-alerting-dto';
import {
AlertInstanceMatch,
findMatchingAlertGroups,
findMatchingRoutes,
normalizeRoute,
unquoteRouteMatchers,
} from './utils/notification-policies';
export interface MatchOptions {
unquoteMatchers?: boolean;
}
export const routeGroupsMatcher = {
getRouteGroupsMap(
rootRoute: RouteWithID,
groups: AlertmanagerGroup[],
options?: MatchOptions
): Map<string, AlertmanagerGroup[]> {
const normalizedRootRoute = getNormalizedRoute(rootRoute, options);
function addRouteGroups(route: RouteWithID, acc: Map<string, AlertmanagerGroup[]>) {
const routeGroups = findMatchingAlertGroups(normalizedRootRoute, route, groups);
acc.set(route.id, routeGroups);
route.routes?.forEach((r) => addRouteGroups(r, acc));
}
const routeGroupsMap = new Map<string, AlertmanagerGroup[]>();
addRouteGroups(normalizedRootRoute, routeGroupsMap);
return routeGroupsMap;
},
matchInstancesToRoute(
routeTree: RouteWithID,
instancesToMatch: Labels[],
options?: MatchOptions
): Map<string, AlertInstanceMatch[]> {
const result = new Map<string, AlertInstanceMatch[]>();
const normalizedRootRoute = getNormalizedRoute(routeTree, options);
instancesToMatch.forEach((instance) => {
const matchingRoutes = findMatchingRoutes(normalizedRootRoute, Object.entries(instance));
matchingRoutes.forEach(({ route, labelsMatch }) => {
const currentRoute = result.get(route.id);
if (currentRoute) {
currentRoute.push({ instance, labelsMatch });
} else {
result.set(route.id, [{ instance, labelsMatch }]);
}
});
});
return result;
},
};
function getNormalizedRoute(route: RouteWithID, options?: MatchOptions): RouteWithID {
return options?.unquoteMatchers ? unquoteRouteMatchers(normalizeRoute(route)) : normalizeRoute(route);
}
export type RouteGroupsMatcher = typeof routeGroupsMatcher;