Alerting : better email formatting
This commit enables better email formatting. Original commit: elastic/x-pack-elasticsearch@8be3e3b6d1
This commit is contained in:
parent
e3250c0366
commit
0d9061b838
|
@ -153,51 +153,55 @@ public class AlertManager extends AbstractLifecycleComponent {
|
|||
).setTypes(ALERT_TYPE).setIndices(ALERT_INDEX).execute().get();
|
||||
for (SearchHit sh : searchResponse.getHits()) {
|
||||
String alertId = sh.getId();
|
||||
logger.warn("Found : [{}]", alertId);
|
||||
Map<String,Object> fields = sh.sourceAsMap();
|
||||
//Map<String,SearchHitField> fields = sh.getFields();
|
||||
|
||||
for (String field : fields.keySet() ) {
|
||||
logger.warn("Field : [{}]", field);
|
||||
}
|
||||
|
||||
String query = fields.get(QUERY_FIELD.getPreferredName()).toString();
|
||||
String schedule = fields.get(SCHEDULE_FIELD.getPreferredName()).toString();
|
||||
Object triggerObj = fields.get(TRIGGER_FIELD.getPreferredName());
|
||||
AlertTrigger trigger = null;
|
||||
if (triggerObj instanceof Map) {
|
||||
Map<String, Object> triggerMap = (Map<String, Object>) triggerObj;
|
||||
trigger = TriggerManager.parseTriggerFromMap(triggerMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse trigger [" + triggerObj + "]");
|
||||
}
|
||||
|
||||
String timeString = fields.get(TIMEPERIOD_FIELD.getPreferredName()).toString();
|
||||
TimeValue timePeriod = TimeValue.parseTimeValue(timeString, defaultTimePeriod);
|
||||
|
||||
Object actionObj = fields.get(ACTION_FIELD.getPreferredName());
|
||||
List<AlertAction> actions = null;
|
||||
if (actionObj instanceof Map) {
|
||||
Map<String, Object> actionMap = (Map<String, Object>) actionObj;
|
||||
actions = actionManager.parseActionsFromMap(actionMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse actions [" + triggerObj + "]");
|
||||
}
|
||||
|
||||
DateTime lastRan = new DateTime(fields.get("lastRan").toString());
|
||||
|
||||
List<String> indices = null;
|
||||
if (fields.get(INDICES.getPreferredName()) != null && fields.get(INDICES.getPreferredName()) instanceof List){
|
||||
indices = (List<String>)fields.get(INDICES.getPreferredName());
|
||||
}
|
||||
|
||||
Alert alert = new Alert(alertId, query, trigger, timePeriod, actions, schedule, lastRan, indices);
|
||||
Alert alert = parseAlert(sh, alertId);
|
||||
alertMap.put(alertId, alert);
|
||||
}
|
||||
logger.warn("Loaded [{}] alerts from the alert index.", alertMap.size());
|
||||
}
|
||||
}
|
||||
|
||||
private Alert parseAlert(SearchHit sh, String alertId) {
|
||||
logger.warn("Found : [{}]", alertId);
|
||||
Map<String,Object> fields = sh.sourceAsMap();
|
||||
//Map<String,SearchHitField> fields = sh.getFields();
|
||||
|
||||
for (String field : fields.keySet() ) {
|
||||
logger.warn("Field : [{}]", field);
|
||||
}
|
||||
|
||||
String query = fields.get(QUERY_FIELD.getPreferredName()).toString();
|
||||
String schedule = fields.get(SCHEDULE_FIELD.getPreferredName()).toString();
|
||||
Object triggerObj = fields.get(TRIGGER_FIELD.getPreferredName());
|
||||
AlertTrigger trigger = null;
|
||||
if (triggerObj instanceof Map) {
|
||||
Map<String, Object> triggerMap = (Map<String, Object>) triggerObj;
|
||||
trigger = TriggerManager.parseTriggerFromMap(triggerMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse trigger [" + triggerObj + "]");
|
||||
}
|
||||
|
||||
String timeString = fields.get(TIMEPERIOD_FIELD.getPreferredName()).toString();
|
||||
TimeValue timePeriod = TimeValue.parseTimeValue(timeString, defaultTimePeriod);
|
||||
|
||||
Object actionObj = fields.get(ACTION_FIELD.getPreferredName());
|
||||
List<AlertAction> actions = null;
|
||||
if (actionObj instanceof Map) {
|
||||
Map<String, Object> actionMap = (Map<String, Object>) actionObj;
|
||||
actions = actionManager.parseActionsFromMap(actionMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse actions [" + triggerObj + "]");
|
||||
}
|
||||
|
||||
DateTime lastRan = new DateTime(fields.get("lastRan").toString());
|
||||
|
||||
List<String> indices = null;
|
||||
if (fields.get(INDICES.getPreferredName()) != null && fields.get(INDICES.getPreferredName()) instanceof List){
|
||||
indices = (List<String>)fields.get(INDICES.getPreferredName());
|
||||
}
|
||||
|
||||
return new Alert(alertId, query, trigger, timePeriod, actions, schedule, lastRan, indices);
|
||||
}
|
||||
|
||||
public Alert getAlertForName(String alertName) {
|
||||
synchronized (alertMap) {
|
||||
return alertMap.get(alertName);
|
||||
|
|
|
@ -6,11 +6,16 @@
|
|||
package org.elasticsearch.alerting;
|
||||
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class AlertResult {
|
||||
public SearchResponse searchResponse;
|
||||
public AlertTrigger trigger;
|
||||
public boolean isTriggered;
|
||||
public XContentBuilder query;
|
||||
public String[] indices;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
@ -20,17 +25,23 @@ public class AlertResult {
|
|||
AlertResult that = (AlertResult) o;
|
||||
|
||||
if (isTriggered != that.isTriggered) return false;
|
||||
if (!searchResponse.equals(that.searchResponse)) return false;
|
||||
if (!trigger.equals(that.trigger)) return false;
|
||||
if (!Arrays.equals(indices, that.indices)) return false;
|
||||
if (query != null ? !query.equals(that.query) : that.query != null) return false;
|
||||
if (searchResponse != null ? !searchResponse.equals(that.searchResponse) : that.searchResponse != null)
|
||||
return false;
|
||||
if (trigger != null ? !trigger.equals(that.trigger) : that.trigger != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = searchResponse.hashCode();
|
||||
result = 31 * result + trigger.hashCode();
|
||||
int result = searchResponse != null ? searchResponse.hashCode() : 0;
|
||||
result = 31 * result + (trigger != null ? trigger.hashCode() : 0);
|
||||
result = 31 * result + (isTriggered ? 1 : 0);
|
||||
result = 31 * result + (query != null ? query.hashCode() : 0);
|
||||
result = 31 * result + (indices != null ? Arrays.hashCode(indices) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,21 +5,15 @@
|
|||
*/
|
||||
package org.elasticsearch.alerting;
|
||||
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.indexedscripts.get.GetIndexedScriptResponse;
|
||||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.script.CompiledScript;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.quartz.*;
|
||||
import org.quartz.impl.StdSchedulerFactory;
|
||||
|
@ -27,25 +21,21 @@ import org.quartz.simpl.SimpleJobFactory;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AlertScheduler extends AbstractLifecycleComponent {
|
||||
|
||||
Scheduler scheduler = null;
|
||||
private final AlertManager alertManager;
|
||||
private final Client client;
|
||||
private final ScriptService scriptService;
|
||||
private final TriggerManager triggerManager;
|
||||
private final AlertActionManager actionManager;
|
||||
|
||||
@Inject
|
||||
public AlertScheduler(Settings settings, AlertManager alertManager, ScriptService scriptService, Client client,
|
||||
public AlertScheduler(Settings settings, AlertManager alertManager, Client client,
|
||||
TriggerManager triggerManager, AlertActionManager actionManager) {
|
||||
super(settings);
|
||||
this.alertManager = alertManager;
|
||||
this.client = client;
|
||||
this.scriptService = scriptService;
|
||||
this.triggerManager = triggerManager;
|
||||
this.actionManager = actionManager;
|
||||
try {
|
||||
|
@ -66,18 +56,24 @@ public class AlertScheduler extends AbstractLifecycleComponent {
|
|||
logger.warn("Running the following query : [{}]", builder.string());
|
||||
|
||||
SearchRequestBuilder srb = client.prepareSearch().setSource(builder);
|
||||
String[] indices = alert.indices().toArray(new String[0]);
|
||||
if (alert.indices() != null ){
|
||||
srb.setIndices(alert.indices().toArray(new String[0]));
|
||||
logger.warn("Setting indices to : " + alert.indices());
|
||||
srb.setIndices(indices);
|
||||
}
|
||||
SearchResponse sr = srb.execute().get();
|
||||
logger.warn("Got search response");
|
||||
logger.warn("Got search response hits : [{}]", sr.getHits().getTotalHits() );
|
||||
AlertResult result = new AlertResult();
|
||||
//TODO: move these to ctr
|
||||
result.isTriggered = triggerManager.isTriggered(alertName,sr);
|
||||
|
||||
result.searchResponse = sr;
|
||||
result.trigger = alert.trigger();
|
||||
result.query = builder;
|
||||
result.indices = indices;
|
||||
|
||||
if (result.isTriggered) {
|
||||
logger.warn("We have triggered");
|
||||
//actionManager.doAction(alertName,result);
|
||||
actionManager.doAction(alertName,result);
|
||||
logger.warn("Did action !");
|
||||
}else{
|
||||
logger.warn("We didn't trigger");
|
||||
|
@ -94,7 +90,6 @@ public class AlertScheduler extends AbstractLifecycleComponent {
|
|||
Date scheduledFireTime = jobExecutionContext.getScheduledFireTime();
|
||||
DateTime clampEnd = new DateTime(scheduledFireTime);
|
||||
DateTime clampStart = clampEnd.minusSeconds((int)alert.timePeriod().seconds());
|
||||
logger.error("Subtracting : [{}] seconds from [{}] = [{}]", (int)alert.timePeriod().seconds(), clampEnd, clampStart );
|
||||
|
||||
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON);
|
||||
builder.startObject();
|
||||
|
|
|
@ -46,6 +46,10 @@ public class AlertTrigger {
|
|||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return triggerType + " " + trigger + " " + value;
|
||||
}
|
||||
|
||||
public static enum SimpleTrigger {
|
||||
EQUAL,
|
||||
NOT_EQUAL,
|
||||
|
@ -54,8 +58,8 @@ public class AlertTrigger {
|
|||
RISES_BY,
|
||||
FALLS_BY;
|
||||
|
||||
public static SimpleTrigger fromString(final String sAction) {
|
||||
switch (sAction) {
|
||||
public static SimpleTrigger fromString(final String sTrigger) {
|
||||
switch (sTrigger) {
|
||||
case ">":
|
||||
return GREATER_THAN;
|
||||
case "<":
|
||||
|
@ -70,9 +74,32 @@ public class AlertTrigger {
|
|||
case "<-":
|
||||
return FALLS_BY;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unknown AlertAction:SimpleAction [" + sAction + "]");
|
||||
throw new ElasticsearchIllegalArgumentException("Unknown AlertAction:SimpleAction [" + sTrigger + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public static String asString(final SimpleTrigger trigger){
|
||||
switch (trigger) {
|
||||
case GREATER_THAN:
|
||||
return ">";
|
||||
case LESS_THAN:
|
||||
return "<";
|
||||
case EQUAL:
|
||||
return "==";
|
||||
case NOT_EQUAL:
|
||||
return "!=";
|
||||
case RISES_BY:
|
||||
return "->";
|
||||
case FALLS_BY:
|
||||
return "<-";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return asString(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static enum TriggerType {
|
||||
|
@ -86,6 +113,19 @@ public class AlertTrigger {
|
|||
throw new ElasticsearchIllegalArgumentException("Unknown AlertTrigger:TriggerType [" + sTriggerType + "]");
|
||||
}
|
||||
}
|
||||
|
||||
public static String asString(final TriggerType triggerType){
|
||||
switch (triggerType) {
|
||||
case NUMBER_OF_EVENTS:
|
||||
return "numberOfEvents";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return asString(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
package org.elasticsearch.alerting;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.SearchHitField;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.AddressException;
|
||||
|
@ -18,6 +21,7 @@ import javax.mail.internet.MimeMessage;
|
|||
|
||||
public class EmailAlertAction implements AlertAction {
|
||||
List<Address> emailAddresses = new ArrayList<>();
|
||||
String displayField = null;
|
||||
|
||||
String from = "esalertingtest@gmail.com";
|
||||
String passwd = "elasticsearchforthewin";
|
||||
|
@ -39,6 +43,10 @@ public class EmailAlertAction implements AlertAction {
|
|||
}
|
||||
}
|
||||
|
||||
public void displayField(String displayField){
|
||||
this.displayField = displayField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doAction(String alertName, AlertResult result) {
|
||||
Properties props = new Properties();
|
||||
|
@ -57,13 +65,36 @@ public class EmailAlertAction implements AlertAction {
|
|||
message.setFrom(new InternetAddress(from));
|
||||
message.setRecipients(Message.RecipientType.TO,
|
||||
emailAddresses.toArray(new Address[1]));
|
||||
message.setSubject("Elasticsearch Alert from " + alertName);
|
||||
message.setText(result.searchResponse.toString());
|
||||
message.setSubject("Elasticsearch Alert " + alertName + " triggered");
|
||||
StringBuffer output = new StringBuffer();
|
||||
output.append("The following query triggered because " + result.trigger.toString() + "\n");
|
||||
output.append("The total number of hits returned : " + result.searchResponse.getHits().getTotalHits() + "\n");
|
||||
output.append("For query : " + XContentHelper.convertToJson(result.query.bytes(),true,true) + "\n");
|
||||
output.append("\n");
|
||||
output.append("Indices : ");
|
||||
for (String index : result.indices) {
|
||||
output.append(index);
|
||||
output.append("/");
|
||||
}
|
||||
output.append("\n");
|
||||
output.append("\n");
|
||||
if (displayField != null) {
|
||||
for (SearchHit sh : result.searchResponse.getHits().getHits()) {
|
||||
if (sh.sourceAsMap().containsKey(displayField)) {
|
||||
output.append(sh.sourceAsMap().get(displayField).toString());
|
||||
} else {
|
||||
output.append(new String(sh.source()));
|
||||
}
|
||||
output.append("\n");
|
||||
}
|
||||
} else {
|
||||
output.append(result.searchResponse.toString());
|
||||
}
|
||||
message.setText(output.toString());
|
||||
Transport.send(message);
|
||||
} catch (Exception e){
|
||||
throw new ElasticsearchException("Failed to send mail", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
*/
|
||||
package org.elasticsearch.alerting;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EmailAlertActionFactory implements AlertActionFactory{
|
||||
|
||||
|
@ -16,6 +19,19 @@ public class EmailAlertActionFactory implements AlertActionFactory{
|
|||
for (String emailAddress : (List<String>)parameters) {
|
||||
action.addEmailAddress(emailAddress);
|
||||
}
|
||||
} else if (parameters instanceof Map) {
|
||||
Map<String,Object> paramMap = (Map<String,Object>)parameters;
|
||||
Object addresses = paramMap.get("addresses");
|
||||
if (addresses == null){
|
||||
throw new ElasticsearchException("Unable to parse email addresses from : " + parameters);
|
||||
}
|
||||
for (String emailAddress : (List<String>)addresses) {
|
||||
action.addEmailAddress(emailAddress);
|
||||
}
|
||||
Object displayField = paramMap.get("display");
|
||||
if (displayField != null){
|
||||
action.displayField(displayField.toString());
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
|
|
@ -41,10 +41,10 @@ public class TriggerManager extends AbstractComponent {
|
|||
logger.warn("Could not find alert named [{}] in alert manager perhaps it has been deleted.", alertName);
|
||||
return false;
|
||||
}
|
||||
int testValue;
|
||||
long testValue;
|
||||
switch (alert.trigger().triggerType()) {
|
||||
case NUMBER_OF_EVENTS:
|
||||
testValue = response.getHits().getHits().length;
|
||||
testValue = response.getHits().getTotalHits();
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Bad value for trigger.triggerType [" + alert.trigger().triggerType() + "]");
|
||||
|
|
Loading…
Reference in New Issue