From 22d750f2d750f85766932093fac3c21ed4a22249 Mon Sep 17 00:00:00 2001 From: Alena Varkockova Date: Sun, 31 Jul 2016 10:25:20 +0200 Subject: [PATCH] HTTP broadcasting of all events in seyren --- .../com/seyren/core/domain/Subscription.java | 4 + .../seyren/core/domain/SubscriptionType.java | 2 +- .../notification/HttpNotificationService.java | 2 +- .../core/service/schedule/CheckRunner.java | 11 ++- .../seyren/core/domain/SubscriptionTest.java | 27 ++++++ .../HttpNotificationServiceTest.java | 3 +- .../service/schedule/CheckRunnerTest.java | 93 ++++++++++++++++++- 7 files changed, 132 insertions(+), 10 deletions(-) diff --git a/seyren-core/src/main/java/com/seyren/core/domain/Subscription.java b/seyren-core/src/main/java/com/seyren/core/domain/Subscription.java index 6b505ce4..c20271be 100644 --- a/seyren-core/src/main/java/com/seyren/core/domain/Subscription.java +++ b/seyren-core/src/main/java/com/seyren/core/domain/Subscription.java @@ -251,6 +251,10 @@ public Subscription withEnabled(boolean enabled) { setEnabled(enabled); return this; } + + public boolean shouldBroadcastAllAlerts() { + return isEnabled() && type == SubscriptionType.HTTPBROADCAST; + } public boolean shouldNotify(DateTime time, AlertType alertType) { if (!isEnabled()) { diff --git a/seyren-core/src/main/java/com/seyren/core/domain/SubscriptionType.java b/seyren-core/src/main/java/com/seyren/core/domain/SubscriptionType.java index b237d633..a260eba0 100644 --- a/seyren-core/src/main/java/com/seyren/core/domain/SubscriptionType.java +++ b/seyren-core/src/main/java/com/seyren/core/domain/SubscriptionType.java @@ -16,5 +16,5 @@ public enum SubscriptionType { EMAIL, PAGERDUTY, HIPCHAT, HUBOT, FLOWDOCK, HTTP, IRCCAT, PUSHOVER, LOGGER, SNMP, SLACK, TWILIO, VICTOROPS, - OPSGENIE + OPSGENIE, HTTPBROADCAST } diff --git a/seyren-core/src/main/java/com/seyren/core/service/notification/HttpNotificationService.java b/seyren-core/src/main/java/com/seyren/core/service/notification/HttpNotificationService.java index 4e6fb040..452d0e80 100644 --- a/seyren-core/src/main/java/com/seyren/core/service/notification/HttpNotificationService.java +++ b/seyren-core/src/main/java/com/seyren/core/service/notification/HttpNotificationService.java @@ -101,7 +101,7 @@ public void sendNotification(Check check, Subscription subscription, List @Override public boolean canHandle(SubscriptionType subscriptionType) { - return subscriptionType == SubscriptionType.HTTP; + return subscriptionType == SubscriptionType.HTTP || subscriptionType == SubscriptionType.HTTPBROADCAST; } private String getPreviewImage(Check check) diff --git a/seyren-core/src/main/java/com/seyren/core/service/schedule/CheckRunner.java b/seyren-core/src/main/java/com/seyren/core/service/schedule/CheckRunner.java index 40807eff..228c981e 100644 --- a/seyren-core/src/main/java/com/seyren/core/service/schedule/CheckRunner.java +++ b/seyren-core/src/main/java/com/seyren/core/service/schedule/CheckRunner.java @@ -77,6 +77,7 @@ public final void run() { } List interestingAlerts = new ArrayList(); + List allAlerts = new ArrayList(); for (Entry> entry : targetValues.entrySet()) { @@ -107,13 +108,14 @@ public final void run() { if (currentState.isWorseThan(worstState)) { worstState = currentState; } + + Alert alert = createAlert(target, currentValue, warn, error, lastState, currentState, now); + allAlerts.add(alert); if (isStillOk(lastState, currentState)) { continue; } - Alert alert = createAlert(target, currentValue, warn, error, lastState, currentState, now); - alertsStore.createAlert(check.getId(), alert); // Only notify if the alert has changed state @@ -127,19 +129,20 @@ public final void run() { Check updatedCheck = checksStore.updateStateAndLastCheck(check.getId(), worstState, DateTime.now()); + if (interestingAlerts.isEmpty()) { return; } for (Subscription subscription : updatedCheck.getSubscriptions()) { - if (!subscription.shouldNotify(now, worstState)) { + if (!subscription.shouldNotify(now, worstState) && !subscription.shouldBroadcastAllAlerts()) { continue; } for (NotificationService notificationService : notificationServices) { if (notificationService.canHandle(subscription.getType())) { try { - notificationService.sendNotification(updatedCheck, subscription, interestingAlerts); + notificationService.sendNotification(updatedCheck, subscription, subscription.shouldBroadcastAllAlerts() ? allAlerts : interestingAlerts); } catch (Exception e) { LOGGER.warn("Notifying {} by {} failed.", subscription.getTarget(), subscription.getType(), e); } diff --git a/seyren-core/src/test/java/com/seyren/core/domain/SubscriptionTest.java b/seyren-core/src/test/java/com/seyren/core/domain/SubscriptionTest.java index 1bb207df..2d9fde0f 100644 --- a/seyren-core/src/test/java/com/seyren/core/domain/SubscriptionTest.java +++ b/seyren-core/src/test/java/com/seyren/core/domain/SubscriptionTest.java @@ -129,6 +129,33 @@ public void subscriptionShouldNotifyOfOkWhenNotIgnoringOk() { .withIgnoreOk(false); assertThat(sub.shouldNotify(dateTime("1015"), AlertType.OK), is(true)); } + + @Test + public void subscriptionShouldBroadcastWhenCorrectType() { + Subscription sub = new Subscription() + .withEnabled(true) + .withType(SubscriptionType.HTTPBROADCAST); + + assertThat(sub.shouldBroadcastAllAlerts(), is(true)); + } + + @Test + public void subscriptionShouldNotBroadcastWhenIncorrectType() { + Subscription sub = new Subscription() + .withEnabled(true) + .withType(SubscriptionType.EMAIL); + + assertThat(sub.shouldBroadcastAllAlerts(), is(false)); + } + + @Test + public void subscriptionShouldNotBroadcastWhenDisabled() { + Subscription sub = new Subscription() + .withEnabled(false) + .withType(SubscriptionType.HTTPBROADCAST); + + assertThat(sub.shouldBroadcastAllAlerts(), is(false)); + } private DateTime dateTime(String time) { return new DateTime(2012, 01, 01, Integer.valueOf(time.substring(0, 2)), Integer.valueOf(time.substring(2))); diff --git a/seyren-core/src/test/java/com/seyren/core/service/notification/HttpNotificationServiceTest.java b/seyren-core/src/test/java/com/seyren/core/service/notification/HttpNotificationServiceTest.java index 6183901e..edbb32ba 100644 --- a/seyren-core/src/test/java/com/seyren/core/service/notification/HttpNotificationServiceTest.java +++ b/seyren-core/src/test/java/com/seyren/core/service/notification/HttpNotificationServiceTest.java @@ -57,8 +57,9 @@ public void before() { @Test public void notifcationServiceCanOnlyHandleHttpSubscription() { assertThat(service.canHandle(SubscriptionType.HTTP), is(true)); + assertThat(service.canHandle(SubscriptionType.HTTPBROADCAST), is(true)); for (SubscriptionType type : SubscriptionType.values()) { - if (type == SubscriptionType.HTTP) { + if (type == SubscriptionType.HTTP || type == SubscriptionType.HTTPBROADCAST) { continue; } assertThat(service.canHandle(type), is(false)); diff --git a/seyren-core/src/test/java/com/seyren/core/service/schedule/CheckRunnerTest.java b/seyren-core/src/test/java/com/seyren/core/service/schedule/CheckRunnerTest.java index 88405ba7..7c6a1bad 100644 --- a/seyren-core/src/test/java/com/seyren/core/service/schedule/CheckRunnerTest.java +++ b/seyren-core/src/test/java/com/seyren/core/service/schedule/CheckRunnerTest.java @@ -26,6 +26,7 @@ import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentMatcher; import org.mockito.Mockito; import com.google.common.base.Optional; @@ -325,10 +326,96 @@ public void exceptionWhileSendingNotificationIsHandled() throws Exception { when(mockSubscription.shouldNotify(any(DateTime.class), eq(AlertType.ERROR))).thenReturn(true); when(mockNotificationService.canHandle(SubscriptionType.EMAIL)).thenReturn(true); Mockito.doThrow(new NotificationFailedException("Boom!")).when(mockNotificationService).sendNotification(eq(mockCheck), eq(mockSubscription), any(List.class)); - + checkRunner.run(); - + verify(mockAlertsStore).createAlert(eq("id"), any(Alert.class)); } - + + @SuppressWarnings("unchecked") + @Test + public void broadcastAllAlertsWhenApplicable() throws Exception { + Subscription mockSubscription = mock(Subscription.class); + when(mockSubscription.getType()).thenReturn(SubscriptionType.HTTPBROADCAST); + + BigDecimal value = BigDecimal.ONE; + BigDecimal value2 = BigDecimal.valueOf(2); + BigDecimal warn = BigDecimal.valueOf(4); + BigDecimal error = BigDecimal.valueOf(5); + + when(mockCheck.getId()).thenReturn("id"); + when(mockCheck.isEnabled()).thenReturn(true); + when(mockCheck.getWarn()).thenReturn(warn); + when(mockCheck.getError()).thenReturn(error); + when(mockCheck.getSubscriptions()).thenReturn(Arrays.asList(mockSubscription)); + + Map> targetValues = new HashMap>(); + targetValues.put("target", Optional.of(value)); + targetValues.put("target2", Optional.of(value2)); + when(mockTargetChecker.check(mockCheck)).thenReturn(targetValues); + when(mockAlertsStore.getLastAlertForTargetOfCheck("target", "id")).thenReturn(new Alert().withToType(AlertType.WARN)); + when(mockAlertsStore.getLastAlertForTargetOfCheck("target2", "id")).thenReturn(new Alert().withToType(AlertType.OK)); + when(mockValueChecker.checkValue(value, warn, error)).thenReturn(AlertType.ERROR); + when(mockValueChecker.checkValue(value2, warn, error)).thenReturn(AlertType.OK); + + Alert alert = new Alert(); + + when(mockAlertsStore.createAlert(eq("id"), any(Alert.class))).thenReturn(alert); + when(mockChecksStore.updateStateAndLastCheck(eq("id"), eq(AlertType.ERROR), any(DateTime.class))).thenReturn(mockCheck); + when(mockSubscription.shouldBroadcastAllAlerts()).thenReturn(true); + when(mockNotificationService.canHandle(SubscriptionType.HTTPBROADCAST)).thenReturn(true); + + checkRunner.run(); + + verify(mockNotificationService, times(1)).sendNotification(eq(mockCheck), eq(mockSubscription), argThat(new IsListOfNElements(2))); + } + + @Test + public void notBroadcastAllAlertsWhenNotApplicable() throws Exception { + Subscription mockSubscription = mock(Subscription.class); + when(mockSubscription.getType()).thenReturn(SubscriptionType.EMAIL); + + BigDecimal value = BigDecimal.ONE; + BigDecimal value2 = BigDecimal.valueOf(2); + BigDecimal warn = BigDecimal.valueOf(4); + BigDecimal error = BigDecimal.valueOf(5); + + when(mockCheck.getId()).thenReturn("id"); + when(mockCheck.isEnabled()).thenReturn(true); + when(mockCheck.getWarn()).thenReturn(warn); + when(mockCheck.getError()).thenReturn(error); + when(mockCheck.getSubscriptions()).thenReturn(Arrays.asList(mockSubscription)); + + Map> targetValues = new HashMap>(); + targetValues.put("target", Optional.of(value)); + targetValues.put("target2", Optional.of(value2)); + when(mockTargetChecker.check(mockCheck)).thenReturn(targetValues); + when(mockAlertsStore.getLastAlertForTargetOfCheck("target", "id")).thenReturn(new Alert().withToType(AlertType.WARN)); + when(mockAlertsStore.getLastAlertForTargetOfCheck("target2", "id")).thenReturn(new Alert().withToType(AlertType.OK)); + when(mockValueChecker.checkValue(value, warn, error)).thenReturn(AlertType.ERROR); + when(mockValueChecker.checkValue(value2, warn, error)).thenReturn(AlertType.OK); + + Alert alert = new Alert(); + + when(mockAlertsStore.createAlert(eq("id"), any(Alert.class))).thenReturn(alert); + when(mockChecksStore.updateStateAndLastCheck(eq("id"), eq(AlertType.ERROR), any(DateTime.class))).thenReturn(mockCheck); + when(mockSubscription.shouldNotify(any(DateTime.class), eq(AlertType.ERROR))).thenReturn(true); + when(mockSubscription.shouldNotify(any(DateTime.class), eq(AlertType.OK))).thenReturn(false); + when(mockNotificationService.canHandle(SubscriptionType.EMAIL)).thenReturn(true); + + checkRunner.run(); + + verify(mockNotificationService, times(1)).sendNotification(eq(mockCheck), eq(mockSubscription), argThat(new IsListOfNElements(1))); + } + + class IsListOfNElements extends ArgumentMatcher { + private int n; + + public IsListOfNElements(int n) { + this.n = n; + } + public boolean matches(Object list) { + return ((List) list).size() == n; + } + } }