@@ -450,12 +459,18 @@ function MetadataRow({
data-testid="matching-instances"
>
{numberOfAlertInstances ?? '-'}
-
{pluralize('instance', numberOfAlertInstances)}
+
+
+ instance
+
+
)}
{contactPoint && (
- Delivered to
+
+ Delivered to
+
{customGrouping && (
- Grouped by
+
+ Grouped by
+
{groupBy.join(', ')}
)}
{singleGroup && (
- Single group
+
+ Single group
+
)}
{noGrouping && (
- Not grouping
+
+ Not grouping
+
)}
>
)}
{hasMuteTimings && (
- Muted when
-
+
+ Muted when
+
+
+
+ )}
+ {hasActiveTimings && (
+
+
+ Active when
+
+
)}
{timingOptions && (
@@ -498,7 +529,9 @@ function MetadataRow({
{hasInheritedProperties && (
<>
- Inherited
+
+ Inherited
+
>
@@ -514,7 +547,7 @@ export const useCreateDropdownMenuActions = (
provisioned: boolean,
onEditPolicy: (route: RouteWithID, isDefault?: boolean, readOnly?: boolean) => void,
currentRoute: RouteWithID,
- toggleShowExportDrawer: (nextValue?: any) => void,
+ toggleShowExportDrawer: () => void,
onDeletePolicy: (route: RouteWithID) => void
) => {
const [
@@ -644,10 +677,12 @@ function DefaultPolicyIndicator() {
return (
<>
- Default policy
+ Default policy
- All alert instances will be handled by the default policy if no other matching policies are found.
+
+ All alert instances will be handled by the default policy if no other matching policies are found.
+
>
);
@@ -656,7 +691,7 @@ function DefaultPolicyIndicator() {
function AutogeneratedRootIndicator() {
return (
- Auto-generated policies
+ Auto-generated policies
);
}
@@ -683,7 +718,7 @@ const InheritedProperties: FC<{ properties: InheritableProperties }> = ({ proper
);
-const MuteTimings: FC<{ timings: string[]; alertManagerSourceName: string }> = ({
+const TimeIntervals: FC<{ timings: string[]; alertManagerSourceName: string }> = ({
timings,
alertManagerSourceName,
}) => {
@@ -852,7 +887,9 @@ const ContactPointsHoverDetails: FC = ({
placement="top"
header={
- Contact Point
+
+ Contact Point
+
{contactPoint}
}
@@ -930,7 +967,7 @@ const routePropertyToValue = (
if (isNotGrouping) {
return (
- Not grouping
+ Not grouping
);
}
@@ -938,7 +975,7 @@ const routePropertyToValue = (
if (isSingleGroup) {
return (
- Single group
+ Single group
);
}
diff --git a/public/app/features/alerting/unified/state/actions.ts b/public/app/features/alerting/unified/state/actions.ts
index a1c3ad5afa6..018a3ff68ff 100644
--- a/public/app/features/alerting/unified/state/actions.ts
+++ b/public/app/features/alerting/unified/state/actions.ts
@@ -52,7 +52,7 @@ import { discoverFeatures } from '../api/buildInfo';
import { FetchPromRulesFilter, fetchRules } from '../api/prometheus';
import { FetchRulerRulesFilter, deleteRulerRulesGroup, fetchRulerRules, setRulerRuleGroup } from '../api/ruler';
import { RuleFormValues } from '../types/rule-form';
-import { addDefaultsToAlertmanagerConfig, removeMuteTimingFromRoute } from '../utils/alertmanager';
+import { addDefaultsToAlertmanagerConfig, removeTimeIntervalFromRoute } from '../utils/alertmanager';
import {
GRAFANA_RULES_SOURCE_NAME,
getAllRulesSourceNames,
@@ -590,7 +590,7 @@ export const deleteMuteTimingAction = (alertManagerSourceName: string, muteTimin
alertmanager_config: {
...configWithoutMuteTimings,
route: config.alertmanager_config.route
- ? removeMuteTimingFromRoute(muteTimingName, config.alertmanager_config?.route)
+ ? removeTimeIntervalFromRoute(muteTimingName, config.alertmanager_config?.route)
: undefined,
...time_intervals_without_mute_to_save,
},
diff --git a/public/app/features/alerting/unified/utils/alertmanager.test.ts b/public/app/features/alerting/unified/utils/alertmanager.test.ts
index 3c0293aef94..1607a72ac6b 100644
--- a/public/app/features/alerting/unified/utils/alertmanager.test.ts
+++ b/public/app/features/alerting/unified/utils/alertmanager.test.ts
@@ -1,7 +1,7 @@
import { Matcher, MatcherOperator, Route } from 'app/plugins/datasource/alertmanager/types';
import { Labels } from 'app/types/unified-alerting-dto';
-import { labelsMatchMatchers, removeMuteTimingFromRoute, matchersToString } from './alertmanager';
+import { labelsMatchMatchers, removeTimeIntervalFromRoute, matchersToString } from './alertmanager';
import { parseMatcher, parsePromQLStyleMatcherLooseSafe } from './matchers';
describe('Alertmanager utils', () => {
@@ -104,6 +104,7 @@ describe('Alertmanager utils', () => {
receiver: 'slack',
object_matchers: [['env', MatcherOperator.equal, 'prod']],
mute_time_intervals: ['test2'],
+ active_time_intervals: ['test1'],
},
{
receiver: 'pagerduty',
@@ -113,13 +114,15 @@ describe('Alertmanager utils', () => {
],
};
- it('should remove mute timings from routes', () => {
- expect(removeMuteTimingFromRoute('test1', route)).toEqual({
+ it('should remove time interval from routes', () => {
+ expect(removeTimeIntervalFromRoute('test1', route)).toEqual({
mute_time_intervals: ['test2'],
+ active_time_intervals: [],
object_matchers: [['foo', '=', 'bar']],
receiver: 'gmail',
routes: [
{
+ active_time_intervals: [],
mute_time_intervals: ['test2'],
object_matchers: [['env', '=', 'prod']],
receiver: 'slack',
@@ -127,6 +130,7 @@ describe('Alertmanager utils', () => {
},
{
mute_time_intervals: [],
+ active_time_intervals: [],
object_matchers: [['env', '=', 'eu']],
receiver: 'pagerduty',
routes: undefined,
diff --git a/public/app/features/alerting/unified/utils/alertmanager.ts b/public/app/features/alerting/unified/utils/alertmanager.ts
index 8a73dd2685c..c7e05d82dd0 100644
--- a/public/app/features/alerting/unified/utils/alertmanager.ts
+++ b/public/app/features/alerting/unified/utils/alertmanager.ts
@@ -35,22 +35,22 @@ export function addDefaultsToAlertmanagerConfig(config: AlertManagerCortexConfig
return config;
}
-export function removeMuteTimingFromRoute(muteTiming: string, route: Route): Route {
+export function removeTimeIntervalFromRoute(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)),
+ active_time_intervals: route.active_time_intervals?.filter((muteName) => muteName !== muteTiming) ?? [],
+ routes: route.routes?.map((subRoute) => removeTimeIntervalFromRoute(muteTiming, subRoute)),
};
return newRoute;
}
-export function renameMuteTimings(newMuteTimingName: string, oldMuteTimingName: string, route: Route): Route {
+export function renameTimeInterval(newName: string, oldName: 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)),
+ mute_time_intervals: route.mute_time_intervals?.map((name) => (name === oldName ? newName : name)),
+ active_time_intervals: route.active_time_intervals?.map((name) => (name === oldName ? newName : name)),
+ routes: route.routes?.map((subRoute) => renameTimeInterval(newName, oldName, subRoute)),
};
}
diff --git a/public/app/plugins/datasource/alertmanager/types.ts b/public/app/plugins/datasource/alertmanager/types.ts
index c5bcacd9457..c27d4e53122 100644
--- a/public/app/plugins/datasource/alertmanager/types.ts
+++ b/public/app/plugins/datasource/alertmanager/types.ts
@@ -119,7 +119,10 @@ export type Route = {
group_interval?: string;
repeat_interval?: string;
routes?: Route[];
+ /** Times when the route should be muted. */
mute_time_intervals?: string[];
+ /** Times when the route should be active. This is the opposite of `mute_time_intervals` */
+ active_time_intervals?: string[];
/** only the root policy might have a provenance field defined */
provenance?: string;
};
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index b2112d30d29..f5a96871f45 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -106,6 +106,7 @@
"export-all": "Export all",
"view": "View"
},
+ "contact-point": "Contact Point",
"contact-points": {
"delivery-duration": "Last delivery took <1>1>",
"last-delivery-attempt": "Last delivery attempt",
@@ -136,7 +137,23 @@
"saving": "Saving mute timing"
},
"policies": {
+ "default-policy": {
+ "description": "All alert instances will be handled by the default policy if no other matching policies are found.",
+ "title": "Default policy"
+ },
+ "generated-policies": "Auto-generated policies",
"metadata": {
+ "active-time": "Active when",
+ "delivered-to": "Delivered to",
+ "grouped-by": "Grouped by",
+ "grouping": {
+ "none": "Not grouping",
+ "single-group": "Single group"
+ },
+ "inherited": "Inherited",
+ "mute-time": "Muted when",
+ "n-instances_one": "instance",
+ "n-instances_other": "instances",
"timingOptions": {
"groupInterval": {
"description": "How long to wait before sending a notification about new alerts that are added to a group of alerts for which an initial notification has already been sent.",
@@ -151,7 +168,12 @@
"label": "Repeated every <1>1>"
}
}
- }
+ },
+ "n-more-policies_one": "{{count}} additional policy",
+ "n-more-policies_other": "{{count}} additional policies",
+ "new-child": "New child policy",
+ "new-policy": "Add new policy",
+ "no-matchers": "No matchers"
},
"provisioning": {
"badge-tooltip-provenance": "This resource has been provisioned via {{provenance}} and cannot be edited through the UI",
diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json
index 244caed14ca..729d80a2982 100644
--- a/public/locales/pseudo-LOCALE/grafana.json
+++ b/public/locales/pseudo-LOCALE/grafana.json
@@ -106,6 +106,7 @@
"export-all": "Ēχpőřŧ äľľ",
"view": "Vįęŵ"
},
+ "contact-point": "Cőʼnŧäčŧ Pőįʼnŧ",
"contact-points": {
"delivery-duration": "Ŀäşŧ đęľįvęřy ŧőőĸ <1>1>",
"last-delivery-attempt": "Ŀäşŧ đęľįvęřy äŧŧęmpŧ",
@@ -136,7 +137,23 @@
"saving": "Ŝävįʼnģ mūŧę ŧįmįʼnģ"
},
"policies": {
+ "default-policy": {
+ "description": "Åľľ äľęřŧ įʼnşŧäʼnčęş ŵįľľ þę ĥäʼnđľęđ þy ŧĥę đęƒäūľŧ pőľįčy įƒ ʼnő őŧĥęř mäŧčĥįʼnģ pőľįčįęş äřę ƒőūʼnđ.",
+ "title": "Đęƒäūľŧ pőľįčy"
+ },
+ "generated-policies": "Åūŧő-ģęʼnęřäŧęđ pőľįčįęş",
"metadata": {
+ "active-time": "Åčŧįvę ŵĥęʼn",
+ "delivered-to": "Đęľįvęřęđ ŧő",
+ "grouped-by": "Ğřőūpęđ þy",
+ "grouping": {
+ "none": "Ńőŧ ģřőūpįʼnģ",
+ "single-group": "Ŝįʼnģľę ģřőūp"
+ },
+ "inherited": "Ĩʼnĥęřįŧęđ",
+ "mute-time": "Mūŧęđ ŵĥęʼn",
+ "n-instances_one": "įʼnşŧäʼnčę",
+ "n-instances_other": "įʼnşŧäʼnčęş",
"timingOptions": {
"groupInterval": {
"description": "Ħőŵ ľőʼnģ ŧő ŵäįŧ þęƒőřę şęʼnđįʼnģ ä ʼnőŧįƒįčäŧįőʼn äþőūŧ ʼnęŵ äľęřŧş ŧĥäŧ äřę äđđęđ ŧő ä ģřőūp őƒ äľęřŧş ƒőř ŵĥįčĥ äʼn įʼnįŧįäľ ʼnőŧįƒįčäŧįőʼn ĥäş äľřęäđy þęęʼn şęʼnŧ.",
@@ -151,7 +168,12 @@
"label": "Ŗępęäŧęđ ęvęřy <1>1>"
}
}
- }
+ },
+ "n-more-policies_one": "{{count}} äđđįŧįőʼnäľ pőľįčy",
+ "n-more-policies_other": "{{count}} äđđįŧįőʼnäľ pőľįčįęş",
+ "new-child": "Ńęŵ čĥįľđ pőľįčy",
+ "new-policy": "Åđđ ʼnęŵ pőľįčy",
+ "no-matchers": "Ńő mäŧčĥęřş"
},
"provisioning": {
"badge-tooltip-provenance": "Ŧĥįş řęşőūřčę ĥäş þęęʼn přővįşįőʼnęđ vįä {{provenance}} äʼnđ čäʼnʼnőŧ þę ęđįŧęđ ŧĥřőūģĥ ŧĥę ŮĨ",