123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- import { SelectableValue } from '@grafana/data';
- import { FetchError } from '@grafana/runtime';
- import {
- AlertManagerCortexConfig,
- MatcherOperator,
- Route,
- Matcher,
- TimeInterval,
- TimeRange,
- } from 'app/plugins/datasource/alertmanager/types';
- import { Labels } from 'app/types/unified-alerting-dto';
- import { MatcherFieldValue } from '../types/silence-form';
- import { getAllDataSources } from './config';
- import { DataSourceType } from './datasource';
- export function addDefaultsToAlertmanagerConfig(config: AlertManagerCortexConfig): AlertManagerCortexConfig {
- // add default receiver if it does not exist
- if (!config.alertmanager_config.receivers) {
- config.alertmanager_config.receivers = [{ name: 'default ' }];
- }
- // add default route if it does not exists
- if (!config.alertmanager_config.route) {
- config.alertmanager_config.route = {
- receiver: config.alertmanager_config.receivers![0].name,
- };
- }
- if (!config.template_files) {
- config.template_files = {};
- }
- return config;
- }
- export function removeMuteTimingFromRoute(muteTiming: string, route: Route): Route {
- const newRoute: Route = {
- ...route,
- mute_time_intervals: route.mute_time_intervals?.filter((muteName) => muteName !== muteTiming) ?? [],
- routes: route.routes?.map((subRoute) => removeMuteTimingFromRoute(muteTiming, subRoute)),
- };
- return newRoute;
- }
- export function renameMuteTimings(newMuteTimingName: string, oldMuteTimingName: string, route: Route): Route {
- return {
- ...route,
- mute_time_intervals: route.mute_time_intervals?.map((name) =>
- name === oldMuteTimingName ? newMuteTimingName : name
- ),
- routes: route.routes?.map((subRoute) => renameMuteTimings(newMuteTimingName, oldMuteTimingName, subRoute)),
- };
- }
- function isReceiverUsedInRoute(receiver: string, route: Route): boolean {
- return (
- (route.receiver === receiver || route.routes?.some((route) => isReceiverUsedInRoute(receiver, route))) ?? false
- );
- }
- export function isReceiverUsed(receiver: string, config: AlertManagerCortexConfig): boolean {
- return (
- (config.alertmanager_config.route && isReceiverUsedInRoute(receiver, config.alertmanager_config.route)) ?? false
- );
- }
- export function matcherToOperator(matcher: Matcher): MatcherOperator {
- if (matcher.isEqual) {
- if (matcher.isRegex) {
- return MatcherOperator.regex;
- } else {
- return MatcherOperator.equal;
- }
- } else if (matcher.isRegex) {
- return MatcherOperator.notRegex;
- } else {
- return MatcherOperator.notEqual;
- }
- }
- export function matcherOperatorToValue(operator: MatcherOperator) {
- switch (operator) {
- case MatcherOperator.equal:
- return { isEqual: true, isRegex: false };
- case MatcherOperator.notEqual:
- return { isEqual: false, isRegex: false };
- case MatcherOperator.regex:
- return { isEqual: true, isRegex: true };
- case MatcherOperator.notRegex:
- return { isEqual: false, isRegex: true };
- }
- }
- export function matcherToMatcherField(matcher: Matcher): MatcherFieldValue {
- return {
- name: matcher.name,
- value: matcher.value,
- operator: matcherToOperator(matcher),
- };
- }
- export function matcherFieldToMatcher(field: MatcherFieldValue): Matcher {
- return {
- name: field.name,
- value: field.value,
- ...matcherOperatorToValue(field.operator),
- };
- }
- export function matchersToString(matchers: Matcher[]) {
- const matcherFields = matchers.map(matcherToMatcherField);
- const combinedMatchers = matcherFields.reduce((acc, current) => {
- const currentMatcherString = `${current.name}${current.operator}"${current.value}"`;
- return acc ? `${acc},${currentMatcherString}` : currentMatcherString;
- }, '');
- return `{${combinedMatchers}}`;
- }
- export const matcherFieldOptions: SelectableValue[] = [
- { label: MatcherOperator.equal, description: 'Equals', value: MatcherOperator.equal },
- { label: MatcherOperator.notEqual, description: 'Does not equal', value: MatcherOperator.notEqual },
- { label: MatcherOperator.regex, description: 'Matches regex', value: MatcherOperator.regex },
- { label: MatcherOperator.notRegex, description: 'Does not match regex', value: MatcherOperator.notRegex },
- ];
- const matcherOperators = [
- MatcherOperator.regex,
- MatcherOperator.notRegex,
- MatcherOperator.notEqual,
- MatcherOperator.equal,
- ];
- export function parseMatcher(matcher: string): Matcher {
- const trimmed = matcher.trim();
- if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
- throw new Error(`PromQL matchers not supported yet, sorry! PromQL matcher found: ${trimmed}`);
- }
- const operatorsFound = matcherOperators
- .map((op): [MatcherOperator, number] => [op, trimmed.indexOf(op)])
- .filter(([_, idx]) => idx > -1)
- .sort((a, b) => a[1] - b[1]);
- if (!operatorsFound.length) {
- throw new Error(`Invalid matcher: ${trimmed}`);
- }
- const [operator, idx] = operatorsFound[0];
- const name = trimmed.slice(0, idx).trim();
- const value = trimmed.slice(idx + operator.length).trim();
- if (!name) {
- throw new Error(`Invalid matcher: ${trimmed}`);
- }
- return {
- name,
- value,
- isRegex: operator === MatcherOperator.regex || operator === MatcherOperator.notRegex,
- isEqual: operator === MatcherOperator.equal || operator === MatcherOperator.regex,
- };
- }
- export function parseMatchers(matcherQueryString: string): Matcher[] {
- const matcherRegExp = /\b([\w.-]+)(=~|!=|!~|=(?="?\w))"?([^"\n,]*)"?/g;
- const matchers: Matcher[] = [];
- matcherQueryString.replace(matcherRegExp, (_, key, operator, value) => {
- const isEqual = operator === MatcherOperator.equal || operator === MatcherOperator.regex;
- const isRegex = operator === MatcherOperator.regex || operator === MatcherOperator.notRegex;
- matchers.push({
- name: key,
- value,
- isEqual,
- isRegex,
- });
- return '';
- });
- return matchers;
- }
- export function labelsMatchMatchers(labels: Labels, matchers: Matcher[]): boolean {
- return matchers.every(({ name, value, isRegex, isEqual }) => {
- return Object.entries(labels).some(([labelKey, labelValue]) => {
- const nameMatches = name === labelKey;
- let valueMatches;
- if (isEqual && !isRegex) {
- valueMatches = value === labelValue;
- }
- if (!isEqual && !isRegex) {
- valueMatches = value !== labelValue;
- }
- if (isEqual && isRegex) {
- valueMatches = new RegExp(value).test(labelValue);
- }
- if (!isEqual && isRegex) {
- valueMatches = !new RegExp(value).test(labelValue);
- }
- return nameMatches && valueMatches;
- });
- });
- }
- export function getAllAlertmanagerDataSources() {
- return getAllDataSources().filter((ds) => ds.type === DataSourceType.Alertmanager);
- }
- export function getAlertmanagerByUid(uid?: string) {
- return getAllAlertmanagerDataSources().find((ds) => uid === ds.uid);
- }
- export function timeIntervalToString(timeInterval: TimeInterval): string {
- const { times, weekdays, days_of_month, months, years } = timeInterval;
- const timeString = getTimeString(times);
- const weekdayString = getWeekdayString(weekdays);
- const daysString = getDaysOfMonthString(days_of_month);
- const monthsString = getMonthsString(months);
- const yearsString = getYearsString(years);
- return [timeString, weekdayString, daysString, monthsString, yearsString].join(', ');
- }
- export function getTimeString(times?: TimeRange[]): string {
- return (
- 'Times: ' +
- (times ? times?.map(({ start_time, end_time }) => `${start_time} - ${end_time} UTC`).join(' and ') : 'All')
- );
- }
- export function getWeekdayString(weekdays?: string[]): string {
- return (
- 'Weekdays: ' +
- (weekdays
- ?.map((day) => {
- if (day.includes(':')) {
- return day
- .split(':')
- .map((d) => {
- const abbreviated = d.slice(0, 3);
- return abbreviated[0].toLocaleUpperCase() + abbreviated.slice(1);
- })
- .join('-');
- } else {
- const abbreviated = day.slice(0, 3);
- return abbreviated[0].toLocaleUpperCase() + abbreviated.slice(1);
- }
- })
- .join(', ') ?? 'All')
- );
- }
- export function getDaysOfMonthString(daysOfMonth?: string[]): string {
- return 'Days of the month: ' + (daysOfMonth?.join(', ') ?? 'All');
- }
- export function getMonthsString(months?: string[]): string {
- return 'Months: ' + (months?.join(', ') ?? 'All');
- }
- export function getYearsString(years?: string[]): string {
- return 'Years: ' + (years?.join(', ') ?? 'All');
- }
- export function isFetchError(e: unknown): e is FetchError {
- return typeof e === 'object' && e !== null && 'status' in e && 'data' in e;
- }
|