package org.stagemonitor.alerting.alerter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.stagemonitor.alerting.AlertingPlugin;
import org.stagemonitor.alerting.check.Check;
import org.stagemonitor.alerting.check.CheckResult;
import org.stagemonitor.alerting.check.Threshold;
import org.stagemonitor.alerting.incident.Incident;
import org.stagemonitor.core.MeasurementSession;
import org.stagemonitor.configuration.ConfigurationRegistry;
import org.stagemonitor.core.util.HttpClient;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import static org.stagemonitor.core.metrics.metrics2.MetricName.name;
public class AlertSender {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final AlertingPlugin alertingPlugin;
private final Map<String, Alerter> alerterByType;
private final List<Alerter> defaultAlerters;
public AlertSender(ConfigurationRegistry configuration) {
this(configuration, ServiceLoader.load(Alerter.class));
}
public AlertSender(ConfigurationRegistry configuration, Iterable<Alerter> alerterIterable) {
this.alertingPlugin = configuration.getConfig(AlertingPlugin.class);
Map<String, Alerter> alerters = new HashMap<String, Alerter>();
for (Alerter alerter : alerterIterable) {
alerter.init(new Alerter.InitArguments(configuration));
alerters.put(alerter.getAlerterType(), alerter);
}
alerterByType = Collections.unmodifiableMap(alerters);
defaultAlerters = Arrays.asList(new LogAlerter(), new ElasticsearchAlerter(configuration, new HttpClient()));
}
/**
* Returns all available {@link Alerter}s
*
* @return all available {@link Alerter}s
*/
public List<Alerter> getAvailableAlerters() {
List<Alerter> alerters = new ArrayList<Alerter>(alerterByType.size());
for (Alerter alerter : alerterByType.values()) {
if (alerter.isAvailable()) {
alerters.add(alerter);
}
}
return alerters;
}
public Incident sendTestAlert(Subscription subscription, CheckResult.Status status) {
Check check = new Check();
check.setName("Test Check");
check.setApplication("testApp");
check.setTarget(name("test").build());
check.getWarn().add(new Threshold("mean", Threshold.Operator.GREATER_EQUAL, 1));
Incident testIncident = new Incident(check, new MeasurementSession("testApp", "testHost", "testInstance"),
Arrays.asList(new CheckResult("test", 10, status)));
tryAlert(testIncident, subscription, alerterByType.get(subscription.getAlerterType()));
return testIncident;
}
public void sendAlerts(Check check, Incident incident) {
if (alertingPlugin.isMuteAlerts() || !incident.isAlertIncident(check)) {
return;
}
for (Alerter alerter : defaultAlerters) {
tryAlert(incident, null, alerter);
}
for (Subscription subscription : alertingPlugin.getSubscriptionsByIds().values()) {
if (subscription.isAlertOn(incident.getNewStatus())) {
tryAlert(incident, subscription, alerterByType.get(subscription.getAlerterType()));
}
}
}
private void tryAlert(Incident incident, Subscription subscription, Alerter alerter) {
if (alerter != null && alerter.isAvailable()) {
try {
alerter.alert(new Alerter.AlertArguments(incident, subscription));
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
} else {
if (subscription != null) {
logger.warn("Alerter with type '{}' is not available. " +
"Either the name of the alerter is invalid or it is not configured correctly.",
subscription.getAlerterType());
}
}
}
}