package org.stagemonitor.alerting.check; import com.fasterxml.jackson.annotation.JsonAutoDetect; import org.stagemonitor.core.metrics.metrics2.MetricName; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; /** * A {@link Check} is a named collection of {@link Threshold}s with the same {@link MetricCategory} and target. * <p/> * Example: We have a check group named 'Search response time' with two checks both have the target * <code>requests.search.time</code>. The first check is that the 75th * percentile shall be < 4sec and the second one says the 99th percentile shall be < 10 sec. */ @JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE) public class Check { private String id = UUID.randomUUID().toString(); private String name; private MetricName target; private int alertAfterXFailures = 1; private Map<CheckResult.Status, List<Threshold>> thresholds = new LinkedHashMap<CheckResult.Status, List<Threshold>>(){{ put(CheckResult.Status.CRITICAL, new LinkedList<Threshold>()); put(CheckResult.Status.ERROR, new LinkedList<Threshold>()); put(CheckResult.Status.WARN, new LinkedList<Threshold>()); }}; private String application; private boolean active = true; /** * Performs threshold checks for the whole check group * * @param currentValuesByMetric the values of the target * @param actualTarget the actual target that matched the {@link #target} pattern * @return a list of check results (results with OK statuses are omitted) */ public List<CheckResult> check(MetricName actualTarget, Map<String, Number> currentValuesByMetric) { SortedMap<CheckResult.Status, List<Threshold>> sortedThresholds = new TreeMap<CheckResult.Status, List<Threshold>>(thresholds); for (Map.Entry<CheckResult.Status, List<Threshold>> entry : sortedThresholds.entrySet()) { List<CheckResult> results = checkThresholds(entry.getValue(), entry.getKey(), actualTarget, currentValuesByMetric); if (!results.isEmpty()) { return results; } } return Collections.emptyList(); } private List<CheckResult> checkThresholds(List<Threshold> thresholds, CheckResult.Status severity, MetricName actualTarget, Map<String, Number> currentValuesByMetric) { List<CheckResult> results = new ArrayList<CheckResult>(thresholds.size()); for (Threshold threshold : thresholds) { CheckResult result = threshold.check(severity, actualTarget, currentValuesByMetric); if (result.getStatus() != CheckResult.Status.OK) { results.add(result); } } return results; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public MetricName getTarget() { return target; } public void setTarget(MetricName target) { this.target = target; } public int getAlertAfterXFailures() { return alertAfterXFailures; } public void setAlertAfterXFailures(int alertAfterXFailures) { this.alertAfterXFailures = alertAfterXFailures; } public String getApplication() { return application; } public void setApplication(String application) { this.application = application; } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } public List<Threshold> getWarn() { return thresholds.get(CheckResult.Status.WARN); } public List<Threshold> getError() { return thresholds.get(CheckResult.Status.ERROR); } public List<Threshold> getCritical() { return thresholds.get(CheckResult.Status.CRITICAL); } public List<Threshold> getThresholds(CheckResult.Status severity) { return thresholds.get(severity); } }