From 5d8f43225acb9f92fd05c95e3a2f7c6b85777f92 Mon Sep 17 00:00:00 2001 From: Brian Murphy Date: Fri, 7 Nov 2014 17:40:37 +0000 Subject: [PATCH] Alerts update trigger manager. This change changes the trigger manager to be pluggable. Also removes the SimpleTrigger class, for now all triggers should be scripts. Original commit: elastic/x-pack-elasticsearch@f7d0cb77e784546c421470e4609a88c38c17e90f --- .../java/org/elasticsearch/alerts/Alert.java | 79 +++--- .../org/elasticsearch/alerts/AlertsStore.java | 9 +- .../alerts/actions/AlertAction.java | 5 - .../alerts/actions/AlertActionFactory.java | 3 - .../alerts/actions/AlertActionManager.java | 11 +- .../alerts/actions/AlertActionRegistry.java | 15 -- .../alerts/actions/EmailAlertAction.java | 24 -- .../actions/EmailAlertActionFactory.java | 15 -- .../alerts/actions/IndexAlertAction.java | 13 +- .../actions/IndexAlertActionFactory.java | 4 - .../alerts/triggers/AlertTrigger.java | 227 ------------------ .../alerts/triggers/ScriptedAlertTrigger.java | 35 --- .../alerts/triggers/TriggerManager.java | 205 ---------------- .../alerts/triggers/TriggerResult.java | 43 ---- .../alerts/triggers/package-info.java | 6 - .../alerts/BasicAlertingTest.java | 9 + .../alerts/actions/AlertActionsTest.java | 35 +-- 17 files changed, 74 insertions(+), 664 deletions(-) delete mode 100644 src/main/java/org/elasticsearch/alerts/triggers/AlertTrigger.java delete mode 100644 src/main/java/org/elasticsearch/alerts/triggers/ScriptedAlertTrigger.java delete mode 100644 src/main/java/org/elasticsearch/alerts/triggers/TriggerManager.java delete mode 100644 src/main/java/org/elasticsearch/alerts/triggers/TriggerResult.java delete mode 100644 src/main/java/org/elasticsearch/alerts/triggers/package-info.java diff --git a/src/main/java/org/elasticsearch/alerts/Alert.java b/src/main/java/org/elasticsearch/alerts/Alert.java index fc75a6fbf69..8bc4e586a97 100644 --- a/src/main/java/org/elasticsearch/alerts/Alert.java +++ b/src/main/java/org/elasticsearch/alerts/Alert.java @@ -34,6 +34,7 @@ public class Alert implements ToXContent { private long version; private boolean enabled; + public Alert() { } @@ -69,53 +70,15 @@ public class Alert implements ToXContent { } if (trigger != null) { builder.field(AlertsStore.TRIGGER_FIELD.getPreferredName()); + builder.startObject(); + builder.field(trigger.getTriggerName()); trigger.toXContent(builder, params); + builder.endObject(); } builder.endObject(); return builder; } - public void readFrom(StreamInput in) throws IOException { - alertName = in.readString(); - searchRequest = new SearchRequest(); - searchRequest.readFrom(in); - trigger = AlertTrigger.readFrom(in); - int numActions = in.readInt(); - actions = new ArrayList<>(numActions); - for (int i=0; i>> 32)); + result = 31 * result + (enabled ? 1 : 0); + return result; + } + } diff --git a/src/main/java/org/elasticsearch/alerts/AlertsStore.java b/src/main/java/org/elasticsearch/alerts/AlertsStore.java index beb02b5cadf..385648e1008 100644 --- a/src/main/java/org/elasticsearch/alerts/AlertsStore.java +++ b/src/main/java/org/elasticsearch/alerts/AlertsStore.java @@ -62,13 +62,15 @@ public class AlertsStore extends AbstractComponent { private final ThreadPool threadPool; private final ConcurrentMap alertMap; private final AlertActionRegistry alertActionRegistry; + private final TriggerManager triggerManager; private final AtomicReference state = new AtomicReference<>(State.STOPPED); private final int scrollSize; private final TimeValue scrollTimeout; @Inject - public AlertsStore(Settings settings, Client client, ThreadPool threadPool, AlertActionRegistry alertActionRegistry) { + public AlertsStore(Settings settings, Client client, ThreadPool threadPool, AlertActionRegistry alertActionRegistry, + TriggerManager triggerManager) { super(settings); this.client = client; this.threadPool = threadPool; @@ -77,6 +79,7 @@ public class AlertsStore extends AbstractComponent { // Not using component settings, to let AlertsStore and AlertActionManager share the same settings this.scrollSize = settings.getAsInt("alerts.scroll.size", 100); this.scrollTimeout = settings.getAsTime("alerts.scroll.timeout", TimeValue.timeValueSeconds(30)); + this.triggerManager = triggerManager; } /** @@ -247,7 +250,7 @@ public class AlertsStore extends AbstractComponent { return alert; } - private Alert parseAlert(String alertName, BytesReference source) { + protected Alert parseAlert(String alertName, BytesReference source) { Alert alert = new Alert(); alert.alertName(alertName); try (XContentParser parser = XContentHelper.createParser(source)) { @@ -259,7 +262,7 @@ public class AlertsStore extends AbstractComponent { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if (TRIGGER_FIELD.match(currentFieldName)) { - alert.trigger(TriggerManager.parseTrigger(parser)); + alert.trigger(triggerManager.instantiateAlertTrigger(parser)); } else if (ACTION_FIELD.match(currentFieldName)) { List actions = alertActionRegistry.instantiateAlertActions(parser); alert.actions(actions); diff --git a/src/main/java/org/elasticsearch/alerts/actions/AlertAction.java b/src/main/java/org/elasticsearch/alerts/actions/AlertAction.java index c70eb50fa63..1bc36a5e7cc 100644 --- a/src/main/java/org/elasticsearch/alerts/actions/AlertAction.java +++ b/src/main/java/org/elasticsearch/alerts/actions/AlertAction.java @@ -20,10 +20,5 @@ public interface AlertAction extends ToXContent { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException; - public void writeTo(StreamOutput out) throws IOException; - public void readFrom(StreamInput in) throws IOException; - public boolean doAction(Alert alert, TriggerResult result); - - } diff --git a/src/main/java/org/elasticsearch/alerts/actions/AlertActionFactory.java b/src/main/java/org/elasticsearch/alerts/actions/AlertActionFactory.java index ecaa346ac73..0fb53b0d9b6 100644 --- a/src/main/java/org/elasticsearch/alerts/actions/AlertActionFactory.java +++ b/src/main/java/org/elasticsearch/alerts/actions/AlertActionFactory.java @@ -15,7 +15,4 @@ public interface AlertActionFactory { AlertAction createAction(XContentParser parser) throws IOException; - - AlertAction readFrom(StreamInput in) throws IOException; - } diff --git a/src/main/java/org/elasticsearch/alerts/actions/AlertActionManager.java b/src/main/java/org/elasticsearch/alerts/actions/AlertActionManager.java index b77c128fdc6..18b1f811834 100644 --- a/src/main/java/org/elasticsearch/alerts/actions/AlertActionManager.java +++ b/src/main/java/org/elasticsearch/alerts/actions/AlertActionManager.java @@ -62,6 +62,7 @@ public class AlertActionManager extends AbstractComponent { private final ThreadPool threadPool; private final AlertsStore alertsStore; private final AlertActionRegistry actionRegistry; + private final TriggerManager triggerManager; private AlertManager alertManager; private final BlockingQueue actionsToBeProcessed = new LinkedBlockingQueue<>(); @@ -73,12 +74,14 @@ public class AlertActionManager extends AbstractComponent { private static AlertActionEntry END_ENTRY = new AlertActionEntry(); @Inject - public AlertActionManager(Settings settings, Client client, AlertActionRegistry actionRegistry, ThreadPool threadPool, AlertsStore alertsStore) { + public AlertActionManager(Settings settings, Client client, AlertActionRegistry actionRegistry, + ThreadPool threadPool, AlertsStore alertsStore, TriggerManager triggerManager) { super(settings); this.client = client; this.actionRegistry = actionRegistry; this.threadPool = threadPool; this.alertsStore = alertsStore; + this.triggerManager = triggerManager; // Not using component settings, to let AlertsStore and AlertActionManager share the same settings this.scrollSize = settings.getAsInt("alerts.scroll.size", 100); this.scrollTimeout = settings.getAsTime("alerts.scroll.timeout", TimeValue.timeValueSeconds(30)); @@ -167,7 +170,7 @@ public class AlertActionManager extends AbstractComponent { logger.info("Loaded [{}] actions from the alert history index into actions queue", actionsToBeProcessed.size()); } - static AlertActionEntry parseHistory(String historyId, BytesReference source, long version, AlertActionRegistry actionRegistry) { + AlertActionEntry parseHistory(String historyId, BytesReference source, long version, AlertActionRegistry actionRegistry) { AlertActionEntry entry = new AlertActionEntry(); entry.setId(historyId); entry.setVersion(version); @@ -179,12 +182,13 @@ public class AlertActionManager extends AbstractComponent { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { + logger.error("START_OBJECT"); switch (currentFieldName) { case ACTIONS_FIELD: entry.setActions(actionRegistry.instantiateAlertActions(parser)); break; case TRIGGER_FIELD: - entry.setTrigger(TriggerManager.parseTrigger(parser)); + entry.setTrigger(triggerManager.instantiateAlertTrigger(parser)); break; case "response": // Ignore this, the binary form is already read @@ -194,6 +198,7 @@ public class AlertActionManager extends AbstractComponent { throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]"); } } else if (token.isValue()) { + logger.error("IS_VALUE"); switch (currentFieldName) { case ALERT_NAME_FIELD: entry.setAlertName(parser.text()); diff --git a/src/main/java/org/elasticsearch/alerts/actions/AlertActionRegistry.java b/src/main/java/org/elasticsearch/alerts/actions/AlertActionRegistry.java index 1f96eb41b43..e58198ec6a8 100644 --- a/src/main/java/org/elasticsearch/alerts/actions/AlertActionRegistry.java +++ b/src/main/java/org/elasticsearch/alerts/actions/AlertActionRegistry.java @@ -67,19 +67,4 @@ public class AlertActionRegistry extends AbstractComponent { } } - public static void writeTo(AlertAction action, StreamOutput out) throws IOException { - out.writeString(action.getActionName()); - action.writeTo(out); - } - - public static AlertAction readFrom(StreamInput in) throws IOException { - String actionName = in.readString(); - AlertActionFactory factory = actionImplemented.get(actionName); - if (factory != null) { - return factory.readFrom(in); - } else { - throw new ElasticsearchIllegalArgumentException("No action exists with the name [" + actionName + "]"); - } - } - } diff --git a/src/main/java/org/elasticsearch/alerts/actions/EmailAlertAction.java b/src/main/java/org/elasticsearch/alerts/actions/EmailAlertAction.java index c9e40e8f273..71fabb85315 100644 --- a/src/main/java/org/elasticsearch/alerts/actions/EmailAlertAction.java +++ b/src/main/java/org/elasticsearch/alerts/actions/EmailAlertAction.java @@ -71,30 +71,6 @@ public class EmailAlertAction implements AlertAction { return builder; } - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeOptionalString(displayField); - out.writeInt(emailAddresses.size()); - for (Address emailAddress : emailAddresses) { - out.writeString(emailAddress.toString()); - } - } - - @Override - public void readFrom(StreamInput in) throws IOException { - displayField = in.readOptionalString(); - int numberOfEmails = in.readInt(); - emailAddresses = new ArrayList<>(numberOfEmails); - for (int i=0; i": - return GREATER_THAN; - case "<": - return LESS_THAN; - case "=": - case "==": - return EQUAL; - case "!=": - return NOT_EQUAL; - case "->": - return RISES_BY; - case "<-": - return FALLS_BY; - default: - 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); - } - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - if (triggerType != TriggerType.SCRIPT) { - builder.startObject(); - builder.field(triggerType.toString(), trigger.toString() + value); - builder.endObject(); - } else { - builder.startObject(); - builder.field(triggerType.toString()); - scriptedTrigger.toXContent(builder, params); - builder.endObject(); - } - return builder; - } - - public static enum TriggerType { - NUMBER_OF_EVENTS, - SCRIPT; - - public static TriggerType fromString(final String sTriggerType) { - switch (sTriggerType) { - case "numberOfEvents": - return NUMBER_OF_EVENTS; - case "script": - return SCRIPT; - default: - throw new ElasticsearchIllegalArgumentException("Unknown AlertTrigger:TriggerType [" + sTriggerType + "]"); - } - } - - public static String asString(final TriggerType triggerType) { - switch (triggerType) { - case NUMBER_OF_EVENTS: - return "numberOfEvents"; - case SCRIPT: - return "script"; - default: - return "unknown"; - } - } - - public String toString(){ - return asString(this); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AlertTrigger that = (AlertTrigger) o; - - if (value != that.value) return false; - if (scriptedTrigger != null ? !scriptedTrigger.equals(that.scriptedTrigger) : that.scriptedTrigger != null) - return false; - if (trigger != that.trigger) return false; - if (triggerType != that.triggerType) return false; - - return true; - } - - @Override - public int hashCode() { - int result = trigger != null ? trigger.hashCode() : 0; - result = 31 * result + (triggerType != null ? triggerType.hashCode() : 0); - result = 31 * result + value; - result = 31 * result + (scriptedTrigger != null ? scriptedTrigger.hashCode() : 0); - return result; - } - - - public static void writeTo(AlertTrigger trigger, StreamOutput out) throws IOException { - out.writeString(trigger.triggerType.toString()); - if (trigger.triggerType.equals(TriggerType.NUMBER_OF_EVENTS)) { - out.writeString(trigger.toString()); - out.writeInt(trigger.value); - } else { - out.writeString(trigger.scriptedTrigger.scriptLang); - ScriptService.ScriptType.writeTo(trigger.scriptedTrigger.scriptType, out); - out.writeString(trigger.scriptedTrigger.script); - } - } - - public static AlertTrigger readFrom(StreamInput in) throws IOException { - TriggerType triggerType = TriggerType.fromString(in.readString()); - if (triggerType.equals(TriggerType.NUMBER_OF_EVENTS)) { - SimpleTrigger trigger = SimpleTrigger.fromString(in.readString()); - int value = in.readInt(); - return new AlertTrigger(trigger, triggerType, value); - } else { - String scriptLang = in.readString(); - ScriptService.ScriptType scriptType = ScriptService.ScriptType.readFrom(in); - String script = in.readString(); - ScriptedAlertTrigger scriptedTrigger = new ScriptedAlertTrigger(script, scriptType, scriptLang); - return new AlertTrigger(scriptedTrigger); - } - } - - -} diff --git a/src/main/java/org/elasticsearch/alerts/triggers/ScriptedAlertTrigger.java b/src/main/java/org/elasticsearch/alerts/triggers/ScriptedAlertTrigger.java deleted file mode 100644 index 96ed290e2d7..00000000000 --- a/src/main/java/org/elasticsearch/alerts/triggers/ScriptedAlertTrigger.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.alerts.triggers; - -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.script.ScriptService; - -import java.io.IOException; - -public class ScriptedAlertTrigger implements ToXContent { - public String script; - public ScriptService.ScriptType scriptType; - public String scriptLang; - - - public ScriptedAlertTrigger(String script, ScriptService.ScriptType scriptType, String scriptLang) { - this.script = script; - this.scriptType = scriptType; - this.scriptLang = scriptLang; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("script",script); - builder.field("script_type", scriptType); - builder.field("script_lang", scriptLang); - builder.endObject(); - return builder; - } -} diff --git a/src/main/java/org/elasticsearch/alerts/triggers/TriggerManager.java b/src/main/java/org/elasticsearch/alerts/triggers/TriggerManager.java deleted file mode 100644 index fef2694a645..00000000000 --- a/src/main/java/org/elasticsearch/alerts/triggers/TriggerManager.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.alerts.triggers; - -import org.elasticsearch.ElasticsearchIllegalArgumentException; -import org.elasticsearch.ElasticsearchIllegalStateException; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.alerts.Alert; -import org.elasticsearch.client.Client; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.collect.MapBuilder; -import org.elasticsearch.common.collect.Tuple; -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.time.DateTime; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.*; -import org.elasticsearch.index.mapper.core.DateFieldMapper; -import org.elasticsearch.script.ExecutableScript; -import org.elasticsearch.script.ScriptService; - -import java.io.IOException; -import java.util.Map; - - -/* - * TODO : The trigger classes need cleanup and refactoring to be similar to the AlertActions and be pluggable - */ -public class TriggerManager extends AbstractComponent { - - private static final FormatDateTimeFormatter dateTimeFormatter = DateFieldMapper.Defaults.DATE_TIME_FORMATTER; - - private final Client client; - private final ScriptService scriptService; - private final String fireTimePlaceHolder; - private final String scheduledFireTimePlaceHolder; - - @Inject - public TriggerManager(Settings settings, Client client, ScriptService scriptService) { - super(settings); - this.client = client; - this.scriptService = scriptService; - this.fireTimePlaceHolder = settings.get("prefix", "<<>>"); - this.scheduledFireTimePlaceHolder = settings.get("postfix", "<<>>"); - } - - public TriggerResult isTriggered(Alert alert, DateTime scheduledFireTime, DateTime fireTime) throws IOException { - SearchRequest request = prepareTriggerSearch(alert, scheduledFireTime, fireTime); - if (logger.isTraceEnabled()) { - logger.trace("For alert [{}] running query for [{}]", alert.alertName(), XContentHelper.convertToJson(request.source(), false, true)); - } - - SearchResponse response = client.search(request).actionGet(); // actionGet deals properly with InterruptedException - logger.debug("Ran alert [{}] and got hits : [{}]", alert.alertName(), response.getHits().getTotalHits()); - switch (alert.trigger().triggerType()) { - case NUMBER_OF_EVENTS: - return doSimpleTrigger(alert, request, response); - case SCRIPT: - return doScriptTrigger(alert, request, response); - default: - throw new ElasticsearchIllegalArgumentException("Bad value for trigger.triggerType [" + alert.trigger().triggerType() + "]"); - } - } - - public static AlertTrigger parseTrigger(XContentParser parser) throws IOException { - AlertTrigger trigger = null; - - 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); - } - } - return trigger; - } - - private TriggerResult doSimpleTrigger(Alert alert, SearchRequest request, SearchResponse response) { - boolean triggered = false; - long testValue = response.getHits().getTotalHits(); - int triggerValue = alert.trigger().value(); - //Move this to SimpleTrigger - switch (alert.trigger().trigger()) { - case GREATER_THAN: - triggered = testValue > triggerValue; - break; - case LESS_THAN: - triggered = testValue < triggerValue; - break; - case EQUAL: - triggered = testValue == triggerValue; - break; - case NOT_EQUAL: - triggered = testValue != triggerValue; - break; - case RISES_BY: - case FALLS_BY: - triggered = false; //TODO FIX THESE - break; - } - return new TriggerResult(triggered, request, response, alert.trigger()); - } - - private TriggerResult doScriptTrigger(Alert alert, SearchRequest request, SearchResponse response) { - boolean triggered = false; - try { - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject(); - builder = response.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - Map responseMap = XContentHelper.convertToMap(builder.bytes(), false).v2(); - - ScriptedAlertTrigger scriptTrigger = alert.trigger().scriptedTrigger(); - ExecutableScript executable = scriptService.executable( - scriptTrigger.scriptLang, scriptTrigger.script, scriptTrigger.scriptType, responseMap - ); - - Object returnValue = executable.run(); - logger.trace("Returned [{}] from script", returnValue); - if (returnValue instanceof Boolean) { - triggered = (Boolean) returnValue; - } else { - throw new ElasticsearchIllegalStateException("Trigger script [" + scriptTrigger.script + "] did not return a Boolean"); - } - } catch (Exception e ){ - logger.error("Failed to execute script trigger", e); - } - return new TriggerResult(triggered, request, response, alert.trigger()); - } - - private SearchRequest prepareTriggerSearch(Alert alert, DateTime scheduledFireTime, DateTime fireTime) throws IOException { - SearchRequest request = alert.getSearchRequest(); - if (Strings.hasLength(request.source())) { - String requestSource = XContentHelper.convertToJson(request.source(), false); - if (requestSource.contains(fireTimePlaceHolder)) { - requestSource = requestSource.replace(fireTimePlaceHolder, dateTimeFormatter.printer().print(fireTime)); - } - if (requestSource.contains(scheduledFireTimePlaceHolder)) { - requestSource = requestSource.replace(scheduledFireTimePlaceHolder, dateTimeFormatter.printer().print(scheduledFireTime)); - } - request.source(requestSource); - } else if (Strings.hasLength(request.templateSource())) { - Tuple> tuple = XContentHelper.convertToMap(request.templateSource(), false); - Map templateSourceAsMap = tuple.v2(); - Map templateObject = (Map) templateSourceAsMap.get("template"); - if (templateObject != null) { - Map params = (Map) templateObject.get("params"); - params.put("scheduled_fire_time", dateTimeFormatter.printer().print(scheduledFireTime)); - params.put("fire_time", dateTimeFormatter.printer().print(fireTime)); - - XContentBuilder builder = XContentFactory.contentBuilder(tuple.v1()); - builder.map(templateSourceAsMap); - request.templateSource(builder.bytes(), false); - } - } else if (request.templateName() != null) { - MapBuilder templateParams = MapBuilder.newMapBuilder(request.templateParams()) - .put("scheduled_fire_time", dateTimeFormatter.printer().print(scheduledFireTime)) - .put("fire_time", dateTimeFormatter.printer().print(fireTime)); - request.templateParams(templateParams.map()); - } else { - throw new ElasticsearchIllegalStateException("Search requests needs either source, template source or template name"); - } - return request; - } -} diff --git a/src/main/java/org/elasticsearch/alerts/triggers/TriggerResult.java b/src/main/java/org/elasticsearch/alerts/triggers/TriggerResult.java deleted file mode 100644 index f9069ec5387..00000000000 --- a/src/main/java/org/elasticsearch/alerts/triggers/TriggerResult.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.alerts.triggers; - -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; - -/** - */ -public class TriggerResult { - - private final boolean triggered; - private final SearchRequest request; - private final SearchResponse response; - private final AlertTrigger trigger; - - public TriggerResult(boolean triggered, SearchRequest request, SearchResponse response, AlertTrigger trigger) { - this.triggered = triggered; - this.request = request; - this.response = response; - this.trigger = trigger; - } - - public boolean isTriggered() { - return triggered; - } - - public SearchRequest getRequest() { - return request; - } - - public SearchResponse getResponse() { - return response; - } - - public AlertTrigger getTrigger() { - return trigger; - } - -} diff --git a/src/main/java/org/elasticsearch/alerts/triggers/package-info.java b/src/main/java/org/elasticsearch/alerts/triggers/package-info.java deleted file mode 100644 index e667ebe2c67..00000000000 --- a/src/main/java/org/elasticsearch/alerts/triggers/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.alerts.triggers; \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/alerts/BasicAlertingTest.java b/src/test/java/org/elasticsearch/alerts/BasicAlertingTest.java index 946b1f8cdc2..0bb560332b3 100644 --- a/src/test/java/org/elasticsearch/alerts/BasicAlertingTest.java +++ b/src/test/java/org/elasticsearch/alerts/BasicAlertingTest.java @@ -6,16 +6,25 @@ package org.elasticsearch.alerts; import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.alerts.actions.AlertAction; import org.elasticsearch.alerts.client.AlertsClientInterface; import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertRequest; import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertResponse; +import org.elasticsearch.alerts.triggers.ScriptedTrigger; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.joda.time.DateTime; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.junit.Test; +import java.util.ArrayList; + import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; /** diff --git a/src/test/java/org/elasticsearch/alerts/actions/AlertActionsTest.java b/src/test/java/org/elasticsearch/alerts/actions/AlertActionsTest.java index 1845edfacc2..f26612a02c1 100644 --- a/src/test/java/org/elasticsearch/alerts/actions/AlertActionsTest.java +++ b/src/test/java/org/elasticsearch/alerts/actions/AlertActionsTest.java @@ -22,7 +22,7 @@ import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertResponse; import org.elasticsearch.alerts.transport.actions.get.GetAlertRequest; import org.elasticsearch.alerts.transport.actions.get.GetAlertResponse; import org.elasticsearch.alerts.triggers.AlertTrigger; -import org.elasticsearch.alerts.triggers.ScriptedAlertTrigger; +import org.elasticsearch.alerts.triggers.ScriptedTrigger; import org.elasticsearch.alerts.triggers.TriggerResult; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; @@ -84,7 +84,12 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest { DateTime scheduledFireTime = new DateTime(DateTimeZone.UTC); Map triggerMap = new HashMap<>(); - triggerMap.put("numberOfEvents", ">1"); + Map scriptTriggerMap = new HashMap<>(); + scriptTriggerMap.put("script", "hits.total>1"); + scriptTriggerMap.put("script_lang", "groovy"); + triggerMap.put("script", scriptTriggerMap ); + + Map actionMap = new HashMap<>(); Map emailParamMap = new HashMap<>(); List addresses = new ArrayList<>(); @@ -113,9 +118,10 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest { builder.field(AlertActionManager.ACTIONS_FIELD, actionMap); builder.field(AlertActionState.FIELD_NAME, AlertActionState.SEARCH_NEEDED.toString()); builder.endObject(); - AlertActionRegistry alertActionRegistry = internalCluster().getInstance(AlertActionRegistry.class, internalCluster().getMasterName()); - AlertActionEntry actionEntry = AlertActionManager.parseHistory("foobar", builder.bytes(), 0, alertActionRegistry); + final AlertActionRegistry alertActionRegistry = internalCluster().getInstance(AlertActionRegistry.class, internalCluster().getMasterName()); + final AlertActionManager alertManager = internalCluster().getInstance(AlertActionManager.class, internalCluster().getMasterName()); + AlertActionEntry actionEntry = alertManager.parseHistory("foobar", builder.bytes(), 0, alertActionRegistry); assertEquals(actionEntry.getVersion(), 0); assertEquals(actionEntry.getAlertName(), "testName"); assertEquals(actionEntry.isTriggered(), true); @@ -123,9 +129,6 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest { assertEquals(actionEntry.getFireTime(), fireTime); assertEquals(actionEntry.getEntryState(), AlertActionState.SEARCH_NEEDED); assertEquals(actionEntry.getSearchResponse().getHits().getTotalHits(), 10); - assertEquals(actionEntry.getTrigger(), - new AlertTrigger(AlertTrigger.SimpleTrigger.GREATER_THAN, AlertTrigger.TriggerType.NUMBER_OF_EVENTS, 1)); - } @Test @@ -163,16 +166,6 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest { return builder; } - @Override - public void writeTo(StreamOutput out) throws IOException { - - } - - @Override - public void readFrom(StreamInput in) throws IOException { - - } - @Override public boolean doAction(Alert alert, TriggerResult actionEntry) { logger.info("Alert {} invoked: {}", alert.alertName(), actionEntry); @@ -187,13 +180,9 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest { parser.nextToken(); return alertAction; } - - @Override - public AlertAction readFrom(StreamInput in) throws IOException { - return alertAction; - } }); - AlertTrigger alertTrigger = new AlertTrigger(new ScriptedAlertTrigger("return true", ScriptService.ScriptType.INLINE, "groovy")); + + AlertTrigger alertTrigger = new ScriptedTrigger("return true", ScriptService.ScriptType.INLINE, "groovy"); Alert alert = new Alert(