package rocks.inspectit.server.alerting;
import java.util.concurrent.TimeUnit;
import org.influxdb.dto.QueryResult;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import rocks.inspectit.server.alerting.state.AlertingState;
import rocks.inspectit.server.influx.dao.InfluxDBDao;
import rocks.inspectit.server.influx.util.InfluxQueryFactory;
import rocks.inspectit.server.influx.util.QueryResultWrapper;
import rocks.inspectit.shared.all.spring.logger.Log;
import rocks.inspectit.shared.cs.ci.AlertingDefinition;
/**
* The threshold checker component. It is used to check the status of a given threshold defined by
* an {@link AlertingDefinition}.
*
* @author Marius Oehler
*
*/
@Component
public class ThresholdChecker {
/**
* Logger of this class.
*/
@Log
private Logger log;
/**
* {@link IInfluxDBDao} instance.
*/
@Autowired
private InfluxDBDao influxDao;
/**
* {@link AlertingStateLifecycleManager} instance.
*/
@Autowired
private AlertingStateLifecycleManager stateManager;
/**
* Checks whether the threshold defined by the {@link AlertingDefinition} contained in the given
* {@link AlertingState} has been violated. The result is given to the
* {@link AlertingStateLifecycleManager}.
*
* @param alertingState
* the {@link AlertingState} containing the threshold to check
*/
public void checkThreshold(AlertingState alertingState) {
if (log.isDebugEnabled()) {
log.debug("||-Check threshold defined by alerting definition '{}'.", alertingState.getAlertingDefinition().toString());
}
if (!influxDao.isConnected()) {
if (log.isDebugEnabled()) {
log.debug("||-Cannot check threshold without connected influxDB.");
}
return;
}
long currentTime = System.currentTimeMillis();
long lastCheckTime = alertingState.getLastCheckTime();
if (lastCheckTime < 0) {
lastCheckTime = currentTime - alertingState.getAlertingDefinition().getTimeRange(TimeUnit.MILLISECONDS);
alertingState.setLastCheckTime(lastCheckTime);
}
String queryString = InfluxQueryFactory.buildThresholdCheckForAlertingStateQuery(alertingState, currentTime);
QueryResult queryResult = influxDao.query(queryString);
QueryResultWrapper resultWrapper = new QueryResultWrapper(queryResult);
if (resultWrapper.isEmpty()) {
stateManager.noData(alertingState);
} else {
double extremeValue = resultWrapper.getDouble(0, 1);
if (isViolating(alertingState.getAlertingDefinition(), extremeValue)) {
stateManager.violation(alertingState, extremeValue);
} else {
stateManager.valid(alertingState);
}
}
alertingState.setLastCheckTime(currentTime);
}
/**
* Checks whether the given double value violates the threshold of the given
* {@link AlertingDefinition}.
*
* @param definition
* the {@link AlertingDefinition} defining the threshold
* @param testValue
* the value to test against the threshold
* @return Returns <code>true</code> if the value violates the threshold.
*/
private boolean isViolating(AlertingDefinition definition, double testValue) {
switch (definition.getThresholdType()) {
case LOWER_THRESHOLD:
return testValue < definition.getThreshold();
case UPPER_THRESHOLD:
default:
return testValue > definition.getThreshold();
}
}
}