Skip to content

Commit 83cf287

Browse files
authored
fix: resolve incorrect alert rule group matching (#1274)
1 parent 12ff3db commit 83cf287

File tree

2 files changed

+120
-6
lines changed

2 files changed

+120
-6
lines changed

src/data/useGMAlerts.test.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ describe('findRelevantAlertGroups', () => {
2020
name: ALERT_NAME,
2121
};
2222

23+
const RULE_5M: PrometheusAlertingRule = {
24+
...MATCHING_RULE,
25+
name: `${ALERT_NAME} [5m]`,
26+
};
27+
28+
const RULE_10M: PrometheusAlertingRule = {
29+
...MATCHING_RULE,
30+
name: `${ALERT_NAME} [10m]`,
31+
};
32+
33+
const RULE_30M: PrometheusAlertingRule = {
34+
...MATCHING_RULE,
35+
name: `${ALERT_NAME} [30m]`,
36+
};
37+
2338
const NON_MATCHING_RULE: PrometheusAlertingRule = {
2439
...MATCHING_RULE,
2540
name: 'OtherAlert',
@@ -82,4 +97,101 @@ describe('findRelevantAlertGroups', () => {
8297
}),
8398
]);
8499
});
100+
101+
describe('period-based alert matching', () => {
102+
const GROUP_5M: PrometheusAlertsGroup = {
103+
evaulationTime: 1,
104+
file: 'Grafana Synthetic Monitoring',
105+
folderUid: 'grafana-synthetic-monitoring-app',
106+
interval: 300,
107+
lastEvaluation: 'now',
108+
name: 'Failed Checks [5m]',
109+
rules: [RULE_5M],
110+
totals: null,
111+
};
112+
113+
const GROUP_10M: PrometheusAlertsGroup = {
114+
...GROUP_5M,
115+
name: 'Failed Checks [10m]',
116+
rules: [RULE_10M],
117+
};
118+
119+
const GROUP_30M: PrometheusAlertsGroup = {
120+
...GROUP_5M,
121+
name: 'Failed Checks [30m]',
122+
rules: [RULE_30M],
123+
};
124+
125+
test('matches exact period when period is specified', () => {
126+
const alerts: CheckAlertPublished[] = [{
127+
name: ALERT_NAME,
128+
period: '5m',
129+
...baseAlert
130+
}];
131+
132+
// Test the scenario from the escalation: 10m group comes first in array
133+
const groups = [GROUP_10M, GROUP_30M, GROUP_5M];
134+
const result = findRelevantAlertGroups(groups, alerts);
135+
136+
expect(result).toStrictEqual([
137+
{
138+
...GROUP_5M,
139+
rules: [RULE_5M],
140+
},
141+
]);
142+
});
143+
144+
test('matches 10m period correctly even when 5m exists', () => {
145+
const alerts: CheckAlertPublished[] = [{
146+
name: ALERT_NAME,
147+
period: '10m',
148+
...baseAlert
149+
}];
150+
151+
const groups = [GROUP_5M, GROUP_10M, GROUP_30M];
152+
const result = findRelevantAlertGroups(groups, alerts);
153+
154+
expect(result).toStrictEqual([
155+
{
156+
...GROUP_10M,
157+
rules: [RULE_10M],
158+
},
159+
]);
160+
});
161+
162+
test('handles alert without period (backward compatibility)', () => {
163+
const alerts: CheckAlertPublished[] = [{
164+
name: ALERT_NAME,
165+
...baseAlert
166+
}];
167+
168+
const groups = [GROUP];
169+
const result = findRelevantAlertGroups(groups, alerts);
170+
171+
expect(result).toStrictEqual([
172+
{
173+
...GROUP,
174+
rules: [MATCHING_RULE],
175+
},
176+
]);
177+
});
178+
179+
test('creates dummy group when no matching period rule exists', () => {
180+
const alerts: CheckAlertPublished[] = [{
181+
name: ALERT_NAME,
182+
period: '15m', // This period doesn't exist in any group
183+
...baseAlert
184+
}];
185+
186+
const groups = [GROUP_5M, GROUP_10M, GROUP_30M];
187+
const result = findRelevantAlertGroups(groups, alerts);
188+
189+
expect(result).toStrictEqual([
190+
expect.objectContaining({
191+
name: CATEGORY,
192+
rules: [expect.objectContaining({ name: ALERT_NAME })],
193+
}),
194+
]);
195+
});
196+
});
85197
});

src/data/useGMAlerts.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ function queryAlertApi() {
4343

4444
function findGroupWithMatchingRule(
4545
groups: PrometheusAlertsGroup[],
46-
alertName: string
46+
alert: { name: string; period?: string }
4747
): PrometheusAlertsGroup | undefined {
48-
return groups.find((group) => group.rules.some((rule) => rule.name.includes(alertName)));
48+
const fullAlertName = alert.period ? `${alert.name} [${alert.period}]` : alert.name;
49+
return groups.find((group) => group.rules.some((rule) => rule.name === fullAlertName));
4950
}
5051

51-
function extractMatchingRules(group: PrometheusAlertsGroup, alertName: string) {
52-
return group.rules.filter((rule) => rule.name.includes(alertName));
52+
function extractMatchingRules(group: PrometheusAlertsGroup, alert: { name: string; period?: string }) {
53+
const fullAlertName = alert.period ? `${alert.name} [${alert.period}]` : alert.name;
54+
return group.rules.filter((rule) => rule.name === fullAlertName);
5355
}
5456

5557
function constructDummyGroup(alertName: string): PrometheusAlertsGroup {
@@ -92,11 +94,11 @@ export function findRelevantAlertGroups(
9294
const grafanaGroups = groups.filter((group) => group.folderUid === GRAFANA_SM_FOLDER_UID);
9395

9496
return alerts.map((alert) => {
95-
const groupWithRule = findGroupWithMatchingRule(grafanaGroups, alert.name);
97+
const groupWithRule = findGroupWithMatchingRule(grafanaGroups, alert);
9698
if (groupWithRule) {
9799
return {
98100
...groupWithRule,
99-
rules: extractMatchingRules(groupWithRule, alert.name),
101+
rules: extractMatchingRules(groupWithRule, alert),
100102
};
101103
}
102104
return constructDummyGroup(alert.name);

0 commit comments

Comments
 (0)