Moved over the streaming parsing.
Original commit: elastic/x-pack-elasticsearch@10bd127df5
This commit is contained in:
parent
6b2fbe400e
commit
3625b5bc91
|
@ -17,7 +17,7 @@ import java.util.List;
|
|||
|
||||
public class Alert implements ToXContent {
|
||||
|
||||
private final String alertName;
|
||||
private String alertName;
|
||||
private String queryName;
|
||||
private AlertTrigger trigger;
|
||||
private TimeValue timePeriod;
|
||||
|
@ -93,6 +93,10 @@ public class Alert implements ToXContent {
|
|||
return alertName;
|
||||
}
|
||||
|
||||
public void alertName(String alertName) {
|
||||
this.alertName = alertName;
|
||||
}
|
||||
|
||||
public String queryName() {
|
||||
return queryName;
|
||||
}
|
||||
|
@ -141,6 +145,9 @@ public class Alert implements ToXContent {
|
|||
this.lastRan = lastRan;
|
||||
}
|
||||
|
||||
public Alert() {
|
||||
}
|
||||
|
||||
public Alert(String alertName, String queryName, AlertTrigger trigger,
|
||||
TimeValue timePeriod, List<AlertAction> actions, String schedule, DateTime lastRan,
|
||||
List<String> indices, DateTime running, long version, boolean enabled, boolean simpleQuery){
|
||||
|
@ -163,35 +170,49 @@ public class Alert implements ToXContent {
|
|||
|
||||
//Note we deliberately don't serialize the version here
|
||||
builder.startObject();
|
||||
builder.field(AlertsStore.QUERY_FIELD.getPreferredName(), queryName);
|
||||
builder.field(AlertsStore.SCHEDULE_FIELD.getPreferredName(), schedule);
|
||||
builder.field(AlertsStore.TIMEPERIOD_FIELD.getPreferredName(), timePeriod);
|
||||
builder.field(AlertsStore.LASTRAN_FIELD.getPreferredName(), lastRan);
|
||||
builder.field(AlertsStore.CURRENTLY_RUNNING.getPreferredName(), running);
|
||||
if (queryName != null) {
|
||||
builder.field(AlertsStore.QUERY_NAME_FIELD.getPreferredName(), queryName);
|
||||
}
|
||||
if (schedule != null) {
|
||||
builder.field(AlertsStore.SCHEDULE_FIELD.getPreferredName(), schedule);
|
||||
}
|
||||
if (timePeriod != null) {
|
||||
builder.field(AlertsStore.TIMEPERIOD_FIELD.getPreferredName(), timePeriod);
|
||||
}
|
||||
if (lastRan != null) {
|
||||
builder.field(AlertsStore.LASTRAN_FIELD.getPreferredName(), lastRan);
|
||||
}
|
||||
if (running != null) {
|
||||
builder.field(AlertsStore.CURRENTLY_RUNNING.getPreferredName(), running);
|
||||
}
|
||||
builder.field(AlertsStore.ENABLED.getPreferredName(), enabled);
|
||||
builder.field(AlertsStore.SIMPLE_QUERY.getPreferredName(), simpleQuery);
|
||||
builder.field(AlertsStore.LAST_ACTION_FIRE.getPreferredName(), lastActionFire);
|
||||
|
||||
builder.field(AlertsStore.TRIGGER_FIELD.getPreferredName());
|
||||
trigger.toXContent(builder, params);
|
||||
builder.field(AlertsStore.ACTION_FIELD.getPreferredName());
|
||||
|
||||
builder.startObject();
|
||||
for (AlertAction action : actions){
|
||||
builder.field(action.getActionName());
|
||||
action.toXContent(builder, params);
|
||||
if (lastActionFire != null) {
|
||||
builder.field(AlertsStore.LAST_ACTION_FIRE.getPreferredName(), lastActionFire);
|
||||
}
|
||||
|
||||
if (actions != null && !actions.isEmpty()) {
|
||||
builder.startObject(AlertsStore.ACTION_FIELD.getPreferredName());
|
||||
for (AlertAction action : actions){
|
||||
builder.field(action.getActionName());
|
||||
action.toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
if (indices != null && !indices.isEmpty()) {
|
||||
builder.field(AlertsStore.INDICES.getPreferredName());
|
||||
builder.startArray();
|
||||
builder.startArray(AlertsStore.INDICES.getPreferredName());
|
||||
for (String index : indices){
|
||||
builder.value(index);
|
||||
}
|
||||
builder.endArray();
|
||||
}
|
||||
|
||||
if (trigger != null) {
|
||||
builder.field(AlertsStore.TRIGGER_FIELD.getPreferredName());
|
||||
trigger.toXContent(builder, params);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.elasticsearch.action.index.IndexResponse;
|
|||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.alerts.actions.AlertAction;
|
||||
import org.elasticsearch.alerts.actions.AlertActionRegistry;
|
||||
import org.elasticsearch.alerts.triggers.AlertTrigger;
|
||||
import org.elasticsearch.alerts.triggers.TriggerManager;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.Requests;
|
||||
|
@ -30,24 +29,19 @@ import org.elasticsearch.common.joda.time.DateTime;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class AlertsStore extends AbstractComponent {
|
||||
|
||||
public static final ParseField QUERY_FIELD = new ParseField("query");
|
||||
public static final ParseField QUERY_NAME_FIELD = new ParseField("query");
|
||||
public static final ParseField SCHEDULE_FIELD = new ParseField("schedule");
|
||||
public static final ParseField TRIGGER_FIELD = new ParseField("trigger");
|
||||
public static final ParseField TIMEPERIOD_FIELD = new ParseField("timeperiod");
|
||||
|
@ -200,96 +194,73 @@ public class AlertsStore extends AbstractComponent {
|
|||
return parseAlert(alertId, sh.getSourceRef(), sh.getVersion());
|
||||
}
|
||||
|
||||
private Alert parseAlert(String alertId, BytesReference bytesReference, long version) {
|
||||
// TODO: streaming parsing!
|
||||
Map<String, Object> fields = XContentHelper.convertToMap(bytesReference, false).v2();
|
||||
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 = alertActionRegistry.parseActionsFromMap(actionMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse actions [" + actionObj + "]");
|
||||
}
|
||||
|
||||
DateTime lastRan = new DateTime(0);
|
||||
if( fields.get(LASTRAN_FIELD.getPreferredName()) != null){
|
||||
lastRan = new DateTime(fields.get(LASTRAN_FIELD.getPreferredName()).toString());
|
||||
} else if (fields.get("lastRan") != null) {
|
||||
lastRan = new DateTime(fields.get("lastRan").toString());
|
||||
}
|
||||
|
||||
DateTime running = new DateTime(0);
|
||||
if (fields.get(CURRENTLY_RUNNING.getPreferredName()) != null) {
|
||||
running = new DateTime(fields.get(CURRENTLY_RUNNING.getPreferredName()).toString());
|
||||
}
|
||||
|
||||
DateTime lastActionFire = new DateTime(0);
|
||||
if (fields.get(LAST_ACTION_FIRE.getPreferredName()) != null) {
|
||||
lastActionFire = new DateTime(fields.get(LAST_ACTION_FIRE.getPreferredName()).toString());
|
||||
}
|
||||
|
||||
List<String> indices = new ArrayList<>();
|
||||
if (fields.get(INDICES.getPreferredName()) != null && fields.get(INDICES.getPreferredName()) instanceof List){
|
||||
indices = (List<String>)fields.get(INDICES.getPreferredName());
|
||||
} else {
|
||||
logger.warn("Indices : " + fields.get(INDICES.getPreferredName()) + " class " + fields.get(INDICES.getPreferredName()).getClass() );
|
||||
}
|
||||
|
||||
boolean enabled = true;
|
||||
if (fields.get(ENABLED.getPreferredName()) != null ) {
|
||||
logger.error(ENABLED.getPreferredName() + " " + fields.get(ENABLED.getPreferredName()));
|
||||
Object enabledObj = fields.get(ENABLED.getPreferredName());
|
||||
enabled = parseAsBoolean(enabledObj);
|
||||
}
|
||||
|
||||
boolean simpleQuery = true;
|
||||
if (fields.get(SIMPLE_QUERY.getPreferredName()) != null ) {
|
||||
logger.error(SIMPLE_QUERY.getPreferredName() + " " + fields.get(SIMPLE_QUERY.getPreferredName()));
|
||||
Object enabledObj = fields.get(SIMPLE_QUERY.getPreferredName());
|
||||
simpleQuery = parseAsBoolean(enabledObj);
|
||||
}
|
||||
|
||||
Alert alert = new Alert(alertId, query, trigger, timePeriod, actions, schedule, lastRan, indices, running, version, enabled, simpleQuery);
|
||||
alert.lastActionFire(lastActionFire);
|
||||
|
||||
if (fields.get(TIMESTAMP_FIELD.getPreferredName()) != null) {
|
||||
alert.timestampString(fields.get(TIMESTAMP_FIELD.getPreferredName()).toString());
|
||||
}
|
||||
|
||||
return alert;
|
||||
}
|
||||
|
||||
private boolean parseAsBoolean(Object enabledObj) {
|
||||
boolean enabled;
|
||||
if (enabledObj instanceof Boolean){
|
||||
enabled = (Boolean)enabledObj;
|
||||
} else {
|
||||
if (enabledObj.toString().toLowerCase(Locale.ROOT).equals("true") ||
|
||||
enabledObj.toString().toLowerCase(Locale.ROOT).equals("1")) {
|
||||
enabled = true;
|
||||
} else if ( enabledObj.toString().toLowerCase(Locale.ROOT).equals("false") ||
|
||||
enabledObj.toString().toLowerCase(Locale.ROOT).equals("0")) {
|
||||
enabled = false;
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse [" + enabledObj + "] as a boolean");
|
||||
private Alert parseAlert(String alertName, BytesReference source, long version) {
|
||||
Alert alert = new Alert();
|
||||
alert.alertName(alertName);
|
||||
alert.version(version);
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
assert token == XContentParser.Token.START_OBJECT;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if (TRIGGER_FIELD.match(currentFieldName)) {
|
||||
alert.trigger(TriggerManager.parseTrigger(parser));
|
||||
} else if (ACTION_FIELD.match(currentFieldName)) {
|
||||
List<AlertAction> actions = alertActionRegistry.instantiateAlertActions(parser);
|
||||
alert.actions(actions);
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if (INDICES.match(currentFieldName)) {
|
||||
List<String> indices = new ArrayList<>();
|
||||
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||
indices.add(parser.text());
|
||||
}
|
||||
alert.indices(indices);
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if (QUERY_NAME_FIELD.match(currentFieldName)) {
|
||||
alert.queryName(parser.textOrNull());
|
||||
} else if (SCHEDULE_FIELD.match(currentFieldName)) {
|
||||
alert.schedule(parser.textOrNull());
|
||||
} else if (TIMEPERIOD_FIELD.match(currentFieldName)) {
|
||||
alert.timestampString(parser.textOrNull());
|
||||
} else if (LASTRAN_FIELD.match(currentFieldName)) {
|
||||
alert.lastRan(DateTime.parse(parser.textOrNull()));
|
||||
} else if (CURRENTLY_RUNNING.match(currentFieldName)) {
|
||||
alert.running(DateTime.parse(parser.textOrNull()));
|
||||
} else if (ENABLED.match(currentFieldName)) {
|
||||
alert.enabled(parser.booleanValue());
|
||||
} else if (SIMPLE_QUERY.match(currentFieldName)) {
|
||||
alert.simpleQuery(parser.booleanValue());
|
||||
} else if (TIMEPERIOD_FIELD.match(currentFieldName)) {
|
||||
alert.timePeriod(TimeValue.parseTimeValue(parser.textOrNull(), defaultTimePeriod));
|
||||
} else if (LAST_ACTION_FIRE.match(currentFieldName)) {
|
||||
alert.lastActionFire(DateTime.parse(parser.textOrNull()));
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected token [" + token + "]");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("Error during parsing alert", e);
|
||||
}
|
||||
return enabled;
|
||||
|
||||
if (alert.timePeriod() == null) {
|
||||
alert.timePeriod(defaultTimePeriod);
|
||||
}
|
||||
if (alert.lastActionFire() == null) {
|
||||
alert.lastActionFire(new DateTime(0));
|
||||
}
|
||||
return alert;
|
||||
}
|
||||
|
||||
private ClusterHealthStatus createAlertsIndex() {
|
||||
|
|
|
@ -12,7 +12,9 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import java.io.IOException;
|
||||
|
||||
public interface AlertAction extends ToXContent {
|
||||
|
||||
public String getActionName();
|
||||
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException;
|
||||
|
||||
public boolean doAction(Alert alert, AlertActionEntry actionEntry);
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.alerts.actions;
|
||||
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface AlertActionFactory {
|
||||
AlertAction createAction(Object parameters);
|
||||
|
||||
AlertAction createAction(XContentParser parser) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.alerts.actions;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
||||
|
@ -15,22 +16,18 @@ import org.elasticsearch.action.index.IndexRequest;
|
|||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.update.UpdateRequest;
|
||||
import org.elasticsearch.action.update.UpdateResponse;
|
||||
import org.elasticsearch.alerts.AlertManager;
|
||||
import org.elasticsearch.alerts.triggers.AlertTrigger;
|
||||
import org.elasticsearch.alerts.triggers.TriggerManager;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.Requests;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Priority;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.index.engine.DocumentAlreadyExistsException;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
@ -38,11 +35,9 @@ import org.elasticsearch.threadpool.ThreadPool;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
|
@ -197,45 +192,82 @@ public class AlertActionManager {
|
|||
|
||||
|
||||
protected AlertActionEntry parseHistory(String historyId, SearchHit sh, long version) {
|
||||
Map<String, Object> fields = sh.sourceAsMap();
|
||||
return parseHistory(historyId, fields, version);
|
||||
return parseHistory(historyId, sh.getSourceRef(), version);
|
||||
}
|
||||
|
||||
protected AlertActionEntry parseHistory(String historyId, Map<String,Object> fields, long version) {
|
||||
return parseHistory(historyId, fields, version, actionRegistry, logger);
|
||||
protected AlertActionEntry parseHistory(String historyId, BytesReference source, long version) {
|
||||
return parseHistory(historyId, source, version, actionRegistry, logger);
|
||||
}
|
||||
|
||||
protected static AlertActionEntry parseHistory(String historyId, Map<String,Object> fields, long version,
|
||||
protected static AlertActionEntry parseHistory(String historyId, BytesReference source, long version,
|
||||
AlertActionRegistry actionRegistry, ESLogger logger) {
|
||||
String alertName = fields.get(ALERT_NAME_FIELD).toString();
|
||||
boolean triggered = (Boolean)fields.get(TRIGGERED_FIELD);
|
||||
DateTime fireTime = new DateTime(fields.get(FIRE_TIME_FIELD).toString());
|
||||
DateTime scheduledFireTime = new DateTime(fields.get(SCHEDULED_FIRE_TIME_FIELD).toString());
|
||||
AlertTrigger trigger = TriggerManager.parseTriggerFromMap((Map<String,Object>)fields.get(TRIGGER_FIELD));
|
||||
String queryRan = fields.get(QUERY_RAN_FIELD).toString();
|
||||
long numberOfResults = ((Number)fields.get(NUMBER_OF_RESULTS_FIELD)).longValue();
|
||||
Object actionObj = fields.get(ACTIONS_FIELD);
|
||||
List<AlertAction> actions;
|
||||
if (actionObj instanceof Map) {
|
||||
Map<String, Object> actionMap = (Map<String, Object>) actionObj;
|
||||
actions = actionRegistry.parseActionsFromMap(actionMap);
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to parse actions [" + actionObj + "]");
|
||||
AlertActionEntry entry = new AlertActionEntry();
|
||||
entry.setId(historyId);
|
||||
entry.setVersion(version);
|
||||
try (XContentParser parser = XContentHelper.createParser(source)) {
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
assert token == XContentParser.Token.START_OBJECT;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
switch (currentFieldName) {
|
||||
case ACTIONS_FIELD:
|
||||
entry.setActions(actionRegistry.instantiateAlertActions(parser));
|
||||
break;
|
||||
case TRIGGER_FIELD:
|
||||
entry.setTrigger(TriggerManager.parseTrigger(parser));
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
switch (currentFieldName) {
|
||||
case INDICES_FIELD:
|
||||
List<String> indices = new ArrayList<>();
|
||||
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||
indices.add(parser.text());
|
||||
}
|
||||
entry.setIndices(indices);
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
switch (currentFieldName) {
|
||||
case ALERT_NAME_FIELD:
|
||||
entry.setAlertName(parser.text());
|
||||
break;
|
||||
case TRIGGERED_FIELD:
|
||||
entry.setTriggered(parser.booleanValue());
|
||||
break;
|
||||
case FIRE_TIME_FIELD:
|
||||
entry.setFireTime(DateTime.parse(parser.text()));
|
||||
break;
|
||||
case SCHEDULED_FIRE_TIME_FIELD:
|
||||
entry.setScheduledTime(DateTime.parse(parser.text()));
|
||||
break;
|
||||
case QUERY_RAN_FIELD:
|
||||
entry.setTriggeringQuery(parser.text());
|
||||
break;
|
||||
case NUMBER_OF_RESULTS_FIELD:
|
||||
entry.setNumberOfResults(parser.longValue());
|
||||
break;
|
||||
case AlertActionState.FIELD_NAME:
|
||||
entry.setEntryState(AlertActionState.fromString(parser.text()));
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("Error during parsing alert action", e);
|
||||
}
|
||||
|
||||
List<String> indices = new ArrayList<>();
|
||||
if (fields.get(INDICES_FIELD) != null && fields.get(INDICES_FIELD) instanceof List){
|
||||
indices = (List<String>)fields.get(INDICES_FIELD);
|
||||
} else {
|
||||
logger.debug("Indices : " + fields.get(INDICES_FIELD) + " class " +
|
||||
(fields.get(INDICES_FIELD) != null ? fields.get(INDICES_FIELD).getClass() : null ));
|
||||
}
|
||||
|
||||
String stateString = fields.get(AlertActionState.FIELD_NAME).toString();
|
||||
AlertActionState state = AlertActionState.fromString(stateString);
|
||||
|
||||
return new AlertActionEntry(historyId, version, alertName, triggered, fireTime, scheduledFireTime, trigger, queryRan,
|
||||
numberOfResults, actions, indices, state);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,7 +341,7 @@ public class AlertActionManager {
|
|||
getRequest.id(entryId);
|
||||
GetResponse getResponse = client.get(getRequest).actionGet();
|
||||
if (getResponse.isExists()) {
|
||||
return parseHistory(entryId, getResponse.getSourceAsMap(), getResponse.getVersion());
|
||||
return parseHistory(entryId, getResponse.getSourceAsBytesRef(), getResponse.getVersion());
|
||||
} else {
|
||||
throw new ElasticsearchException("Unable to find [" + entryId + "] in the [" + ALERT_HISTORY_INDEX + "]" );
|
||||
}
|
||||
|
|
|
@ -7,16 +7,16 @@ package org.elasticsearch.alerts.actions;
|
|||
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.alerts.Alert;
|
||||
import org.elasticsearch.alerts.AlertManager;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AlertActionRegistry extends AbstractComponent {
|
||||
|
||||
|
@ -37,16 +37,23 @@ public class AlertActionRegistry extends AbstractComponent {
|
|||
.build();
|
||||
}
|
||||
|
||||
public List<AlertAction> parseActionsFromMap(Map<String,Object> actionMap) {
|
||||
ImmutableOpenMap<String, AlertActionFactory> actionImplemented = this.actionImplemented;
|
||||
public List<AlertAction> instantiateAlertActions(XContentParser parser) throws IOException {
|
||||
List<AlertAction> actions = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> actionEntry : actionMap.entrySet()) {
|
||||
AlertActionFactory factory = actionImplemented.get(actionEntry.getKey());
|
||||
if (factory != null) {
|
||||
actions.add(factory.createAction(actionEntry.getValue()));
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("No action exists with the name [" + actionEntry.getKey() + "]");
|
||||
ImmutableOpenMap<String, AlertActionFactory> actionImplemented = this.actionImplemented;
|
||||
String actionFactoryName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
actionFactoryName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
AlertActionFactory factory = actionImplemented.get(actionFactoryName);
|
||||
if (factory != null) {
|
||||
actions.add(factory.createAction(parser));
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("No action exists with the name [" + actionFactoryName + "]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
|
|
@ -9,25 +9,27 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.alerts.Alert;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.mail.*;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
public class EmailAlertAction implements AlertAction {
|
||||
List<Address> emailAddresses = new ArrayList<>();
|
||||
String displayField = null;
|
||||
|
||||
private String displayField = null;
|
||||
private List<Address> emailAddresses = new ArrayList<>();
|
||||
|
||||
// TODO: Move to factory and make configurable
|
||||
int port = 587;
|
||||
String server = "smtp.gmail.com";
|
||||
String from = "esalertingtest@gmail.com";
|
||||
String passwd = "elasticsearchforthewin";
|
||||
String server = "smtp.gmail.com";
|
||||
int port = 587;
|
||||
|
||||
public EmailAlertAction(String ... addresses){
|
||||
public EmailAlertAction(String displayField, String ... addresses){
|
||||
for (String address : addresses) {
|
||||
addEmailAddress(address);
|
||||
}
|
||||
|
|
|
@ -5,37 +5,47 @@
|
|||
*/
|
||||
package org.elasticsearch.alerts.actions;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EmailAlertActionFactory implements AlertActionFactory {
|
||||
|
||||
@Override
|
||||
public AlertAction createAction(Object parameters) {
|
||||
EmailAlertAction action = new EmailAlertAction();
|
||||
if (parameters instanceof List){
|
||||
for (String emailAddress : (List<String>)parameters) {
|
||||
action.addEmailAddress(emailAddress);
|
||||
public AlertAction createAction(XContentParser parser) throws IOException {
|
||||
String display = null;
|
||||
List<String> addresses = new ArrayList<>();
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
switch (currentFieldName) {
|
||||
case "display":
|
||||
display = parser.text();
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
switch (currentFieldName) {
|
||||
case "addresses":
|
||||
while (parser.nextToken() != XContentParser.Token.END_ARRAY) {
|
||||
addresses.add(parser.text());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected token [" + token + "]");
|
||||
}
|
||||
} 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());
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse [" + parameters + "] as an EmailAlertAction");
|
||||
}
|
||||
return action;
|
||||
return new EmailAlertAction(display, addresses.toArray(new String[addresses.size()]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,42 +7,46 @@ package org.elasticsearch.alerts.actions;
|
|||
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by brian on 8/17/14.
|
||||
*/
|
||||
public class IndexAlertActionFactory implements AlertActionFactory {
|
||||
Client client;
|
||||
|
||||
private final Client client;
|
||||
|
||||
public IndexAlertActionFactory(Client client){
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertAction createAction(Object parameters) {
|
||||
try {
|
||||
if (parameters instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) parameters;
|
||||
String index = paramMap.get("index").toString();
|
||||
if (!index.toLowerCase(Locale.ROOT).equals(index)) {
|
||||
throw new ElasticsearchIllegalArgumentException("Index names must be all lowercase");
|
||||
}
|
||||
public AlertAction createAction(XContentParser parser) throws IOException {
|
||||
String index = null;
|
||||
String type = null;
|
||||
|
||||
String type = paramMap.get("type").toString();
|
||||
if (!type.toLowerCase(Locale.ROOT).equals(type)) {
|
||||
throw new ElasticsearchIllegalArgumentException("Type names must be all lowercase");
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
switch (currentFieldName) {
|
||||
case "index":
|
||||
index = parser.text();
|
||||
break;
|
||||
case "type":
|
||||
type = parser.text();
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
|
||||
return new IndexAlertAction(index, type, client);
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse [" + parameters + "] as an IndexAlertAction");
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected token [" + token + "]");
|
||||
}
|
||||
} catch (Throwable t){
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse [" + parameters + "] as an IndexAlertAction", t);
|
||||
}
|
||||
return new IndexAlertAction(index, type, client);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,11 @@ import org.elasticsearch.alerts.AlertManager;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.script.ExecutableScript;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
|
@ -32,34 +29,52 @@ public class TriggerManager extends AbstractComponent {
|
|||
private final AlertManager alertManager;
|
||||
private final ScriptService scriptService;
|
||||
|
||||
public static AlertTrigger parseTriggerFromMap(Map<String, Object> triggerMap) {
|
||||
for (Map.Entry<String,Object> entry : triggerMap.entrySet()){
|
||||
AlertTrigger.TriggerType type = AlertTrigger.TriggerType.fromString(entry.getKey());
|
||||
if (type == AlertTrigger.TriggerType.SCRIPT) {
|
||||
ScriptedAlertTrigger scriptedTrigger = parseScriptedTrigger(entry.getValue());
|
||||
return new AlertTrigger(scriptedTrigger);
|
||||
} else {
|
||||
AlertTrigger.SimpleTrigger simpleTrigger = AlertTrigger.SimpleTrigger.fromString(entry.getValue().toString().substring(0, 1));
|
||||
int value = Integer.valueOf(entry.getValue().toString().substring(1));
|
||||
return new AlertTrigger(simpleTrigger, type, value);
|
||||
}
|
||||
}
|
||||
throw new ElasticsearchIllegalArgumentException();
|
||||
}
|
||||
public static AlertTrigger parseTrigger(XContentParser parser) throws IOException {
|
||||
AlertTrigger trigger = null;
|
||||
|
||||
private static ScriptedAlertTrigger parseScriptedTrigger(Object value) {
|
||||
if (value instanceof Map) {
|
||||
Map<String,Object> valueMap = (Map<String,Object>)value;
|
||||
try {
|
||||
return new ScriptedAlertTrigger(valueMap.get("script").toString(),
|
||||
ScriptService.ScriptType.valueOf(valueMap.get("script_type").toString().toUpperCase(Locale.ROOT)), ///TODO : Fix ScriptType to parse strings properly, currently only accepts uppercase versions of the enum names
|
||||
valueMap.get("script_lang").toString());
|
||||
} catch (Exception e){
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse " + value + " as a ScriptedAlertTrigger", e);
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
switch (currentFieldName) {
|
||||
case "script":
|
||||
String script = null;
|
||||
ScriptService.ScriptType scriptType = null;
|
||||
String scriptLang = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token.isValue()) {
|
||||
switch (currentFieldName) {
|
||||
case "script" :
|
||||
script = parser.text();
|
||||
break;
|
||||
case "script_type" :
|
||||
scriptType = ScriptService.ScriptType.valueOf(parser.text());
|
||||
break;
|
||||
case "script_lang" :
|
||||
scriptLang = parser.text();
|
||||
break;
|
||||
default:
|
||||
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
trigger = new AlertTrigger(new ScriptedAlertTrigger(script, scriptType, scriptLang));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
String expression = parser.text();
|
||||
AlertTrigger.SimpleTrigger simpleTrigger = AlertTrigger.SimpleTrigger.fromString(expression.substring(0, 1));
|
||||
int value = Integer.valueOf(expression.substring(1));
|
||||
trigger = new AlertTrigger(simpleTrigger, AlertTrigger.TriggerType.NUMBER_OF_EVENTS, value);
|
||||
}
|
||||
} else {
|
||||
throw new ElasticsearchIllegalArgumentException("Unable to parse " + value + " as a ScriptedAlertTrigger, not a Map");
|
||||
}
|
||||
return trigger;
|
||||
}
|
||||
|
||||
@Inject
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.settings.ImmutableSettings;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
@ -103,7 +104,8 @@ public class BasicAlertingTest extends ElasticsearchIntegrationTest {
|
|||
AlertActionRegistry alertActionRegistry = internalCluster().getInstance(AlertActionRegistry.class, internalCluster().getMasterName());
|
||||
alertActionRegistry.registerAction("test", new AlertActionFactory() {
|
||||
@Override
|
||||
public AlertAction createAction(Object parameters) {
|
||||
public AlertAction createAction(XContentParser parser) throws IOException {
|
||||
parser.nextToken();
|
||||
return alertAction;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.alerts.actions;
|
||||
|
||||
import org.elasticsearch.alerts.BasicAlertingTest;
|
||||
import org.elasticsearch.alerts.triggers.AlertTrigger;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.time.DateTime;
|
||||
import org.elasticsearch.common.joda.time.DateTimeZone;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -16,15 +19,19 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
|
||||
/**
|
||||
*/
|
||||
@ElasticsearchIntegrationTest.ClusterScope(scope = ElasticsearchIntegrationTest.Scope.SUITE, numClientNodes = 0, transportClientRatio = 0, numDataNodes = 1)
|
||||
public class AlertActionsTest extends ElasticsearchIntegrationTest {
|
||||
|
||||
private static final FormatDateTimeFormatter formatter = DateFieldMapper.Defaults.DATE_TIME_FORMATTER;
|
||||
|
||||
@Test
|
||||
public void testAlertActionParser(){
|
||||
DateTime fireTime = new DateTime();
|
||||
DateTime scheduledFireTime = new DateTime();
|
||||
public void testAlertActionParser() throws Exception {
|
||||
DateTime fireTime = new DateTime(DateTimeZone.UTC);
|
||||
DateTime scheduledFireTime = new DateTime(DateTimeZone.UTC);
|
||||
Map<String, Object> triggerMap = new HashMap<>();
|
||||
triggerMap.put("numberOfEvents", ">1");
|
||||
Map<String,Object> actionMap = new HashMap<>();
|
||||
|
@ -34,18 +41,20 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest {
|
|||
emailParamMap.put("addresses", addresses);
|
||||
actionMap.put("email", emailParamMap);
|
||||
|
||||
Map<String, Object> fieldMap = new HashMap<>();
|
||||
fieldMap.put(AlertActionManager.ALERT_NAME_FIELD, "testName");
|
||||
fieldMap.put(AlertActionManager.TRIGGERED_FIELD, true);
|
||||
fieldMap.put(AlertActionManager.FIRE_TIME_FIELD, fireTime.toDateTimeISO().toString());
|
||||
fieldMap.put(AlertActionManager.SCHEDULED_FIRE_TIME_FIELD, scheduledFireTime.toDateTimeISO().toString());
|
||||
fieldMap.put(AlertActionManager.TRIGGER_FIELD, triggerMap);
|
||||
fieldMap.put(AlertActionManager.QUERY_RAN_FIELD, "foobar");
|
||||
fieldMap.put(AlertActionManager.NUMBER_OF_RESULTS_FIELD,10);
|
||||
fieldMap.put(AlertActionManager.ACTIONS_FIELD, actionMap);
|
||||
fieldMap.put(AlertActionState.FIELD_NAME, AlertActionState.ACTION_NEEDED.toString());
|
||||
XContentBuilder builder = jsonBuilder();
|
||||
builder.startObject();
|
||||
builder.field(AlertActionManager.ALERT_NAME_FIELD, "testName");
|
||||
builder.field(AlertActionManager.TRIGGERED_FIELD, true);
|
||||
builder.field(AlertActionManager.FIRE_TIME_FIELD, formatter.printer().print(fireTime));
|
||||
builder.field(AlertActionManager.SCHEDULED_FIRE_TIME_FIELD, formatter.printer().print(scheduledFireTime));
|
||||
builder.field(AlertActionManager.TRIGGER_FIELD, triggerMap);
|
||||
builder.field(AlertActionManager.QUERY_RAN_FIELD, "foobar");
|
||||
builder.field(AlertActionManager.NUMBER_OF_RESULTS_FIELD, 10);
|
||||
builder.field(AlertActionManager.ACTIONS_FIELD, actionMap);
|
||||
builder.field(AlertActionState.FIELD_NAME, AlertActionState.ACTION_NEEDED.toString());
|
||||
builder.endObject();
|
||||
AlertActionRegistry alertActionRegistry = internalCluster().getInstance(AlertActionRegistry.class, internalCluster().getMasterName());
|
||||
AlertActionEntry actionEntry = AlertActionManager.parseHistory("foobar", fieldMap, 0, alertActionRegistry, logger);
|
||||
AlertActionEntry actionEntry = AlertActionManager.parseHistory("foobar", builder.bytes(), 0, alertActionRegistry, logger);
|
||||
|
||||
assertEquals(actionEntry.getVersion(), 0);
|
||||
assertEquals(actionEntry.getAlertName(), "testName");
|
||||
|
|
Loading…
Reference in New Issue