mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
Alerting: Fix RegExp matchers in frontend for Silences and other previews. (#51726)
This commit is contained in:
parent
602ee37533
commit
d99a7334d5
@ -56,27 +56,38 @@ describe('Unified Alerting matchers', () => {
|
||||
});
|
||||
|
||||
it('should match for regex', () => {
|
||||
const matchers = [{ name: 'foo', value: 'bar', operator: MatcherOperator.regex }];
|
||||
const matchers = [{ name: 'foo', value: 'b{1}a.*', operator: MatcherOperator.regex }];
|
||||
const alerts = [
|
||||
mockPromAlert({ labels: { foo: 'bbr' } }),
|
||||
mockPromAlert({ labels: { foo: 'aba' } }), // This does not match because the regex is implicitly anchored.
|
||||
mockPromAlert({ labels: { foo: 'ba' } }),
|
||||
mockPromAlert({ labels: { foo: 'bar' } }),
|
||||
mockPromAlert({ labels: { foo: 'baz' } }),
|
||||
mockPromAlert({ labels: { foo: 'bas' } }),
|
||||
];
|
||||
|
||||
const matchedAlerts = findAlertInstancesWithMatchers(alerts, matchers);
|
||||
expect(matchedAlerts).toHaveLength(1);
|
||||
expect(matchedAlerts).toHaveLength(4);
|
||||
expect(matchedAlerts.map((instance) => instance.data.matchedInstance.labels.foo)).toEqual([
|
||||
'ba',
|
||||
'bar',
|
||||
'baz',
|
||||
'bas',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not match regex', () => {
|
||||
const matchers = [{ name: 'foo', value: 'bar', operator: MatcherOperator.notRegex }];
|
||||
const matchers = [{ name: 'foo', value: 'ba{3}', operator: MatcherOperator.notRegex }];
|
||||
const alerts = [
|
||||
mockPromAlert({ labels: { foo: 'bar' } }),
|
||||
mockPromAlert({ labels: { foo: 'baz' } }),
|
||||
mockPromAlert({ labels: { foo: 'baaa' } }),
|
||||
mockPromAlert({ labels: { foo: 'bas' } }),
|
||||
];
|
||||
|
||||
const matchedAlerts = findAlertInstancesWithMatchers(alerts, matchers);
|
||||
expect(matchedAlerts).toHaveLength(2);
|
||||
expect(matchedAlerts).toHaveLength(3);
|
||||
expect(matchedAlerts.map((instance) => instance.data.matchedInstance.labels.foo)).toEqual(['bar', 'baz', 'bas']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -41,29 +41,44 @@ export const findAlertInstancesWithMatchers = (
|
||||
instances: Alert[],
|
||||
matchers: MatcherFieldValue[]
|
||||
): MatchedInstance[] => {
|
||||
const hasMatcher = (instance: Alert, matcher: MatcherFieldValue) => {
|
||||
const anchorRegex = (regexpString: string): RegExp => {
|
||||
// Silence matchers are always fully anchored in the Alertmanager: https://github.com/prometheus/alertmanager/pull/748
|
||||
if (!regexpString.startsWith('^')) {
|
||||
regexpString = '^' + regexpString;
|
||||
}
|
||||
if (!regexpString.endsWith('$')) {
|
||||
regexpString = regexpString + '$';
|
||||
}
|
||||
return new RegExp(regexpString);
|
||||
};
|
||||
|
||||
const matchesInstance = (instance: Alert, matcher: MatcherFieldValue) => {
|
||||
return Object.entries(instance.labels).some(([key, value]) => {
|
||||
if (!matcher.name || !matcher.value) {
|
||||
return false;
|
||||
}
|
||||
if (matcher.operator === MatcherOperator.equal) {
|
||||
return matcher.name === key && matcher.value === value;
|
||||
if (matcher.name !== key) {
|
||||
return false;
|
||||
}
|
||||
if (matcher.operator === MatcherOperator.notEqual) {
|
||||
return matcher.name === key && matcher.value !== value;
|
||||
switch (matcher.operator) {
|
||||
case MatcherOperator.equal:
|
||||
return matcher.value === value;
|
||||
case MatcherOperator.notEqual:
|
||||
return matcher.value !== value;
|
||||
case MatcherOperator.regex:
|
||||
const regex = anchorRegex(matcher.value);
|
||||
return regex.test(value);
|
||||
case MatcherOperator.notRegex:
|
||||
const negregex = anchorRegex(matcher.value);
|
||||
return !negregex.test(value);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (matcher.operator === MatcherOperator.regex) {
|
||||
return matcher.name === key && matcher.value.match(value);
|
||||
}
|
||||
if (matcher.operator === MatcherOperator.notRegex) {
|
||||
return matcher.name === key && !matcher.value.match(value);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
const filteredInstances = instances.filter((instance) => {
|
||||
return matchers.every((matcher) => hasMatcher(instance, matcher));
|
||||
return matchers.every((matcher) => matchesInstance(instance, matcher));
|
||||
});
|
||||
const mappedInstances = filteredInstances.map((instance) => ({
|
||||
id: `${instance.activeAt}-${instance.value}`,
|
||||
|
Loading…
Reference in New Issue
Block a user