Greg Padgett has uploaded a new change for review. Change subject: tools: notifier: filter messages based on severity ......................................................................
tools: notifier: filter messages based on severity Extend the existing notifier filter mechanism to accept severities in an extra, optional field: PATTERN=include|exclude:event[:severity][(subscriber)] The parser accepts the prior format for backwards compatibility. An inclusion filter will match an event with greater-or-equal severity. Conversely, an exclusion filter will match an event with lesser-or-equal severity. Change-Id: Ia8abc34d56f1ede2fb51daf71dee293d08f198a3 Signed-off-by: Greg Padgett <[email protected]> --- M backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java M backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/dao/EventsManager.java M backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilter.java M backend/manager/tools/src/test/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilterTest.java M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in 5 files changed, 120 insertions(+), 11 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/42/38442/1 diff --git a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java index 6f72d9a..431f76f 100644 --- a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java +++ b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/NotificationService.java @@ -118,6 +118,7 @@ for (String subscriber : dbDownSubscribers.split(",")) { new FirstMatchSimpleFilter.FilterEntry( EventsManager.DATABASE_UNREACHABLE, + null, false, EventNotificationMethod.SMTP.getAsString(), subscriber); diff --git a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/dao/EventsManager.java b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/dao/EventsManager.java index 96de97a..b5bd10a 100644 --- a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/dao/EventsManager.java +++ b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/dao/EventsManager.java @@ -92,6 +92,7 @@ String eventDownName = eventMap.get(eventUpName); eventSubscribers.add( new FirstMatchSimpleFilter.FilterEntry(eventUpName, + null, false, rs.getString("notification_method"), rs.getString("method_address"))); @@ -99,6 +100,7 @@ if (eventDownName != null) { eventSubscribers.add( new FirstMatchSimpleFilter.FilterEntry(eventDownName, + null, false, rs.getString("notification_method"), rs.getString("method_address"))); diff --git a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilter.java b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilter.java index 43f54dc..1ec1cb6 100644 --- a/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilter.java +++ b/backend/manager/tools/src/main/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilter.java @@ -10,6 +10,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; +import org.ovirt.engine.core.common.AuditLogSeverity; import org.ovirt.engine.core.notifier.transport.Transport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,6 +23,10 @@ "((?<include>include)|(?<exclude>exclude))" + ":" + "((?<anymsg>\\*)|(?<message>\\w+))" + + "(?>" + + ":" + + "((?<anyseverity>\\*)|(?<severity>\\w+))" + + ")?" + "(?<recipient>" + "\\(" + "(" + @@ -75,6 +80,10 @@ entry.getEventName().equals(event.getName()) ) && ( + entry.getSeverity() == null || + severityMatches(entry.getSeverity(), event.getSeverity(), entry.isExclude()) + ) && + ( entry.getRecipient() == null || entry.getRecipient().equals(recipient) )) { @@ -92,6 +101,24 @@ } } } + } + + private boolean severityMatches( + String filterSeverityString, + AuditLogSeverity eventSeverity, + boolean isExclusion) { + // Severity matching works in the opposite way for inclusions and exclusions; a filter will + // include events of equal-or-greater severity or exclude events of lesser-or-equal severity. + AuditLogSeverity filterSeverity; + try { + filterSeverity = AuditLogSeverity.valueOf(filterSeverityString); + } catch (IllegalArgumentException e) { + log.warn("Severity value '{}' specified in notifier configuration" + + " does not match any known severities", filterSeverityString); + return false; + } + int cmp = eventSeverity.compareTo(filterSeverity); + return isExclusion ? cmp <= 0 : cmp >= 0; } public static List<FilterEntry> parse(String filters) { @@ -112,6 +139,7 @@ ret.add( new FilterEntry( m.group("anymsg") != null ? null : m.group("message"), + m.group("anyseverity") != null ? null : m.group("severity"), m.group("exclude") != null, m.group("recipient") == null || m.group("anyrecipient") != null ? null : new Recipient( m.group("transport"), @@ -154,7 +182,8 @@ } Recipient that = (Recipient) obj; - return (StringUtils.equals(this.transport, that.transport) && StringUtils.equals(this.name, that.name)); + return (StringUtils.equals(this.transport, that.transport) + && StringUtils.equals(this.name, that.name)); } @Override @@ -177,22 +206,29 @@ private final String eventName; + private final String severity; + private final boolean exclude; private final Recipient recipient; - public FilterEntry(String eventName, boolean exclude, Recipient recipient) { + public FilterEntry(String eventName, String severity, boolean exclude, Recipient recipient) { this.eventName = eventName; + this.severity = severity; this.exclude = exclude; this.recipient = recipient; } - public FilterEntry(String eventName, boolean exclude, String transport, String name) { - this(eventName, exclude, new Recipient(transport, name)); + public FilterEntry(String eventName, String severity, boolean exclude, String transport, String name) { + this(eventName, severity, exclude, new Recipient(transport, name)); } public String getEventName() { return eventName; + } + + public String getSeverity() { + return severity; } public boolean isExclude() { @@ -207,6 +243,7 @@ public String toString() { return "FilterEntry{" + "eventName='" + eventName + '\'' + + ", severity=" + severity + ", exclude=" + exclude + ", recipient=" + recipient + '}'; diff --git a/backend/manager/tools/src/test/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilterTest.java b/backend/manager/tools/src/test/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilterTest.java index 56a322d..871abad 100644 --- a/backend/manager/tools/src/test/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilterTest.java +++ b/backend/manager/tools/src/test/java/org/ovirt/engine/core/notifier/filter/FirstMatchSimpleFilterTest.java @@ -4,6 +4,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.ovirt.engine.core.common.AuditLogSeverity; import org.ovirt.engine.core.notifier.dao.DispatchResult; import org.ovirt.engine.core.notifier.transport.Observer; import org.ovirt.engine.core.notifier.transport.Transport; @@ -21,19 +22,30 @@ T smtp; /* - * This replaces the application message representation, the only request we have is to have getName() to return the - * name based on which we filter. + * This replaces the application message representation; the only requests we have are getName() to return the + * name based on which we filter, and getSeverity() used only in filters where the severity is specified. */ private static class E extends AuditLogEvent { private String e; + private AuditLogSeverity s; public E(String e) { + this(e, null); + } + + public E(String e, AuditLogSeverity s) { this.e = e; + this.s = s; } @Override public String getName() { return e; + } + + @Override + public AuditLogSeverity getSeverity() { + return s; } } @@ -116,7 +128,7 @@ filter.clearFilterEntries(); filter.addFilterEntries( Collections.singletonList( - new FirstMatchSimpleFilter.FilterEntry("message0", false, "smtp", "[email protected]")) + new FirstMatchSimpleFilter.FilterEntry("message0", null, false, "smtp", "[email protected]")) ); filter.processEvent(new E("message0")); filter.processEvent(new E("message1")); @@ -156,13 +168,63 @@ } @Test + public void testSeverity() throws Exception { + String expected1 = "[email protected]"; + String expected2 = "[email protected]"; + filter.clearFilterEntries(); + filter.addFilterEntries( + FirstMatchSimpleFilter.parse( + "include:*:WARNING(smtp:" + expected1 + ") " + + "exclude:*(smtp:" + expected1 + ")" + + "exclude:*:WARNING(smtp:" + expected2 + ") " + + "include:*(smtp:" + expected2 + ")" + )); + filter.processEvent(new E("message1", AuditLogSeverity.NORMAL)); + filter.processEvent(new E("message2", AuditLogSeverity.WARNING)); + filter.processEvent(new E("message3", AuditLogSeverity.ERROR)); + Assert.assertTrue(smtp.getEvents().contains("message2-->" + expected1)); + Assert.assertTrue(smtp.getEvents().contains("message3-->" + expected1)); + Assert.assertTrue(smtp.getEvents().contains("message3-->" + expected2)); + Assert.assertEquals(3, smtp.getEvents().size()); + } + + @Test + public void testSeverityAndEventCombo() throws Exception { + // These combinations aren't useful in the real world, but we want them to work anyway + String expected = "[email protected]"; + filter.clearFilterEntries(); + filter.addFilterEntries( + FirstMatchSimpleFilter.parse( + "include:normal_message:ERROR(smtp:" + expected + ") " + + "include:error_message:NORMAL(smtp:" + expected + ") " + + "exclude:*" + )); + filter.processEvent(new E("normal_message", AuditLogSeverity.NORMAL)); + filter.processEvent(new E("error_message", AuditLogSeverity.ERROR)); + Assert.assertTrue(smtp.getEvents().contains("error_message-->" + expected)); + Assert.assertEquals(1, smtp.getEvents().size()); + } + + @Test + public void testNonExistingSeverity() throws Exception { + // A filter tuple with invalid severity should be ignored + filter.clearFilterEntries(); + filter.addFilterEntries( + FirstMatchSimpleFilter.parse( + "include:message1:_badSeverityTest_(smtp:[email protected]) exclude:*") + ); + filter.processEvent(new E("message1", AuditLogSeverity.ALERT)); + Assert.assertTrue(smtp.getEvents().isEmpty()); + } + + @Test public void testAll() throws Exception { filter.clearFilterEntries(); filter.addFilterEntries(Collections.singletonList( - new FirstMatchSimpleFilter.FilterEntry("kuku", false, "snmp", "pupu")) + new FirstMatchSimpleFilter.FilterEntry("kuku", null, false, "snmp", "pupu")) ); filter.addFilterEntries(Collections.singletonList( - new FirstMatchSimpleFilter.FilterEntry("kuku", false, "smtp", "pupu")) + new FirstMatchSimpleFilter.FilterEntry("kuku", null, false, "smtp", "pupu")) ); filter.addFilterEntries( FirstMatchSimpleFilter.parse( diff --git a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in index d7e13ad..dfca4a3 100644 --- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in +++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.conf.in @@ -119,24 +119,31 @@ # Filter syntax # # FILTER=[PATTERN ...] -# PATTERN=include|exclude:event[(subscriber)] +# PATTERN=include|exclude:event[:severity][(subscriber)] # # Filter logic # -# Each (event E, subscriber S) pair is checked against each +# Each (event E, severity, subscriber S) tuple is checked against each # include/exclude pattern in turn, and the first pattern match is acted upon: # if it is an include pattern then E is sent to S; # if it is an exclude pattern then E is skipped for S; # # The event '*' matches everything. +# A missing severity and the severity '*' matches everything. # A missing '(subscriber)' matches all subscribers and should only be used for excludes. # # Message constants can be found at: # @ENGINE_DOC@/AuditLogMessages.properties # +# Valid severity values in increasing order of severity include: +# 'NORMAL', 'WARNING', 'ERROR', 'ALERT' +# An inclusion filter with a given severity will match all events of greater-or-equal severity; +# an exclusion filter with a given severity will match all events of lesser-or-equal severity. +# # examples: # FILTER="include:VDC_START(smtp:[email protected]) ${FILTER}" # FILTER="exclude:VDC_START include:*(smtp:[email protected]) ${FILTER}" +# FILTER="include:*:ERROR(smtp:[email protected]) ${FILTER}" # # The final filter list contains FILTER as well as 'event_subscriber' table records. # database records are considered first. -- To view, visit https://gerrit.ovirt.org/38442 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia8abc34d56f1ede2fb51daf71dee293d08f198a3 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Greg Padgett <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
