Alerting transport layer.

This commit adds the transport layer to the alerting plugin.

Original commit: elastic/x-pack-elasticsearch@a99dce9411
This commit is contained in:
Brian Murphy 2014-11-04 15:01:25 +00:00
parent 669203b2a1
commit 75ce20ecff
37 changed files with 1444 additions and 11 deletions

View File

@ -7,15 +7,22 @@ package org.elasticsearch.alerts;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.alerts.actions.AlertAction;
import org.elasticsearch.alerts.actions.AlertActionFactory;
import org.elasticsearch.alerts.actions.AlertActionRegistry;
import org.elasticsearch.alerts.triggers.AlertTrigger;
import org.elasticsearch.common.io.stream.DataOutputStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.joda.time.DateTimeZone;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.omg.CORBA.portable.Streamable;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Alert implements ToXContent {
@ -72,6 +79,47 @@ public class Alert implements ToXContent {
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<numActions; ++i) {
actions.add(AlertActionRegistry.readFrom(in));
}
schedule = in.readOptionalString();
if (in.readBoolean()) {
lastActionFire = new DateTime(in.readLong(), DateTimeZone.UTC);
}
version = in.readLong();
enabled = in.readBoolean();
}
public void writeTo(StreamOutput out) throws IOException {
out.writeString(alertName);
searchRequest.writeTo(out);
AlertTrigger.writeTo(trigger, out);
if (actions == null) {
out.writeInt(0);
} else {
out.writeInt(actions.size());
for (AlertAction action : actions) {
action.writeTo(out);
}
}
out.writeOptionalString(schedule);
if (lastActionFire == null) {
out.writeBoolean(false);
} else {
out.writeLong(lastActionFire.toDateTime(DateTimeZone.UTC).getMillis());
}
out.writeLong(version);
out.writeBoolean(enabled);
}
/**
* @return The last time this alert ran.
*/

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.indices.IndicesService;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -40,6 +41,7 @@ public class AlertManager extends AbstractComponent {
private final AlertActionManager actionManager;
private final AtomicBoolean started = new AtomicBoolean(false);
@Inject
public AlertManager(Settings settings, ClusterService clusterService, AlertsStore alertsStore,
IndicesService indicesService, TriggerManager triggerManager, AlertActionManager actionManager) {
@ -92,6 +94,18 @@ public class AlertManager extends AbstractComponent {
return alert;
}
public Alert addAlert(Alert alert) {
ensureStarted();
try {
alertsStore.createAlert(alert);
} catch (IOException ioe) {
throw new ElasticsearchException("Failed to create alert [" + alert + "]", ioe);
}
scheduler.add(alert.alertName(), alert);
return alert;
}
public List<Alert> getAllAlerts() {
ensureStarted();
return ImmutableList.copyOf(alertsStore.getAlerts().values());
@ -136,6 +150,10 @@ public class AlertManager extends AbstractComponent {
}
}
public Alert getAlert(String alertName) {
return alertsStore.getAlert(alertName);
}
private final class AlertsClusterStateListener implements ClusterStateListener {
@Override

View File

@ -5,13 +5,17 @@
*/
package org.elasticsearch.alerts;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.elasticsearch.alerts.actions.AlertActionRegistry;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.rest.AlertRestHandler;
import org.elasticsearch.alerts.scheduler.AlertScheduler;
import org.elasticsearch.alerts.triggers.TriggerManager;
import org.elasticsearch.common.inject.AbstractModule;
public class AlertingModule extends AbstractModule {
@Override
@ -23,6 +27,8 @@ public class AlertingModule extends AbstractModule {
bind(AlertScheduler.class).asEagerSingleton();
bind(AlertActionRegistry.class).asEagerSingleton();
bind(AlertRestHandler.class).asEagerSingleton();
//bind(AlertsClientInterface.class).to(AlertsClient.class).asEagerSingleton();
bind(AlertsClient.class).asEagerSingleton();
}
}

View File

@ -25,6 +25,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.BytesStreamInput;
import org.elasticsearch.common.io.stream.DataOutputStreamOutput;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
@ -33,6 +34,8 @@ import org.elasticsearch.common.xcontent.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.threadpool.ThreadPool;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
@ -99,6 +102,25 @@ public class AlertsStore extends AbstractComponent {
return alert;
}
/**
* Creates an alert with the specified and fails if an alert with the name already exists.
*/
public Alert createAlert(Alert alert) throws IOException {
if (!client.admin().indices().prepareExists(ALERT_INDEX).execute().actionGet().isExists()) {
createAlertsIndex();
}
if (alertMap.putIfAbsent(alert.alertName(), alert) == null) {
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
alert.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
persistAlert(alert.alertName(), jsonBuilder.bytes(), IndexRequest.OpType.CREATE);
} else {
throw new ElasticsearchIllegalArgumentException("There is already an alert named [" + alert.alertName() + "]");
}
return alert;
}
/**
* Updates the specified alert by making sure that the made changes are persisted.
*/

View File

@ -6,6 +6,8 @@
package org.elasticsearch.alerts.actions;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -17,5 +19,10 @@ 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, AlertActionEntry actionEntry);
}

View File

@ -5,7 +5,9 @@
*/
package org.elasticsearch.alerts.actions;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.io.stream.StreamInput;
import java.io.IOException;
@ -13,4 +15,7 @@ public interface AlertActionFactory {
AlertAction createAction(XContentParser parser) throws IOException;
AlertAction readFrom(StreamInput in) throws IOException;
}

View File

@ -11,6 +11,8 @@ 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.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentParser;
@ -20,12 +22,12 @@ import java.util.List;
public class AlertActionRegistry extends AbstractComponent {
private volatile ImmutableOpenMap<String, AlertActionFactory> actionImplemented;
private static volatile ImmutableOpenMap<String, AlertActionFactory> actionImplemented;
@Inject
public AlertActionRegistry(Settings settings, Client client) {
super(settings);
this.actionImplemented = ImmutableOpenMap.<String, AlertActionFactory>builder()
actionImplemented = ImmutableOpenMap.<String, AlertActionFactory>builder()
.fPut("email", new EmailAlertActionFactory())
.fPut("index", new IndexAlertActionFactory(client))
.build();
@ -37,6 +39,7 @@ public class AlertActionRegistry extends AbstractComponent {
.build();
}
public List<AlertAction> instantiateAlertActions(XContentParser parser) throws IOException {
List<AlertAction> actions = new ArrayList<>();
ImmutableOpenMap<String, AlertActionFactory> actionImplemented = this.actionImplemented;
@ -53,7 +56,6 @@ public class AlertActionRegistry extends AbstractComponent {
throw new ElasticsearchIllegalArgumentException("No action exists with the name [" + actionFactoryName + "]");
}
}
}
return actions;
}
@ -64,4 +66,19 @@ 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 + "]");
}
}
}

View File

@ -7,6 +7,8 @@ package org.elasticsearch.alerts.actions;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import javax.mail.*;
@ -68,6 +70,30 @@ 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<numberOfEmails; ++i) {
String address = in.readString();
try {
emailAddresses.add(InternetAddress.parse(address)[0]);
} catch (AddressException ae) {
throw new IOException("Unable to parse [" + address + "] as an email adderss", ae);
}
}
}
@Override
public boolean doAction(Alert alert, AlertActionEntry result) {
Properties props = new Properties();

View File

@ -7,6 +7,7 @@ package org.elasticsearch.alerts.actions;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.io.stream.StreamInput;
import java.io.IOException;
import java.util.ArrayList;
@ -48,4 +49,20 @@ public class EmailAlertActionFactory implements AlertActionFactory {
}
return new EmailAlertAction(display, addresses.toArray(new String[addresses.size()]));
}
@Override
public AlertAction readFrom(StreamInput in) throws IOException{
String displayField = in.readOptionalString();
int numberOfEmails = in.readInt();
String[] emailAddresses = new String[numberOfEmails];
for (int i=0; i<numberOfEmails; ++i) {
String address = in.readString();
emailAddresses[i] = address;
}
EmailAlertAction emailAction = new EmailAlertAction(displayField, emailAddresses);
return emailAction;
}
}

View File

@ -9,6 +9,8 @@ import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.ToXContent;
@ -18,8 +20,8 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import java.io.IOException;
public class IndexAlertAction implements AlertAction, ToXContent {
private final String index;
private final String type;
private String index;
private String type;
private Client client = null;
ESLogger logger = Loggers.getLogger(IndexAlertAction.class);
@ -44,6 +46,18 @@ public class IndexAlertAction implements AlertAction, ToXContent {
return builder;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(index);
out.writeString(type);
}
@Override
public void readFrom(StreamInput in) throws IOException {
index = in.readString();
type = in.readString();
}
@Override
public boolean doAction(Alert alert, AlertActionEntry alertResult) {
IndexRequest indexRequest = new IndexRequest();

View File

@ -8,11 +8,10 @@ package org.elasticsearch.alerts.actions;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import org.elasticsearch.common.io.stream.StreamInput;
/**
* Created by brian on 8/17/14.
*/
public class IndexAlertActionFactory implements AlertActionFactory {
@ -49,4 +48,9 @@ public class IndexAlertActionFactory implements AlertActionFactory {
}
return new IndexAlertAction(index, type, client);
}
@Override
public AlertAction readFrom(StreamInput in) throws IOException {
return new IndexAlertAction(in.readString(), in.readString(), client);
}
}

View File

@ -41,4 +41,5 @@ public class AlertsPlugin extends AbstractPlugin {
.build();
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.transport.actions.create;
import org.elasticsearch.action.ClientAction;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientAction;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class CreateAlertAction extends AlertsClientAction<CreateAlertRequest, CreateAlertResponse, CreateAlertRequestBuilder> {
public static final CreateAlertAction INSTANCE = new CreateAlertAction();
public static final String NAME = "indices:data/write/alert/create";
private CreateAlertAction() {
super(NAME);
}
@Override
public CreateAlertRequestBuilder newRequestBuilder(AlertsClientInterface client) {
return new CreateAlertRequestBuilder(client);
}
@Override
public CreateAlertResponse newResponse() {
return new CreateAlertResponse();
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.transport.actions.create;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.triggers.AlertTrigger;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.unit.TimeValue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
*/
public class CreateAlertRequest extends MasterNodeOperationRequest<CreateAlertRequest> {
private Alert alert;
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (alert == null) {
validationException = ValidateActions.addValidationError("alert is missing", validationException);
}
return validationException;
}
CreateAlertRequest() {
}
public CreateAlertRequest(Alert alert) {
this.alert = alert;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
alert = new Alert();
alert.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
alert.writeTo(out);
}
public Alert alert() {
return alert;
}
public void Alert(Alert alert) {
this.alert = alert;
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.transport.actions.create;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class CreateAlertRequestBuilder
extends MasterNodeOperationRequestBuilder<CreateAlertRequest, CreateAlertResponse,
CreateAlertRequestBuilder, AlertsClientInterface> {
public CreateAlertRequestBuilder(AlertsClientInterface client) {
super(client, new CreateAlertRequest(null));
}
public CreateAlertRequestBuilder(AlertsClientInterface client, Alert alert) {
super(client, new CreateAlertRequest(alert));
}
@Override
protected void doExecute(ActionListener<CreateAlertResponse> listener) {
client.createAlert(request, listener);
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.transport.actions.create;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
/**
*/
public class CreateAlertResponse extends ActionResponse {
private boolean success;
public CreateAlertResponse(boolean success) {
this.success = success;
}
public CreateAlertResponse() {
this.success = success;
}
public boolean success() {
return success;
}
public void success(boolean success) {
this.success = success;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBoolean(success);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
success = in.readBoolean();
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.transport.actions.create;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.HandledTransportAction;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.actions.AlertAction;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.elasticsearch.alerts.triggers.TriggerManager;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.quartz.Trigger;
import java.util.ArrayList;
/**
*/
public class TransportCreateAlertAction extends TransportMasterNodeOperationAction<CreateAlertRequest, CreateAlertResponse> {
private final AlertManager alertManager;
@Inject
public TransportCreateAlertAction(Settings settings, String actionName, TransportService transportService,
ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters,
AlertManager alertManager) {
super(settings, actionName, transportService, clusterService, threadPool, actionFilters);
this.alertManager = alertManager;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected CreateAlertRequest newRequest() {
return new CreateAlertRequest();
}
@Override
protected CreateAlertResponse newResponse() {
return new CreateAlertResponse();
}
@Override
protected void masterOperation(CreateAlertRequest request, ClusterState state, ActionListener<CreateAlertResponse> listener) throws ElasticsearchException {
try {
alertManager.addAlert(request.alert());
listener.onResponse(new CreateAlertResponse(true));
} catch (Exception e) {
listener.onFailure(e);
}
}
@Override
protected ClusterBlockException checkBlock(CreateAlertRequest request, ClusterState state) {
if (!alertManager.isStarted()) {
return new ClusterBlockException(null);
}
return state.blocks().indicesBlockedException(ClusterBlockLevel.WRITE, new String[]{AlertsStore.ALERT_INDEX, AlertActionManager.ALERT_HISTORY_INDEX});
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.transport.actions.delete;
import org.elasticsearch.action.ClientAction;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientAction;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class DeleteAlertAction extends AlertsClientAction<DeleteAlertRequest, DeleteAlertResponse, DeleteAlertRequestBuilder> {
public static final DeleteAlertAction INSTANCE = new DeleteAlertAction();
public static final String NAME = "indices:data/write/alert/delete";
private DeleteAlertAction() {
super(NAME);
}
@Override
public DeleteAlertResponse newResponse() {
return new DeleteAlertResponse();
}
@Override
public DeleteAlertRequestBuilder newRequestBuilder(AlertsClientInterface client) {
return new DeleteAlertRequestBuilder(client);
}
}

View File

@ -0,0 +1,100 @@
/*
* 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.transport.actions.delete;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.script.ScriptService;
import java.io.IOException;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
*/
public class DeleteAlertRequest extends MasterNodeOperationRequest<DeleteAlertRequest> implements IndicesRequest {
private long version = Versions.MATCH_ANY;
private String alertName;
public DeleteAlertRequest() {
}
public DeleteAlertRequest(String alertName) {
this.alertName = alertName;
}
public void alertName(String alertName) {
this.alertName = alertName;
}
public String alertName() {
return alertName;
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (alertName == null){
validationException = ValidateActions.addValidationError("alertName is missing", validationException);
}
return validationException;
}
@Override
public String[] indices() {
return new String[]{AlertsStore.ALERT_INDEX};
}
@Override
public IndicesOptions indicesOptions() {
return IndicesOptions.strictSingleIndexNoExpandForbidClosed();
}
/**
* Sets the version, which will cause the delete operation to only be performed if a matching
* version exists and no changes happened on the doc since then.
*/
public DeleteAlertRequest version(long version) {
this.version = version;
return this;
}
public long version() {
return this.version;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
version = Versions.readVersion(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
Versions.writeVersion(version, out);
}
@Override
public String toString() {
return "delete {[" + AlertsStore.ALERT_INDEX + "][" + alertName + "]}";
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.transport.actions.delete;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.VersionType;
/**
* A delete document action request builder.
*/
public class DeleteAlertRequestBuilder
extends MasterNodeOperationRequestBuilder<DeleteAlertRequest, DeleteAlertResponse, DeleteAlertRequestBuilder, AlertsClientInterface> {
public DeleteAlertRequestBuilder(AlertsClientInterface client) {
super(client, new DeleteAlertRequest());
}
public DeleteAlertRequestBuilder(AlertsClientInterface client, String alertName) {
super(client, new DeleteAlertRequest(alertName));
}
public DeleteAlertRequestBuilder setAlertName(String alertName) {
this.request().alertName(alertName);
return this;
}
@Override
protected void doExecute(final ActionListener<DeleteAlertResponse> listener) {
client.deleteAlert(request, listener);
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.transport.actions.delete;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
/**
*/
public class DeleteAlertResponse extends ActionResponse {
boolean success;
public DeleteAlertResponse() {
success = false;
}
public DeleteAlertResponse(boolean success) {
this.success = true;
}
public boolean success() {
return success;
}
public void success(boolean success) {
this.success = success;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
success = in.readBoolean();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBoolean(success);
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.transport.actions.delete;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.indexedscripts.delete.DeleteIndexedScriptAction;
import org.elasticsearch.action.indexedscripts.delete.DeleteIndexedScriptRequest;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.DelegatingActionListener;
import org.elasticsearch.action.support.HandledTransportAction;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
/**
* Performs the delete operation.
*/
public class TransportDeleteAlertAction extends TransportMasterNodeOperationAction<DeleteAlertRequest, DeleteAlertResponse> {
private final AlertManager alertManager;
@Inject
public TransportDeleteAlertAction(Settings settings, String actionName, TransportService transportService,
ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters,
AlertManager alertManager) {
super(settings, actionName, transportService, clusterService, threadPool, actionFilters);
this.alertManager = alertManager;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected DeleteAlertRequest newRequest() {
return new DeleteAlertRequest();
}
@Override
protected DeleteAlertResponse newResponse() {
return new DeleteAlertResponse();
}
@Override
protected void masterOperation(DeleteAlertRequest request, ClusterState state, ActionListener<DeleteAlertResponse> listener) throws ElasticsearchException {
try {
boolean success = alertManager.deleteAlert(request.alertName());
listener.onResponse(new DeleteAlertResponse(success));
} catch (Exception e) {
listener.onFailure(e);
}
}
@Override
protected ClusterBlockException checkBlock(DeleteAlertRequest request, ClusterState state) {
if (!alertManager.isStarted()) {
return new ClusterBlockException(null);
}
return state.blocks().indicesBlockedException(ClusterBlockLevel.WRITE, new String[]{AlertsStore.ALERT_INDEX, AlertActionManager.ALERT_HISTORY_INDEX});
}
}

View File

@ -0,0 +1,10 @@
/*
* 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.
*/
/**
* Delete action.
*/
package org.elasticsearch.alerts.transport.actions.delete;

View File

@ -0,0 +1,34 @@
/*
* 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.transport.actions.get;
import org.elasticsearch.action.ClientAction;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientAction;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class GetAlertAction extends AlertsClientAction<GetAlertRequest, GetAlertResponse, GetAlertRequestBuilder> {
public static final GetAlertAction INSTANCE = new GetAlertAction();
public static final String NAME = "indices:data/read/alert/get";
private GetAlertAction() {
super(NAME);
}
@Override
public GetAlertResponse newResponse() {
return new GetAlertResponse();
}
@Override
public GetAlertRequestBuilder newRequestBuilder(AlertsClientInterface client) {
return new GetAlertRequestBuilder(client);
}
}

View File

@ -0,0 +1,113 @@
/*
* 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.transport.actions.get;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.index.VersionType;
import java.io.IOException;
/**
*/
public class GetAlertRequest extends MasterNodeOperationRequest<GetAlertRequest> implements IndicesRequest {
private String alertName;
private long version = Versions.MATCH_ANY;
private VersionType versionType = VersionType.INTERNAL;
public GetAlertRequest() {
}
public GetAlertRequest(String alertName) {
this.alertName = alertName;
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (alertName == null) {
validationException = ValidateActions.addValidationError("alertName is missing", validationException);
}
return validationException;
}
@Override
public String[] indices() {
return new String[]{AlertsStore.ALERT_INDEX};
}
@Override
public IndicesOptions indicesOptions() {
return IndicesOptions.strictSingleIndexNoExpandForbidClosed();
}
public String alertName() {
return alertName;
}
public GetAlertRequest alertName(String alertName){
this.alertName = alertName;
return this;
}
/**
* Sets the version, which will cause the delete operation to only be performed if a matching
* version exists and no changes happened on the doc since then.
*/
public GetAlertRequest version(long version) {
this.version = version;
return this;
}
public long version() {
return this.version;
}
public GetAlertRequest versionType(VersionType versionType) {
this.versionType = versionType;
return this;
}
public VersionType versionType() {
return this.versionType;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
version = Versions.readVersion(in);
versionType = VersionType.fromValue(in.readByte());
alertName = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
Versions.writeVersion(version, out);
out.writeByte(versionType.getValue());
out.writeString(alertName);
}
@Override
public String toString() {
return "delete {[" + AlertsStore.ALERT_INDEX + "][" + alertName +"]}";
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.transport.actions.get;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.VersionType;
/**
* A delete document action request builder.
*/
public class GetAlertRequestBuilder
extends MasterNodeOperationRequestBuilder<GetAlertRequest, GetAlertResponse, GetAlertRequestBuilder, AlertsClientInterface> {
public GetAlertRequestBuilder(AlertsClientInterface client, String alertName) {
super(client, new GetAlertRequest(alertName));
}
public GetAlertRequestBuilder(AlertsClientInterface client) {
super(client, new GetAlertRequest());
}
public GetAlertRequestBuilder setAlertName(String alertName) {
request.alertName(alertName);
return this;
}
/**
* Sets the type of versioning to use. Defaults to {@link org.elasticsearch.index.VersionType#INTERNAL}.
*/
public GetAlertRequestBuilder setVersionType(VersionType versionType) {
request.versionType(versionType);
return this;
}
@Override
protected void doExecute(final ActionListener<GetAlertResponse> listener) {
client.getAlert(request, listener);
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.transport.actions.get;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
/**
*/
public class GetAlertResponse extends ActionResponse {
boolean found = false;
Alert alert = null;
public GetAlertResponse() {
}
public boolean found() {
return this.found;
}
public void found(boolean found) {
this.found = found;
}
public Alert alert() {
return alert;
}
public void alert(Alert alert){
this.alert = alert;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
found = in.readBoolean();
if (found) {
alert = new Alert();
alert.readFrom(in);
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeBoolean(found);
if (found && alert != null){
alert.writeTo(out);
}
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.transport.actions.get;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertRequest;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertResponse;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
/**
* Performs the delete operation.
*/
public class TransportGetAlertAction extends TransportMasterNodeOperationAction<GetAlertRequest, GetAlertResponse> {
private final AlertManager alertManager;
@Inject
public TransportGetAlertAction(Settings settings, String actionName, TransportService transportService,
ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters,
AlertManager alertManager) {
super(settings, actionName, transportService, clusterService, threadPool, actionFilters);
this.alertManager = alertManager;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected GetAlertRequest newRequest() {
return new GetAlertRequest();
}
@Override
protected GetAlertResponse newResponse() {
return new GetAlertResponse();
}
@Override
protected void masterOperation(GetAlertRequest request, ClusterState state, ActionListener<GetAlertResponse> listener) throws ElasticsearchException {
try {
Alert alert = alertManager.getAlert(request.alertName());
GetAlertResponse response = new GetAlertResponse();
response.found(alert != null);
response.alert(alert);
listener.onResponse(response);
} catch (Exception e) {
listener.onFailure(e);
}
}
@Override
protected ClusterBlockException checkBlock(GetAlertRequest request, ClusterState state) {
if (!alertManager.isStarted()) {
return new ClusterBlockException(null);
}
return state.blocks().indicesBlockedException(ClusterBlockLevel.WRITE, new String[]{AlertsStore.ALERT_INDEX, AlertActionManager.ALERT_HISTORY_INDEX});
}
}

View File

@ -0,0 +1,10 @@
/*
* 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.
*/
/**
* Delete action.
*/
package org.elasticsearch.alerts.transport.actions.get;

View File

@ -0,0 +1,64 @@
/*
* 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.transport.actions.update;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
/**
*/
public class TransportUpdateAlertAction extends TransportMasterNodeOperationAction<UpdateAlertRequest, UpdateAlertResponse> {
private final AlertManager alertManager;
public TransportUpdateAlertAction(Settings settings, String actionName, TransportService transportService,
ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters,
AlertManager alertManager) {
super(settings, actionName, transportService, clusterService, threadPool, actionFilters);
this.alertManager = alertManager;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected UpdateAlertRequest newRequest() {
return new UpdateAlertRequest();
}
@Override
protected UpdateAlertResponse newResponse() {
return new UpdateAlertResponse();
}
@Override
protected void masterOperation(UpdateAlertRequest request, ClusterState state, ActionListener<UpdateAlertResponse> listener) throws ElasticsearchException {
}
@Override
protected ClusterBlockException checkBlock(UpdateAlertRequest request, ClusterState state) {
if (!alertManager.isStarted()) {
return new ClusterBlockException(null);
}
return state.blocks().indicesBlockedException(ClusterBlockLevel.WRITE, new String[]{AlertsStore.ALERT_INDEX, AlertActionManager.ALERT_HISTORY_INDEX});
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.transport.actions.update;
import org.elasticsearch.action.ClientAction;
import org.elasticsearch.alerts.client.AlertsClientAction;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class UpdateAlertAction extends AlertsClientAction<UpdateAlertRequest, UpdateAlertResponse, UpdateAlertRequestBuilder> {
public static final UpdateAlertAction INSTANCE = new UpdateAlertAction();
public static final String NAME = "indices:data/write/alert/update";
private UpdateAlertAction() {
super(NAME);
}
@Override
public UpdateAlertRequestBuilder newRequestBuilder(AlertsClientInterface client) {
return new UpdateAlertRequestBuilder(client);
}
@Override
public UpdateAlertResponse newResponse() {
return new UpdateAlertResponse();
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.transport.actions.update;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
/**
*/
public class UpdateAlertRequest extends MasterNodeOperationRequest<UpdateAlertRequest> {
private Alert alert;
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (alert == null) {
validationException = ValidateActions.addValidationError("alert is missing", validationException);
}
return validationException;
}
UpdateAlertRequest() {
}
public UpdateAlertRequest(Alert alert) {
this.alert = alert;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
alert = new Alert();
alert.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
alert.writeTo(out);
}
public Alert alert() {
return alert;
}
public void Alert(Alert alert) {
this.alert = alert;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.transport.actions.update;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.client.Client;
/**
*/
public class UpdateAlertRequestBuilder extends MasterNodeOperationRequestBuilder
<UpdateAlertRequest, UpdateAlertResponse, UpdateAlertRequestBuilder, AlertsClientInterface> {
public UpdateAlertRequestBuilder(AlertsClientInterface client) {
super(client, new UpdateAlertRequest());
}
public UpdateAlertRequestBuilder(AlertsClientInterface client, Alert alert) {
super(client, new UpdateAlertRequest(alert));
}
@Override
protected void doExecute(ActionListener<UpdateAlertResponse> listener) {
client.updateAlert(request, listener);
}
}

View File

@ -0,0 +1,13 @@
/*
* 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.transport.actions.update;
import org.elasticsearch.action.ActionResponse;
/**
*/
public class UpdateAlertResponse extends ActionResponse {
}

View File

@ -6,8 +6,11 @@
package org.elasticsearch.alerts.triggers;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.script.ScriptService;
import java.io.IOException;
@ -16,6 +19,7 @@ public class AlertTrigger implements ToXContent {
private SimpleTrigger trigger;
private TriggerType triggerType;
private int value;
private ScriptedAlertTrigger scriptedTrigger;
public ScriptedAlertTrigger scriptedTrigger() {
return scriptedTrigger;
@ -25,8 +29,6 @@ public class AlertTrigger implements ToXContent {
this.scriptedTrigger = scriptedTrigger;
}
private ScriptedAlertTrigger scriptedTrigger;
public SimpleTrigger trigger() {
return trigger;
}
@ -193,4 +195,33 @@ public class AlertTrigger implements ToXContent {
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);
}
}
}

View File

@ -10,6 +10,8 @@ import org.elasticsearch.alerts.actions.*;
import org.elasticsearch.alerts.plugin.AlertsPlugin;
import org.elasticsearch.alerts.triggers.AlertTrigger;
import org.elasticsearch.alerts.triggers.ScriptedAlertTrigger;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -74,6 +76,16 @@ public class BasicAlertingTest 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, AlertActionEntry actionEntry) {
logger.info("Alert {} invoked: {}", alert.alertName(), actionEntry);
@ -88,6 +100,11 @@ public class BasicAlertingTest 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"));
Alert alert = new Alert(

View File

@ -5,9 +5,18 @@
*/
package org.elasticsearch.alerts.actions;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.alerts.AlertManager;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.BasicAlertingTest;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.client.AlertsClientInterface;
import org.elasticsearch.alerts.plugin.AlertsPlugin;
import org.elasticsearch.alerts.transport.actions.create.CreateAlertRequest;
import org.elasticsearch.alerts.transport.actions.create.CreateAlertResponse;
import org.elasticsearch.alerts.triggers.AlertTrigger;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
@ -18,6 +27,9 @@ import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.search.internal.InternalSearchHit;
import org.elasticsearch.search.internal.InternalSearchHits;
import org.elasticsearch.search.internal.InternalSearchResponse;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.junit.Test;
@ -25,6 +37,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -33,12 +49,29 @@ 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;
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return ImmutableSettings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put("plugin.mandatory", "alerts")
.put("plugin.types", AlertsPlugin.class.getName())
.put("node.mode", "network")
.put("plugins.load_classpath_plugins", false)
.build();
}
@Test
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<>();
@ -83,4 +116,37 @@ public class AlertActionsTest extends ElasticsearchIntegrationTest {
new AlertTrigger(AlertTrigger.SimpleTrigger.GREATER_THAN, AlertTrigger.TriggerType.NUMBER_OF_EVENTS, 1));
}
@Test
public void testCreateAlert() throws Exception {
createIndex("my-index");
createIndex(AlertsStore.ALERT_INDEX);
createIndex(AlertActionManager.ALERT_HISTORY_INDEX);
ensureGreen("my-index", AlertsStore.ALERT_INDEX, AlertActionManager.ALERT_HISTORY_INDEX);
client().preparePutIndexedScript()
.setScriptLang("mustache")
.setId("query")
.setSource(jsonBuilder().startObject().startObject("template").startObject("match_all").endObject().endObject().endObject())
.get();
CreateAlertRequest alertRequest = new CreateAlertRequest("myAlert");
alertRequest.queryName("test-query");
alertRequest.enabled(true);
alertRequest.schedule("0/5 * * * * ? *");
alertRequest.trigger(new AlertTrigger(AlertTrigger.SimpleTrigger.GREATER_THAN, AlertTrigger.TriggerType.NUMBER_OF_EVENTS, 1));
alertRequest.timePeriod(new TimeValue(300, TimeUnit.SECONDS));
alertRequest.actions(new ArrayList<String>());
alertRequest.lastRan(new DateTime());
alertRequest.lastActionFire(new DateTime());
alertRequest.running(new DateTime());
AlertsClientInterface alertsClient = internalCluster().getInstance(AlertsClient.class, internalCluster().getMasterName());
CreateAlertResponse alertsResponse = alertsClient.createAlert(alertRequest).actionGet();
assertTrue(alertsResponse.success());
}
}