/** * Returns the name of the given {@link AlertingState}. If the name is empty or null a default * name is returned. * * @param alertingState * the {@link AlertingState} * @return the name of the given {@link AlertingState} */ private String getAlertingName(AlertingState alertingState) { String alertingDefinitionName = alertingState.getAlertingDefinition().getName(); if (StringUtils.isEmpty(alertingDefinitionName)) { return DEFAULT_ALERTING_NAME; } else { return alertingDefinitionName; } }
/** * {@inheritDoc} */ @Override public void run() { if (log.isDebugEnabled()) { log.debug("|-Checking alert definitions..."); } long currentTime = System.currentTimeMillis(); for (AlertingState alertingState : alertingStates) { try { long nextCheckTime = alertingState.getLastCheckTime() + alertingState.getAlertingDefinition().getTimeRange(TimeUnit.MILLISECONDS); if (nextCheckTime <= currentTime) { thresholdChecker.checkThreshold(alertingState); } } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Unexpected exception occured.", e); } } } }
/** * This method is called when an active alert is still violating its threshold. * * @param alertingState * the ongoing alert * @param violationValue * the value has violated the threshold */ public void alertOngoing(AlertingState alertingState, double violationValue) { if (alertingState == null) { throw new IllegalArgumentException("The given alerting state may not be null."); } if (log.isDebugEnabled()) { log.debug("Alert definition '{}' is ongoing.", alertingState.getAlertingDefinition().getName()); } if (alertingState.getAlertingDefinition().getThresholdType() == ThresholdType.UPPER_THRESHOLD) { alertingState.setExtremeValue(Math.max(violationValue, alertingState.getExtremeValue())); } else { alertingState.setExtremeValue(Math.min(violationValue, alertingState.getExtremeValue())); } for (IAlertAction alertAction : alertActions) { alertAction.onOngoing(alertingState); } }
/** * This method is called when an active alert is ending. * * @param alertingState * the ending alert */ public void alertEnding(AlertingState alertingState) { if (alertingState == null) { throw new IllegalArgumentException("The given alerting state may not be null."); } if (log.isDebugEnabled()) { log.debug("Alert definition '{}' is ending.", alertingState.getAlertingDefinition().getName()); } alertingState.getAlert().close(System.currentTimeMillis(), AlertClosingReason.ALERT_RESOLVED); for (IAlertAction alertAction : alertActions) { alertAction.onEnding(alertingState); } alertingState.setAlert(null); } }
/** * Handle the {@link AbstractAlertingDefinitionEvent}. * * @param event * the received {@link AbstractAlertingDefinitionEvent} */ private void deletedAlertingDefinition(AbstractAlertingDefinitionEvent event) { for (AlertingState state : alertingStates) { if (Objects.equals(state.getAlertingDefinition().getId(), event.getFirst().getId())) { if (null != state.getAlert()) { state.getAlert().close(System.currentTimeMillis(), AlertClosingReason.ALERTING_DEFINITION_DELETED); } alertingStates.remove(state); break; } } }
@Test public void loadingEvent() { AbstractAlertingDefinitionEvent event = new AlertingDefinitionLoadedEvent(this, Arrays.asList(definitionOne, definitionTwo)); alertingScheduler.onApplicationEvent(event); verifyZeroInteractions(thresholdChecker, executorService, definitionOne, definitionTwo); assertThat(getAlertingStates(), hasSize(2)); assertThat(getAlertingStates().get(0).getAlertingDefinition(), equalTo(definitionOne)); assertThat(getAlertingStates().get(1).getAlertingDefinition(), equalTo(definitionTwo)); }
/** * This method is called when no data is existing for the given threshold in the latest period. * * @param alertingState * the threshold which has been checked */ public void noData(AlertingState alertingState) { if (alertingState == null) { return; } if (log.isDebugEnabled()) { log.debug("||-No data available for alerting definition '{}'. Expecting the same behavior as before.", alertingState.getAlertingDefinition().getName()); } if (!alertingState.isAlertActive() || (alertingState.getValidCount() > 0)) { valid(alertingState); } else { violation(alertingState, Double.NaN); } } }
@Test @SuppressWarnings("unchecked") public void templateResolverThrowsException() throws IOException { when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingDefinition.getName()).thenReturn("myName"); when(templateResolver.resolveTemplate(any(AlertEMailTemplateType.class), any(AlertingState.class))).thenThrow(IOException.class); emailAction.onEnding(alertingState); verify(alertingDefinition).getName(); verify(alertingDefinition).getMeasurement(); verifyNoMoreInteractions(alertingDefinition); verify(alertingState, times(2)).getAlertingDefinition(); verifyNoMoreInteractions(alertingState); verify(templateResolver).resolveTemplate(any(AlertEMailTemplateType.class), eq(alertingState)); verifyNoMoreInteractions(templateResolver); verifyZeroInteractions(emailSender); }
@Test public void createEvent() { AbstractAlertingDefinitionEvent event = new AlertingDefinitionCreatedEvent(this, definitionOne); alertingScheduler.onApplicationEvent(event); verifyZeroInteractions(thresholdChecker, executorService, definitionOne); assertThat(getAlertingStates(), hasSize(1)); assertThat(getAlertingStates().get(0).getAlertingDefinition(), equalTo(definitionOne)); }
@Test @SuppressWarnings("unchecked") public void templateResolverThrowsException() throws IOException { when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingDefinition.getName()).thenReturn("myName"); when(templateResolver.resolveTemplate(any(AlertEMailTemplateType.class), any(AlertingState.class))).thenThrow(IOException.class); emailAction.onStarting(alertingState); verify(alertingDefinition).getName(); verify(alertingDefinition).getMeasurement(); verifyNoMoreInteractions(alertingDefinition); verify(alertingState, times(2)).getAlertingDefinition(); verifyNoMoreInteractions(alertingState); verify(templateResolver).resolveTemplate(any(AlertEMailTemplateType.class), eq(alertingState)); verifyNoMoreInteractions(templateResolver); verifyZeroInteractions(emailSender); }
/** * Handle the {@link AbstractAlertingDefinitionEvent}. * * @param event * the received {@link AbstractAlertingDefinitionEvent} */ private void updatedAlertingDefinition(AbstractAlertingDefinitionEvent event) { Iterator<AlertingState> iterator = alertingStates.iterator(); while (iterator.hasNext()) { AlertingState state = iterator.next(); if (Objects.equals(state.getAlertingDefinition().getId(), event.getFirst().getId())) { state.setAlertingDefinition(event.getFirst()); if (null != state.getAlert()) { state.getAlert().setAlertingDefinition(event.getFirst()); } break; } } } }
@Test @SuppressWarnings("unchecked") public void lowerThresholdNewExtremeValue() { IAlertAction alertAction = Mockito.mock(IAlertAction.class); Iterator<IAlertAction> iterator = Mockito.mock(Iterator.class); when(iterator.hasNext()).thenReturn(true, false); when(iterator.next()).thenReturn(alertAction); when(alertActions.iterator()).thenReturn(iterator); AlertingDefinition alertingDefinition = Mockito.mock(AlertingDefinition.class); when(alertingDefinition.getThresholdType()).thenReturn(ThresholdType.LOWER_THRESHOLD); AlertingState alertingState = Mockito.mock(AlertingState.class); when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingState.getLastCheckTime()).thenReturn(1234L); when(alertingState.getExtremeValue()).thenReturn(5D); alertingService.alertOngoing(alertingState, 3D); verify(alertingState).setExtremeValue(3D); verify(alertingState).getExtremeValue(); verify(alertingState).getAlertingDefinition(); verifyNoMoreInteractions(alertingState); verify(alertAction).onOngoing(alertingState); verifyNoMoreInteractions(alertAction); verify(alertActions).iterator(); verifyNoMoreInteractions(alertActions); verifyZeroInteractions(alertRegistry); }
@Test @SuppressWarnings({ "unchecked", "rawtypes" }) public void onStartNoBtx() throws IOException { when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingDefinition.getName()).thenReturn("myName"); when(alertingDefinition.getNotificationEmailAddresses()).thenReturn(Arrays.asList("test@example.com")); when(templateResolver.resolveTemplate(AlertEMailTemplateType.HTML_ALERT_OPEN, alertingState)).thenReturn("htmlBody"); when(templateResolver.resolveTemplate(AlertEMailTemplateType.TXT_ALERT_OPEN, alertingState)).thenReturn("textBody"); emailAction.onStarting(alertingState); verify(alertingDefinition).getName(); verify(alertingDefinition).getMeasurement(); verify(alertingDefinition).getNotificationEmailAddresses(); verifyNoMoreInteractions(alertingDefinition); verify(alertingState, times(3)).getAlertingDefinition(); verifyNoMoreInteractions(alertingState); verify(templateResolver).resolveTemplate(AlertEMailTemplateType.HTML_ALERT_OPEN, alertingState); verify(templateResolver).resolveTemplate(AlertEMailTemplateType.TXT_ALERT_OPEN, alertingState); verifyNoMoreInteractions(templateResolver); ArgumentCaptor<String> captorSubject = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> captorHtmlBody = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> captorTextBody = ArgumentCaptor.forClass(String.class); ArgumentCaptor<List> captorRecipients = ArgumentCaptor.forClass(List.class); verify(emailSender).sendEMail(captorSubject.capture(), captorHtmlBody.capture(), captorTextBody.capture(), captorRecipients.capture()); assertThat(captorHtmlBody.getValue(), equalTo("htmlBody")); assertThat(captorTextBody.getValue(), equalTo("textBody")); assertThat(captorSubject.getValue(), containsString("myName")); assertThat((List<String>) captorRecipients.getValue(), hasItem("test@example.com")); verifyNoMoreInteractions(emailSender); }
@Test public void checkExistingAlertingStates() throws Exception { AlertingDefinition definitionOne = mock(AlertingDefinition.class); AlertingDefinition definitionTwo = mock(AlertingDefinition.class); when(definitionOne.getTimeRange(any(TimeUnit.class))).thenReturn(1L); when(definitionTwo.getTimeRange(any(TimeUnit.class))).thenReturn(3600000L); alertingScheduler.onApplicationEvent(new AlertingDefinitionCreatedEvent(this, definitionOne)); alertingScheduler.onApplicationEvent(new AlertingDefinitionCreatedEvent(this, definitionTwo)); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { ((AlertingState) invocation.getArguments()[0]).setLastCheckTime(System.currentTimeMillis()); return null; } }).when(thresholdChecker).checkThreshold(any(AlertingState.class)); alertingScheduler.run(); // both are checked Thread.sleep(10); alertingScheduler.run(); // only first is checked ArgumentCaptor<AlertingState> stateCaptor = ArgumentCaptor.forClass(AlertingState.class); verify(thresholdChecker, times(3)).checkThreshold(stateCaptor.capture()); verifyNoMoreInteractions(thresholdChecker); verifyZeroInteractions(executorService); assertThat(stateCaptor.getAllValues().get(0).getAlertingDefinition(), equalTo(definitionOne)); assertThat(stateCaptor.getAllValues().get(1).getAlertingDefinition(), equalTo(definitionTwo)); assertThat(stateCaptor.getAllValues().get(2).getAlertingDefinition(), equalTo(definitionOne)); }
@Test public void updateEvent() { alertingScheduler.onApplicationEvent(new AlertingDefinitionCreatedEvent(this, definitionOne)); assertThat(getAlertingStates().get(0).getAlertingDefinition(), equalTo(definitionOne)); AbstractAlertingDefinitionEvent event = new AlertingDefinitionUpdateEvent(this, definitionTwo); when(definitionOne.getId()).thenReturn("id"); when(definitionTwo.getId()).thenReturn("id"); alertingScheduler.onApplicationEvent(event); verify(definitionOne).getId(); verify(definitionTwo).getId(); verifyNoMoreInteractions(definitionOne, definitionTwo); verifyZeroInteractions(thresholdChecker, executorService); assertThat(getAlertingStates(), hasSize(1)); assertThat(getAlertingStates().get(0).getAlertingDefinition(), equalTo(definitionTwo)); }
@Test public void updateUnknownEvent() { alertingScheduler.onApplicationEvent(new AlertingDefinitionCreatedEvent(this, definitionOne)); AbstractAlertingDefinitionEvent event = new AlertingDefinitionUpdateEvent(this, definitionTwo); when(definitionOne.getId()).thenReturn("id"); when(definitionTwo.getId()).thenReturn("id_2"); alertingScheduler.onApplicationEvent(event); assertThat(getAlertingStates(), hasSize(1)); assertThat(getAlertingStates().get(0).getAlertingDefinition(), equalTo(definitionOne)); verify(definitionOne).getId(); verify(definitionTwo).getId(); verifyNoMoreInteractions(definitionOne, definitionTwo); verifyZeroInteractions(thresholdChecker, executorService); assertThat(getAlertingStates(), hasSize(1)); } }
/** * This method is called when a new alert is started. * * @param alertingState * the started alert * @param violationValue * the value has violated the threshold */ public void alertStarting(AlertingState alertingState, double violationValue) { if (alertingState == null) { throw new IllegalArgumentException("The given alerting state may not be null."); } Alert alert = new Alert(alertingState.getAlertingDefinition(), alertingState.getLastCheckTime()); alertRegistry.registerAlert(alert); alertingState.setAlert(alert); alertingState.setExtremeValue(violationValue); for (IAlertAction alertAction : alertActions) { alertAction.onStarting(alertingState); } }
@Test public void neverChecked() throws BusinessException, Exception { long time = System.currentTimeMillis(); when(influxDao.isConnected()).thenReturn(true); when(influxDao.query(any(String.class))).thenReturn(new QueryResult()); when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingState.getLastCheckTime()).thenReturn(-1L); thresholdChecker.checkThreshold(alertingState); ArgumentCaptor<Long> currentTimeCaptor = ArgumentCaptor.forClass(Long.class); verify(alertingState, times(2)).getLastCheckTime(); verify(alertingState, times(2)).setLastCheckTime(currentTimeCaptor.capture()); verify(alertingState, times(2)).getAlertingDefinition(); assertThat(currentTimeCaptor.getValue(), greaterThanOrEqualTo(time)); verify(alertingDefinition, times(2)).getTimeRange(TimeUnit.MILLISECONDS); verify(influxDao).query(any(String.class)); verify(influxDao).isConnected(); verify(stateManager).noData(alertingState); verify(alertingDefinition).getThresholdType(); verify(alertingDefinition).getField(); verify(alertingDefinition).getTags(); verify(alertingDefinition).getMeasurement(); verify(alertingDefinition, times(2)).getTimeRange(TimeUnit.MILLISECONDS); verifyNoMoreInteractions(influxDao, alertingState, stateManager, alertingDefinition); }
@Test public void noData() throws BusinessException, Exception { long time = System.currentTimeMillis(); when(influxDao.isConnected()).thenReturn(true); when(influxDao.query(any(String.class))).thenReturn(new QueryResult()); when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); thresholdChecker.checkThreshold(alertingState); ArgumentCaptor<Long> timeCaptor = ArgumentCaptor.forClass(Long.class); verify(alertingState, times(2)).getLastCheckTime(); verify(alertingState).setLastCheckTime(timeCaptor.capture()); verify(alertingState).getAlertingDefinition(); assertThat(timeCaptor.getValue(), greaterThanOrEqualTo(time)); verify(influxDao).query(any(String.class)); verify(influxDao).isConnected(); verify(stateManager).noData(alertingState); verify(alertingDefinition).getThresholdType(); verify(alertingDefinition).getField(); verify(alertingDefinition).getTags(); verify(alertingDefinition).getMeasurement(); verify(alertingDefinition).getTimeRange(TimeUnit.MILLISECONDS); verifyNoMoreInteractions(influxDao, alertingState, stateManager, alertingDefinition); }
@Test public void noViolationUpperThreshold() throws BusinessException, Exception { long time = System.currentTimeMillis(); when(influxDao.isConnected()).thenReturn(true); when(influxDao.query(any(String.class))).thenReturn(queryResult); when(alertingState.getAlertingDefinition()).thenReturn(alertingDefinition); when(alertingDefinition.getThresholdType()).thenReturn(ThresholdType.UPPER_THRESHOLD); when(alertingDefinition.getThreshold()).thenReturn(15D); thresholdChecker.checkThreshold(alertingState); ArgumentCaptor<Long> timeCaptor = ArgumentCaptor.forClass(Long.class); verify(alertingState, times(2)).getLastCheckTime(); verify(alertingState).setLastCheckTime(timeCaptor.capture()); verify(alertingState, times(2)).getAlertingDefinition(); assertThat(timeCaptor.getValue(), greaterThanOrEqualTo(time)); verify(influxDao).query(any(String.class)); verify(influxDao).isConnected(); verify(stateManager).valid(alertingState); verify(alertingDefinition, times(2)).getThresholdType(); verify(alertingDefinition).getThreshold(); verify(alertingDefinition).getField(); verify(alertingDefinition).getTags(); verify(alertingDefinition).getMeasurement(); verify(alertingDefinition).getTimeRange(TimeUnit.MILLISECONDS); verifyNoMoreInteractions(influxDao, alertingState, stateManager, alertingDefinition); }