package rocks.inspectit.server.alerting; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import rocks.inspectit.server.alerting.action.AlertingActionService; import rocks.inspectit.server.alerting.state.AlertingState; import rocks.inspectit.shared.all.spring.logger.Log; import rocks.inspectit.shared.cs.ci.AlertingDefinition; /** * This component handles the management of the lifecycle of the alerts. It is responsible for * transition from the individual alert states (starting, ongoing, ending). * * @author Marius Oehler * */ @Component public class AlertingStateLifecycleManager { /** * The logger for this class. */ @Log private Logger log; /** * The amount of intervals without a threshold violation before an alert is considered as valid. */ @Value("${alerting.resolutionDelay}") int thresholdResetCount; /** * {@link AlertingActionService} instance. */ @Autowired AlertingActionService alertingActionService; /** * This method is called if the given threshold (specified by the {@link AlertingDefinition} * contained in the {@link AlertingState}) has been violated in the latest interval. The given * value showed the largest deviation to the threshold. * * @param alertingState * the threshold which has been violated * @param violationValue * the value which violated the threshold */ public void violation(AlertingState alertingState, double violationValue) { if (alertingState == null) { return; } if (alertingState.isAlertActive()) { // alert is ongoing if (log.isDebugEnabled()) { log.debug("||-Violation of threshold '{}' is ongoing.", alertingState.getAlertingDefinition().getName()); } alertingState.setValidCount(0); alertingActionService.alertOngoing(alertingState, violationValue); } else { // alert is new if (log.isDebugEnabled()) { log.debug("||-Threshold violation. Value '{}' violated threshold '{}' and started a new alert.", violationValue, alertingState.getAlertingDefinition().toString()); } alertingActionService.alertStarting(alertingState, violationValue); } } /** * This method is called when the given threshold has not been violated in the latest period. * * @param alertingState * the threshold which has not been violated */ public void valid(AlertingState alertingState) { if (alertingState == null) { return; } if (log.isDebugEnabled()) { log.debug("||-Threshold '{}' has not been violated in the last interval.", alertingState.getAlertingDefinition().getName()); } if (!alertingState.isAlertActive()) { // threshold is not in a violation series return; } int validCount = alertingState.getValidCount(); if (validCount >= thresholdResetCount) { // alert ended if (log.isDebugEnabled()) { log.debug("||-Ended threshold violation series of '{}'.", alertingState.getAlertingDefinition().getName()); } alertingActionService.alertEnding(alertingState); } else { // alert is waiting for reset alertingState.setValidCount(validCount + 1); } } /** * 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); } } }