Change project name to elasticsearch-watcher

- `alerts` package is now `watcher` package
- we no longer use the term `Alert`, but instead we use `Watch`
- documentation still needs to be updated

Original commit: elastic/x-pack-elasticsearch@1225edf7e3
This commit is contained in:
uboness 2015-03-24 13:06:06 +01:00
parent a6bdbf0b0b
commit 41832b6f5b
252 changed files with 4485 additions and 4498 deletions

View File

@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-alerts</artifactId>
<artifactId>elasticsearch-watcher</artifactId>
<version>1.0.0-beta2-SNAPSHOT</version>
<parent>

View File

@ -1,57 +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;
import org.elasticsearch.alerts.actions.ActionModule;
import org.elasticsearch.alerts.client.AlertsClientModule;
import org.elasticsearch.alerts.condition.ConditionModule;
import org.elasticsearch.alerts.history.HistoryModule;
import org.elasticsearch.alerts.input.InputModule;
import org.elasticsearch.alerts.rest.AlertsRestModule;
import org.elasticsearch.alerts.scheduler.SchedulerModule;
import org.elasticsearch.alerts.support.TemplateUtils;
import org.elasticsearch.alerts.support.clock.ClockModule;
import org.elasticsearch.alerts.support.init.InitializingModule;
import org.elasticsearch.alerts.support.template.TemplateModule;
import org.elasticsearch.alerts.transform.TransformModule;
import org.elasticsearch.alerts.transport.AlertsTransportModule;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.SpawnModules;
public class AlertsModule extends AbstractModule implements SpawnModules {
@Override
public Iterable<? extends Module> spawnModules() {
return ImmutableList.of(
new InitializingModule(),
new TemplateModule(),
new ClockModule(),
new AlertsClientModule(),
new TransformModule(),
new AlertsRestModule(),
new SchedulerModule(),
new AlertsTransportModule(),
new ConditionModule(),
new InputModule(),
new ActionModule(),
new HistoryModule());
}
@Override
protected void configure() {
bind(Alert.Parser.class).asEagerSingleton();
bind(AlertLockService.class).asEagerSingleton();
bind(AlertsLifeCycleService.class).asEagerSingleton();
bind(AlertsService.class).asEagerSingleton();
bind(AlertsStore.class).asEagerSingleton();
bind(TemplateUtils.class).asEagerSingleton();
}
}

View File

@ -1,253 +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.client;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertAction;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertRequest;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertRequestBuilder;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertResponse;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertAction;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertRequest;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertRequestBuilder;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertResponse;
import org.elasticsearch.alerts.transport.actions.get.GetAlertAction;
import org.elasticsearch.alerts.transport.actions.get.GetAlertRequest;
import org.elasticsearch.alerts.transport.actions.get.GetAlertRequestBuilder;
import org.elasticsearch.alerts.transport.actions.get.GetAlertResponse;
import org.elasticsearch.alerts.transport.actions.put.PutAlertAction;
import org.elasticsearch.alerts.transport.actions.put.PutAlertRequest;
import org.elasticsearch.alerts.transport.actions.put.PutAlertRequestBuilder;
import org.elasticsearch.alerts.transport.actions.put.PutAlertResponse;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceAction;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceRequest;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceRequestBuilder;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceResponse;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsAction;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsRequest;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsRequestBuilder;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
/**
*/
public class AlertsClient {
private final Client client;
@Inject
public AlertsClient(Client client) {
this.client = client;
}
/**
* Creates a request builder that gets an alert by name (id)
*
* @param alertName the name (id) of the alert
* @return The request builder
*/
public GetAlertRequestBuilder prepareGetAlert(String alertName) {
return new GetAlertRequestBuilder(client, alertName);
}
/**
* Creates a request builder that gets an alert
*
* @return the request builder
*/
public GetAlertRequestBuilder prepareGetAlert() {
return new GetAlertRequestBuilder(client);
}
/**
* Gets an alert from the alert index
*
* @param request The get alert request
* @param listener The listener for the get alert response containing the GetResponse for this alert
*/
public void getAlert(GetAlertRequest request, ActionListener<GetAlertResponse> listener) {
client.execute(GetAlertAction.INSTANCE, request, listener);
}
/**
* Gets an alert from the alert index
*
* @param request The get alert request with the alert name (id)
* @return The response containing the GetResponse for this alert
*/
public ActionFuture<GetAlertResponse> getAlert(GetAlertRequest request) {
return client.execute(GetAlertAction.INSTANCE, request);
}
/**
* Creates a request builder to delete an alert by name (id)
*
* @param alertName the name (id) of the alert
* @return The request builder
*/
public DeleteAlertRequestBuilder prepareDeleteAlert(String alertName) {
return new DeleteAlertRequestBuilder(client, alertName);
}
/**
* Creates a request builder that deletes an alert
*
* @return The request builder
*/
public DeleteAlertRequestBuilder prepareDeleteAlert() {
return new DeleteAlertRequestBuilder(client);
}
/**
* Deletes an alert
*
* @param request The delete request with the alert name (id) to be deleted
* @param listener The listener for the delete alert response containing the DeleteResponse for this action
*/
public void deleteAlert(DeleteAlertRequest request, ActionListener<DeleteAlertResponse> listener) {
client.execute(DeleteAlertAction.INSTANCE, request, listener);
}
/**
* Deletes an alert
*
* @param request The delete request with the alert name (id) to be deleted
* @return The response containing the DeleteResponse for this action
*/
public ActionFuture<DeleteAlertResponse> deleteAlert(DeleteAlertRequest request) {
return client.execute(DeleteAlertAction.INSTANCE, request);
}
/**
* Creates a request builder to build a request to put an alert
*
* @param alertName The name of the alert to put
* @return The builder to create the alert
*/
public PutAlertRequestBuilder preparePutAlert(String alertName) {
return new PutAlertRequestBuilder(client, alertName);
}
/**
* Creates a request builder to build a request to put an alert
*
* @return The builder
*/
public PutAlertRequestBuilder preparePutAlert() {
return new PutAlertRequestBuilder(client);
}
/**
* Put an alert and registers it with the scheduler
*
* @param request The request containing the alert to index and register
* @param listener The listener for the response containing the IndexResponse for this alert
*/
public void putAlert(PutAlertRequest request, ActionListener<PutAlertResponse> listener) {
client.execute(PutAlertAction.INSTANCE, request, listener);
}
/**
* Put an alert and registers it with the scheduler
*
* @param request The request containing the alert to index and register
* @return The response containing the IndexResponse for this alert
*/
public ActionFuture<PutAlertResponse> putAlert(PutAlertRequest request) {
return client.execute(PutAlertAction.INSTANCE, request);
}
/**
* Gets the alert stats
*
* @param request The request for the alert stats
* @return The response containing the StatsResponse for this action
*/
public ActionFuture<AlertsStatsResponse> alertsStats(AlertsStatsRequest request) {
return client.execute(AlertsStatsAction.INSTANCE, request);
}
/**
* Creates a request builder to build a request to get the alerts stats
*
* @return The builder get the alerts stats
*/
public AlertsStatsRequestBuilder prepareAlertsStats() {
return new AlertsStatsRequestBuilder(client);
}
/**
* Gets the alert stats
*
* @param request The request for the alert stats
* @param listener The listener for the response containing the AlertsStatsResponse
*/
public void alertsStats(AlertsStatsRequest request, ActionListener<AlertsStatsResponse> listener) {
client.execute(AlertsStatsAction.INSTANCE, request, listener);
}
/**
* Creates a request builder to ack an alert by name (id)
*
* @param alertName the name (id) of the alert
* @return The request builder
*/
public AckAlertRequestBuilder prepareAckAlert(String alertName) {
return new AckAlertRequestBuilder(client, alertName);
}
/**
* Creates a request builder that acks an alert
*
* @return The request builder
*/
public AckAlertRequestBuilder prepareAckAlert() {
return new AckAlertRequestBuilder(client);
}
/**
* Ack an alert
*
* @param request The ack request with the alert name (id) to be acked
* @param listener The listener for the ack alert response
*/
public void ackAlert(AckAlertRequest request, ActionListener<AckAlertResponse> listener) {
client.execute(AckAlertAction.INSTANCE, request, listener);
}
/**
* Acks an alert
*
* @param request The ack request with the alert name (id) to be acked
* @return The AckAlertResponse
*/
public ActionFuture<AckAlertResponse> ackAlert(AckAlertRequest request) {
return client.execute(AckAlertAction.INSTANCE, request);
}
/**
* Prepare make an alert service request.
*/
public AlertsServiceRequestBuilder prepareAlertService() {
return new AlertsServiceRequestBuilder(client);
}
/**
* Perform an alert service request to either start, stop or restart the alerting plugin.
*/
public void alertService(AlertsServiceRequest request, ActionListener<AlertsServiceResponse> listener) {
client.execute(AlertsServiceAction.INSTANCE, request, listener);
}
/**
* Perform an alert service request to either start, stop or restart the alerting plugin.
*/
public ActionFuture<AlertsServiceResponse> alertService(AlertsServiceRequest request) {
return client.execute(AlertsServiceAction.INSTANCE, request);
}
}

View File

@ -1,189 +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.history;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.alerts.support.TemplateUtils;
import org.elasticsearch.alerts.support.init.proxy.ClientProxy;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.joda.time.format.DateTimeFormat;
import org.elasticsearch.common.joda.time.format.DateTimeFormatter;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
*/
public class HistoryStore extends AbstractComponent {
public static final String ALERT_HISTORY_INDEX_PREFIX = ".alert_history_";
public static final String ALERT_HISTORY_TYPE = "fired_alert";
static final DateTimeFormatter alertHistoryIndexTimeFormat = DateTimeFormat.forPattern("YYYY-MM-dd");
private final ClientProxy client;
private final TemplateUtils templateUtils;
private final int scrollSize;
private final TimeValue scrollTimeout;
private final FiredAlert.Parser alertRecordParser;
@Inject
public HistoryStore(Settings settings, ClientProxy client, TemplateUtils templateUtils, FiredAlert.Parser alertRecordParser) {
super(settings);
this.client = client;
this.templateUtils = templateUtils;
this.alertRecordParser = alertRecordParser;
this.scrollTimeout = settings.getAsTime("alerts.scroll.timeout", TimeValue.timeValueSeconds(30));
this.scrollSize = settings.getAsInt("alerts.scroll.size", 100);
}
public void put(FiredAlert firedAlert) throws HistoryException {
String alertHistoryIndex = getAlertHistoryIndexNameForTime(firedAlert.scheduledTime());
try {
IndexResponse response = client.prepareIndex(alertHistoryIndex, ALERT_HISTORY_TYPE, firedAlert.id())
.setSource(XContentFactory.jsonBuilder().value(firedAlert))
.setOpType(IndexRequest.OpType.CREATE)
.get();
firedAlert.version(response.getVersion());
} catch (IOException e) {
throw new HistoryException("persisting new fired alert [" + firedAlert + "] failed", e);
}
}
public void update(FiredAlert firedAlert) throws HistoryException {
logger.debug("updating fired alert [{}]", firedAlert);
try {
BytesReference bytes = XContentFactory.jsonBuilder().value(firedAlert).bytes();
IndexResponse response = client.prepareIndex(getAlertHistoryIndexNameForTime(firedAlert.scheduledTime()), ALERT_HISTORY_TYPE, firedAlert.id())
.setSource(bytes)
.setVersion(firedAlert.version())
.get();
firedAlert.version(response.getVersion());
logger.debug("updated fired alert [{}]", firedAlert);
} catch (IOException e) {
throw new HistoryException("persisting fired alert [" + firedAlert + "] failed", e);
}
}
public LoadResult loadFiredAlerts(ClusterState state, FiredAlert.State firedAlertState) {
String[] indices = state.metaData().concreteIndices(IndicesOptions.lenientExpandOpen(), ALERT_HISTORY_INDEX_PREFIX + "*");
if (indices.length == 0) {
logger.debug("No .alert_history indices found, skip loading of alert actions");
templateUtils.ensureIndexTemplateIsLoaded(state, "alerthistory");
return new LoadResult(true);
}
int numPrimaryShards = 0;
for (String index : indices) {
IndexMetaData indexMetaData = state.getMetaData().index(index);
if (indexMetaData != null) {
if (!state.routingTable().index(index).allPrimaryShardsActive()) {
logger.debug("Not all primary shards of the [{}] index are started. Schedule to retry alert action loading..", index);
return new LoadResult(false);
} else {
numPrimaryShards += indexMetaData.numberOfShards();
}
}
}
RefreshResponse refreshResponse = client.refresh(new RefreshRequest(ALERT_HISTORY_INDEX_PREFIX + "*"));
if (refreshResponse.getSuccessfulShards() < numPrimaryShards) {
return new LoadResult(false);
}
SearchRequest searchRequest = createScanSearchRequest(firedAlertState);
SearchResponse response = client.search(searchRequest);
List<FiredAlert> alerts = new ArrayList<>();
try {
if (response.getTotalShards() != response.getSuccessfulShards()) {
return new LoadResult(false);
}
if (response.getHits().getTotalHits() > 0) {
response = client.searchScroll(response.getScrollId(), scrollTimeout);
while (response.getHits().hits().length != 0) {
for (SearchHit sh : response.getHits()) {
String historyId = sh.getId();
FiredAlert historyEntry = alertRecordParser.parse(sh.getSourceRef(), historyId, sh.version());
assert historyEntry.state() == FiredAlert.State.AWAITS_EXECUTION;
logger.debug("loaded fired alert from index [{}/{}/{}]", sh.index(), sh.type(), sh.id());
alerts.add(historyEntry);
}
response = client.searchScroll(response.getScrollId(), scrollTimeout);
}
}
} finally {
client.clearScroll(response.getScrollId());
}
templateUtils.ensureIndexTemplateIsLoaded(state, "alerthistory");
return new LoadResult(true, alerts);
}
/**
* Calculates the correct alert history index name for a given time using alertHistoryIndexTimeFormat
*/
public static String getAlertHistoryIndexNameForTime(DateTime time) {
return ALERT_HISTORY_INDEX_PREFIX + alertHistoryIndexTimeFormat.print(time);
}
private SearchRequest createScanSearchRequest(FiredAlert.State firedAlertState) {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.termQuery(FiredAlert.Parser.STATE_FIELD.getPreferredName(), firedAlertState.id()))
.size(scrollSize)
.version(true);
SearchRequest searchRequest = new SearchRequest(ALERT_HISTORY_INDEX_PREFIX + "*");
searchRequest.source(sourceBuilder);
searchRequest.searchType(SearchType.SCAN);
searchRequest.types(ALERT_HISTORY_TYPE);
searchRequest.scroll(scrollTimeout);
searchRequest.preference("_primary");
return searchRequest;
}
public class LoadResult implements Iterable<FiredAlert> {
private final boolean succeeded;
private final List<FiredAlert> alerts;
public LoadResult(boolean succeeded, List<FiredAlert> alerts) {
this.succeeded = succeeded;
this.alerts = alerts;
}
public LoadResult(boolean succeeded) {
this.succeeded = succeeded;
this.alerts = Collections.emptyList();
}
@Override
public Iterator<FiredAlert> iterator() {
return alerts.iterator();
}
public boolean succeeded() {
return succeeded;
}
}
}

View File

@ -1,50 +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.rest.action;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertRequest;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
/**
* The rest action to ack an alert
*/
public class RestAckAlertAction extends BaseRestHandler {
private final AlertsClient alertsClient;
@Inject
protected RestAckAlertAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(RestRequest.Method.PUT, AlertsStore.ALERT_INDEX + "/alert/{name}/_ack", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel restChannel, Client client) throws Exception {
final AckAlertRequest ackAlertRequest = new AckAlertRequest();
ackAlertRequest.setAlertName(request.param("name"));
alertsClient.ackAlert(ackAlertRequest, new RestBuilderListener<AckAlertResponse>(restChannel) {
@Override
public RestResponse buildResponse(AckAlertResponse ackAlertResponse, XContentBuilder builder) throws Exception {
builder.startObject();
builder.field(Alert.Parser.STATUS_FIELD.getPreferredName(), ackAlertResponse.getStatus().toString());
builder.endObject();
return new BytesRestResponse(RestStatus.OK, builder);
}
});
}
}

View File

@ -1,70 +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.rest.action;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceRequest;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
/**
*/
public class RestAlertServiceAction extends BaseRestHandler {
private final AlertsClient alertsClient;
@Inject
protected RestAlertServiceAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(RestRequest.Method.PUT, AlertsStore.ALERT_INDEX + "/_restart", this);
controller.registerHandler(RestRequest.Method.PUT, AlertsStore.ALERT_INDEX + "/_start", new StartRestHandler(settings, controller, client));
controller.registerHandler(RestRequest.Method.PUT, AlertsStore.ALERT_INDEX + "/_stop", new StopRestHandler(settings, controller, client));
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
AlertsServiceRequest serviceRequest = new AlertsServiceRequest();
serviceRequest.restart();
alertsClient.alertService(serviceRequest, new AcknowledgedRestListener<AlertsServiceResponse>(channel));
}
final class StartRestHandler extends BaseRestHandler {
public StartRestHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
}
@Override
public void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
AlertsServiceRequest serviceRequest = new AlertsServiceRequest();
serviceRequest.start();
alertsClient.alertService(serviceRequest, new AcknowledgedRestListener<AlertsServiceResponse>(channel));
}
}
final class StopRestHandler extends BaseRestHandler {
public StopRestHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
}
@Override
public void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
AlertsServiceRequest serviceRequest = new AlertsServiceRequest();
serviceRequest.stop();
alertsClient.alertService(serviceRequest, new AcknowledgedRestListener<AlertsServiceResponse>(channel));
}
}
}

View File

@ -1,63 +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.rest.action;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsRequest;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import java.util.Locale;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK;
/**
* The RestAction for alerts stats
*/
public class RestAlertsStatsAction extends BaseRestHandler {
private final AlertsClient alertsClient;
@Inject
protected RestAlertsStatsAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(GET, AlertsStore.ALERT_INDEX + "/alert/_stats", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel restChannel, Client client) throws Exception {
AlertsStatsRequest statsRequest = new AlertsStatsRequest();
alertsClient.alertsStats(statsRequest, new RestBuilderListener<AlertsStatsResponse>(restChannel) {
@Override
public RestResponse buildResponse(AlertsStatsResponse alertsStatsResponse, XContentBuilder builder) throws Exception {
builder.startObject()
.field("alert_manager_state", alertsStatsResponse.getAlertManagerStarted().toString().toLowerCase(Locale.ENGLISH))
.field("alert_action_manager_started", alertsStatsResponse.isAlertActionManagerStarted())
.field("alert_action_queue_size", alertsStatsResponse.getAlertActionManagerQueueSize())
.field("number_of_alerts", alertsStatsResponse.getNumberOfRegisteredAlerts())
.field("alert_action_queue_max_size", alertsStatsResponse.getAlertActionManagerLargestQueueSize());
builder.startObject("version")
.field("number", alertsStatsResponse.getVersion().number())
.field("build_hash", alertsStatsResponse.getBuild().hash())
.field("build_timestamp", alertsStatsResponse.getBuild().timestamp())
.field("build_snapshot", alertsStatsResponse.getVersion().snapshot)
.endObject();
return new BytesRestResponse(OK, builder);
}
});
}
}

View File

@ -1,63 +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.rest.action;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.get.GetAlertRequest;
import org.elasticsearch.alerts.transport.actions.get.GetAlertResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
import static org.elasticsearch.rest.RestStatus.OK;
/**
* The rest action to get an alert
*/
public class RestGetAlertAction extends BaseRestHandler {
private final AlertsClient alertsClient;
@Inject
public RestGetAlertAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(GET, AlertsStore.ALERT_INDEX + "/alert/{name}", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
final GetAlertRequest getAlertRequest = new GetAlertRequest();
getAlertRequest.alertName(request.param("name"));
alertsClient.getAlert(getAlertRequest, new RestBuilderListener<GetAlertResponse>(channel) {
@Override
public RestResponse buildResponse(GetAlertResponse result, XContentBuilder builder) throws Exception {
GetResponse getResponse = result.getResponse();
builder.startObject()
.field("found", getResponse.isExists())
.field("_index", getResponse.getIndex())
.field("_type", getResponse.getType())
.field("_id", getResponse.getId())
.field("_version", getResponse.getVersion())
.field("alert", getResponse.getSource())
.endObject();
RestStatus status = OK;
if (!getResponse.isExists()) {
status = NOT_FOUND;
}
return new BytesRestResponse(status, builder);
}
});
}
}

View File

@ -1,63 +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.rest.action;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.put.PutAlertRequest;
import org.elasticsearch.alerts.transport.actions.put.PutAlertResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT;
import static org.elasticsearch.rest.RestStatus.CREATED;
import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestPutAlertAction extends BaseRestHandler {
private final AlertsClient alertsClient;
@Inject
public RestPutAlertAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(POST, AlertsStore.ALERT_INDEX + "/alert/{name}", this);
controller.registerHandler(PUT, AlertsStore.ALERT_INDEX + "/alert/{name}", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
PutAlertRequest putAlertRequest = new PutAlertRequest();
putAlertRequest.setAlertName(request.param("name"));
putAlertRequest.source(request.content(), request.contentUnsafe());
alertsClient.putAlert(putAlertRequest, new RestBuilderListener<PutAlertResponse>(channel) {
@Override
public RestResponse buildResponse(PutAlertResponse response, XContentBuilder builder) throws Exception {
IndexResponse indexResponse = response.indexResponse();
builder.startObject()
.field("_index", indexResponse.getIndex())
.field("_type", indexResponse.getType())
.field("_id", indexResponse.getId())
.field("_version", indexResponse.getVersion())
.field("created", indexResponse.isCreated());
builder.endObject();
RestStatus status = OK;
if (indexResponse.isCreated()) {
status = CREATED;
}
return new BytesRestResponse(status, builder);
}
});
}
}

View File

@ -1,24 +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.throttle;
import org.elasticsearch.alerts.ExecutionContext;
import static org.elasticsearch.alerts.support.AlertsDateUtils.formatDate;
/**
*
*/
public class AckThrottler implements Throttler {
@Override
public Result throttle(ExecutionContext ctx) {
if (ctx.alert().acked()) {
return Result.throttle("alert [" + ctx.alert().name() + "] was acked at [" + formatDate(ctx.alert().status().ackStatus().timestamp()) + "]");
}
return Result.NO;
}
}

View File

@ -1,47 +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.transport;
import org.elasticsearch.action.ActionModule;
import org.elasticsearch.alerts.transport.actions.ack.AckAlertAction;
import org.elasticsearch.alerts.transport.actions.ack.TransportAckAlertAction;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertAction;
import org.elasticsearch.alerts.transport.actions.delete.TransportDeleteAlertAction;
import org.elasticsearch.alerts.transport.actions.get.GetAlertAction;
import org.elasticsearch.alerts.transport.actions.get.TransportGetAlertAction;
import org.elasticsearch.alerts.transport.actions.put.PutAlertAction;
import org.elasticsearch.alerts.transport.actions.put.TransportPutAlertAction;
import org.elasticsearch.alerts.transport.actions.service.AlertsServiceAction;
import org.elasticsearch.alerts.transport.actions.service.TransportAlertsServiceAction;
import org.elasticsearch.alerts.transport.actions.stats.AlertsStatsAction;
import org.elasticsearch.alerts.transport.actions.stats.TransportAlertsStatsAction;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
/**
*
*/
public class AlertsTransportModule extends AbstractModule implements PreProcessModule {
@Override
public void processModule(Module module) {
if (module instanceof ActionModule) {
ActionModule actionModule = (ActionModule) module;
actionModule.registerAction(PutAlertAction.INSTANCE, TransportPutAlertAction.class);
actionModule.registerAction(DeleteAlertAction.INSTANCE, TransportDeleteAlertAction.class);
actionModule.registerAction(GetAlertAction.INSTANCE, TransportGetAlertAction.class);
actionModule.registerAction(AlertsStatsAction.INSTANCE, TransportAlertsStatsAction.class);
actionModule.registerAction(AckAlertAction.INSTANCE, TransportAckAlertAction.class);
actionModule.registerAction(AlertsServiceAction.INSTANCE, TransportAlertsServiceAction.class);
}
}
@Override
protected void configure() {
}
}

View File

@ -1,33 +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.transport.actions.ack;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
* This action acks an alert in memory, and the index
*/
public class AckAlertAction extends AlertsAction<AckAlertRequest, AckAlertResponse, AckAlertRequestBuilder> {
public static final AckAlertAction INSTANCE = new AckAlertAction();
public static final String NAME = "indices:data/write/alert/ack";
private AckAlertAction() {
super(NAME);
}
@Override
public AckAlertResponse newResponse() {
return new AckAlertResponse();
}
@Override
public AckAlertRequestBuilder newRequestBuilder(Client client) {
return new AckAlertRequestBuilder(client);
}
}

View File

@ -1,39 +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.transport.actions.ack;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.client.Client;
/**
* A ack alert action request builder.
*/
public class AckAlertRequestBuilder extends MasterNodeOperationRequestBuilder<AckAlertRequest, AckAlertResponse, AckAlertRequestBuilder, Client> {
public AckAlertRequestBuilder(Client client) {
super(client, new AckAlertRequest());
}
public AckAlertRequestBuilder(Client client, String alertName) {
super(client, new AckAlertRequest(alertName));
}
/**
* Sets the name of the alert to be ack
*/
public AckAlertRequestBuilder setAlertName(String alertName) {
this.request().setAlertName(alertName);
return this;
}
@Override
protected void doExecute(final ActionListener<AckAlertResponse> listener) {
new AlertsClient(client).ackAlert(request, listener);
}
}

View File

@ -1,32 +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.transport.actions.delete;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
* This action deletes an alert from in memory, the scheduler and the index
*/
public class DeleteAlertAction extends AlertsAction<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(Client client) {
return new DeleteAlertRequestBuilder(client);
}
}

View File

@ -1,39 +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.transport.actions.delete;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.client.Client;
/**
* A delete document action request builder.
*/
public class DeleteAlertRequestBuilder extends MasterNodeOperationRequestBuilder<DeleteAlertRequest, DeleteAlertResponse, DeleteAlertRequestBuilder, Client> {
public DeleteAlertRequestBuilder(Client client) {
super(client, new DeleteAlertRequest());
}
public DeleteAlertRequestBuilder(Client client, String alertName) {
super(client, new DeleteAlertRequest(alertName));
}
/**
* Sets the name of the alert to be deleted
*/
public DeleteAlertRequestBuilder setAlertName(String alertName) {
this.request().setAlertName(alertName);
return this;
}
@Override
protected void doExecute(final ActionListener<DeleteAlertResponse> listener) {
new AlertsClient(client).deleteAlert(request, listener);
}
}

View File

@ -1,32 +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.transport.actions.get;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
* This action gets an alert by name
*/
public class GetAlertAction extends AlertsAction<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(Client client) {
return new GetAlertRequestBuilder(client);
}
}

View File

@ -1,32 +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.transport.actions.put;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
* This action puts an alert into the alert index and adds it to the scheduler
*/
public class PutAlertAction extends AlertsAction<PutAlertRequest, PutAlertResponse, PutAlertRequestBuilder> {
public static final PutAlertAction INSTANCE = new PutAlertAction();
public static final String NAME = "indices:data/write/alert/put";
private PutAlertAction() {
super(NAME);
}
@Override
public PutAlertRequestBuilder newRequestBuilder(Client client) {
return new PutAlertRequestBuilder(client);
}
@Override
public PutAlertResponse newResponse() {
return new PutAlertResponse();
}
}

View File

@ -1,119 +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.transport.actions.put;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ValidateActions;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.alerts.client.AlertSourceBuilder;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
/**
* This request class contains the data needed to create an alert along with the name of the alert
* the name of the alert will become the ID of the indexed document.
*/
public class PutAlertRequest extends MasterNodeOperationRequest<PutAlertRequest> {
private String alertName;
private BytesReference alertSource;
private boolean alertSourceUnsafe;
public PutAlertRequest() {
}
/**
* @param alertSource The alertSource
*/
public PutAlertRequest(BytesReference alertSource) {
this.alertSource = alertSource;
}
/**
* @return The name that will be the ID of the indexed document
*/
public String getAlertName() {
return alertName;
}
/**
* Set the alert name
*/
public void setAlertName(String alertName) {
this.alertName = alertName;
}
/**
* @return The source of the alert
*/
public BytesReference getAlertSource() {
return alertSource;
}
/**
* Set the source of the alert
*/
public void source(AlertSourceBuilder source) {
source(source.buildAsBytes(XContentType.JSON));
}
/**
* Set the source of the alert
*/
public void source(BytesReference alertSource) {
this.alertSource = alertSource;
this.alertSourceUnsafe = false;
}
/**
* Set the source of the alert with boolean to control source safety
*/
public void source(BytesReference alertSource, boolean alertSourceUnsafe) {
this.alertSource = alertSource;
this.alertSourceUnsafe = alertSourceUnsafe;
}
public void beforeLocalFork() {
if (alertSourceUnsafe) {
alertSource = alertSource.copyBytesArray();
alertSourceUnsafe = false;
}
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (alertName == null) {
validationException = ValidateActions.addValidationError("alertName is missing", validationException);
}
if (alertSource == null) {
validationException = ValidateActions.addValidationError("alertSource is missing", validationException);
}
return validationException;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
alertName = in.readString();
alertSource = in.readBytesReference();
alertSourceUnsafe = false;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(alertName);
out.writeBytesReference(alertSource);
}
}

View File

@ -1,57 +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.transport.actions.put;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertSourceBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.bytes.BytesReference;
/**
* A Builder to build a PutAlertRequest
*/
public class PutAlertRequestBuilder extends MasterNodeOperationRequestBuilder<PutAlertRequest, PutAlertResponse, PutAlertRequestBuilder, Client> {
public PutAlertRequestBuilder(Client client) {
super(client, new PutAlertRequest());
}
public PutAlertRequestBuilder(Client client, String alertName) {
super(client, new PutAlertRequest());
request.setAlertName(alertName);
}
/**
* @param alertName The alert name to be created
*/
public PutAlertRequestBuilder alertName(String alertName){
request.setAlertName(alertName);
return this;
}
/**
* @param source the source of the alert to be created
*/
public PutAlertRequestBuilder source(BytesReference source) {
request.source(source);
return this;
}
/**
* @param source the source of the alert to be created
*/
public PutAlertRequestBuilder source(AlertSourceBuilder source) {
request.source(source);
return this;
}
@Override
protected void doExecute(ActionListener<PutAlertResponse> listener) {
new AlertsClient(client).putAlert(request, listener);
}
}

View File

@ -1,32 +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.transport.actions.service;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
*/
public class AlertsServiceAction extends AlertsAction<AlertsServiceRequest, AlertsServiceResponse, AlertsServiceRequestBuilder> {
public static final AlertsServiceAction INSTANCE = new AlertsServiceAction();
public static final String NAME = "cluster:admin/alerts/service";
private AlertsServiceAction() {
super(NAME);
}
@Override
public AlertsServiceResponse newResponse() {
return new AlertsServiceResponse();
}
@Override
public AlertsServiceRequestBuilder newRequestBuilder(Client client) {
return new AlertsServiceRequestBuilder(client);
}
}

View File

@ -1,49 +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.transport.actions.service;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.client.Client;
/**
*/
public class AlertsServiceRequestBuilder extends MasterNodeOperationRequestBuilder<AlertsServiceRequest, AlertsServiceResponse, AlertsServiceRequestBuilder, Client> {
public AlertsServiceRequestBuilder(Client client) {
super(client, new AlertsServiceRequest());
}
/**
* Starts alerting if not already started.
*/
public AlertsServiceRequestBuilder start() {
request.start();
return this;
}
/**
* Stops alerting if not already stopped.
*/
public AlertsServiceRequestBuilder stop() {
request.stop();
return this;
}
/**
* Starts and stops alerting.
*/
public AlertsServiceRequestBuilder restart() {
request.restart();
return this;
}
@Override
protected void doExecute(ActionListener<AlertsServiceResponse> listener) {
new AlertsClient(client).alertService(request, listener);
}
}

View File

@ -1,33 +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.transport.actions.stats;
import org.elasticsearch.alerts.client.AlertsAction;
import org.elasticsearch.client.Client;
/**
* This Action gets the stats for the alert plugin
*/
public class AlertsStatsAction extends AlertsAction<AlertsStatsRequest, AlertsStatsResponse, AlertsStatsRequestBuilder> {
public static final AlertsStatsAction INSTANCE = new AlertsStatsAction();
public static final String NAME = "cluster/alerts/stats";
private AlertsStatsAction() {
super(NAME);
}
@Override
public AlertsStatsResponse newResponse() {
return new AlertsStatsResponse();
}
@Override
public AlertsStatsRequestBuilder newRequestBuilder(Client client) {
return new AlertsStatsRequestBuilder(client);
}
}

View File

@ -1,31 +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.transport.actions.stats;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.client.Client;
/**
* An alert stats document action request builder.
*/
public class AlertsStatsRequestBuilder extends MasterNodeOperationRequestBuilder<AlertsStatsRequest, AlertsStatsResponse, AlertsStatsRequestBuilder, Client> {
/**
* The constructor for the AlertsStatsRequestBuilder
*/
public AlertsStatsRequestBuilder(Client client) {
super(client, new AlertsStatsRequest());
}
@Override
protected void doExecute(final ActionListener<AlertsStatsResponse> listener) {
new AlertsClient(client).alertsStats(request, listener);
}
}

View File

@ -1,133 +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.transport.actions.stats;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.alerts.AlertsBuild;
import org.elasticsearch.alerts.AlertsService;
import org.elasticsearch.alerts.AlertsVersion;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
/**
* The AlertStatsResponse response
*/
public class AlertsStatsResponse extends ActionResponse {
private AlertsVersion version;
private AlertsBuild build;
private long numberOfRegisteredAlerts;
private AlertsService.State alertManagerState;
private boolean alertActionManagerStarted;
private long alertActionManagerQueueSize;
private long alertActionManagerLargestQueueSize;
public AlertsStatsResponse() {
}
/**
* @return The current queue size in the alert action manager
*/
public long getAlertActionManagerQueueSize() {
return alertActionManagerQueueSize;
}
void setAlertActionManagerQueueSize(long alertActionManagerQueueSize) {
this.alertActionManagerQueueSize = alertActionManagerQueueSize;
}
/**
* @return The number of alerts currently registered in the system
*/
public long getNumberOfRegisteredAlerts() {
return numberOfRegisteredAlerts;
}
void setNumberOfRegisteredAlerts(long numberOfRegisteredAlerts) {
this.numberOfRegisteredAlerts = numberOfRegisteredAlerts;
}
/**
* Returns the state of the alert manager.
*/
public AlertsService.State getAlertManagerStarted() {
return alertManagerState;
}
void setAlertManagerState(AlertsService.State alertManagerState) {
this.alertManagerState = alertManagerState;
}
/**
* @return {@code true} if the alert action manager is started
*/
public boolean isAlertActionManagerStarted() {
return alertActionManagerStarted;
}
void setAlertActionManagerStarted(boolean alertActionManagerStarted) {
this.alertActionManagerStarted = alertActionManagerStarted;
}
/**
* @return The largest queue size the alert action manager queue has grown to
*/
public long getAlertActionManagerLargestQueueSize() {
return alertActionManagerLargestQueueSize;
}
void setAlertActionManagerLargestQueueSize(long alertActionManagerLargestQueueSize) {
this.alertActionManagerLargestQueueSize = alertActionManagerLargestQueueSize;
}
/**
* @return The alerts plugin version.
*/
public AlertsVersion getVersion() {
return version;
}
void setVersion(AlertsVersion version) {
this.version = version;
}
/**
* @return The alerts plugin build information.
*/
public AlertsBuild getBuild() {
return build;
}
void setBuild(AlertsBuild build) {
this.build = build;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
numberOfRegisteredAlerts = in.readLong();
alertActionManagerQueueSize = in.readLong();
alertActionManagerLargestQueueSize = in.readLong();
alertManagerState = AlertsService.State.fromId(in.readByte());
alertActionManagerStarted = in.readBoolean();
version = AlertsVersion.readVersion(in);
build = AlertsBuild.readBuild(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeLong(numberOfRegisteredAlerts);
out.writeLong(alertActionManagerQueueSize);
out.writeLong(alertActionManagerLargestQueueSize);
out.writeByte(alertManagerState.getId());
out.writeBoolean(alertActionManagerStarted);
AlertsVersion.writeVersion(version, out);
AlertsBuild.writeBuild(build, out);
}
}

View File

@ -1,76 +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.transport.actions.stats;
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.AlertsBuild;
import org.elasticsearch.alerts.AlertsService;
import org.elasticsearch.alerts.AlertsVersion;
import org.elasticsearch.alerts.history.HistoryService;
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 stats operation.
*/
public class TransportAlertsStatsAction extends TransportMasterNodeOperationAction<AlertsStatsRequest, AlertsStatsResponse> {
private final AlertsService alertsService;
private final HistoryService historyService;
@Inject
public TransportAlertsStatsAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters, AlertsService alertsService,
HistoryService historyService) {
super(settings, AlertsStatsAction.NAME, transportService, clusterService, threadPool, actionFilters);
this.alertsService = alertsService;
this.historyService = historyService;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected AlertsStatsRequest newRequest() {
return new AlertsStatsRequest();
}
@Override
protected AlertsStatsResponse newResponse() {
return new AlertsStatsResponse();
}
@Override
protected void masterOperation(AlertsStatsRequest request, ClusterState state, ActionListener<AlertsStatsResponse> listener) throws ElasticsearchException {
AlertsStatsResponse statsResponse = new AlertsStatsResponse();
statsResponse.setAlertManagerState(alertsService.state());
statsResponse.setAlertActionManagerStarted(historyService.started());
statsResponse.setAlertActionManagerQueueSize(historyService.queueSize());
statsResponse.setNumberOfRegisteredAlerts(alertsService.getNumberOfAlerts());
statsResponse.setAlertActionManagerLargestQueueSize(historyService.largestQueueSize());
statsResponse.setVersion(AlertsVersion.CURRENT);
statsResponse.setBuild(AlertsBuild.CURRENT);
listener.onResponse(statsResponse);
}
@Override
protected ClusterBlockException checkBlock(AlertsStatsRequest request, ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA);
}
}

View File

@ -3,7 +3,7 @@
* 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;
package org.elasticsearch.watcher;
import org.elasticsearch.common.io.FastStringReader;
import org.elasticsearch.common.io.Streams;
@ -17,9 +17,9 @@ import java.util.Properties;
/**
*/
public class AlertsBuild {
public class WatcherBuild {
public static final AlertsBuild CURRENT;
public static final WatcherBuild CURRENT;
static {
String hash = "NA";
@ -27,7 +27,7 @@ public class AlertsBuild {
String timestamp = "NA";
try {
String properties = Streams.copyToStringFromClasspath("/alerts-build.properties");
String properties = Streams.copyToStringFromClasspath("/watcher-build.properties");
Properties props = new Properties();
props.load(new FastStringReader(properties));
hash = props.getProperty("hash", hash);
@ -42,14 +42,14 @@ public class AlertsBuild {
// just ignore...
}
CURRENT = new AlertsBuild(hash, hashShort, timestamp);
CURRENT = new WatcherBuild(hash, hashShort, timestamp);
}
private final String hash;
private final String hashShort;
private final String timestamp;
AlertsBuild(String hash, String hashShort, String timestamp) {
WatcherBuild(String hash, String hashShort, String timestamp) {
this.hash = hash;
this.hashShort = hashShort;
this.timestamp = timestamp;
@ -72,7 +72,7 @@ public class AlertsBuild {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AlertsBuild that = (AlertsBuild) o;
WatcherBuild that = (WatcherBuild) o;
if (!hash.equals(that.hash)) return false;
if (!hashShort.equals(that.hashShort)) return false;
@ -89,14 +89,14 @@ public class AlertsBuild {
return result;
}
public static AlertsBuild readBuild(StreamInput in) throws IOException {
public static WatcherBuild readBuild(StreamInput in) throws IOException {
String hash = in.readString();
String hashShort = in.readString();
String timestamp = in.readString();
return new AlertsBuild(hash, hashShort, timestamp);
return new WatcherBuild(hash, hashShort, timestamp);
}
public static void writeBuild(AlertsBuild build, StreamOutput out) throws IOException {
public static void writeBuild(WatcherBuild build, StreamOutput out) throws IOException {
out.writeString(build.hash());
out.writeString(build.hashShort());
out.writeString(build.timestamp());

View File

@ -3,20 +3,20 @@
* 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;
package org.elasticsearch.watcher;
import org.elasticsearch.ElasticsearchException;
/**
* A base class for all alerts exceptions
* A base class for all watcher exceptions
*/
public class AlertsException extends ElasticsearchException {
public class WatcherException extends ElasticsearchException {
public AlertsException(String msg) {
public WatcherException(String msg) {
super(msg);
}
public AlertsException(String msg, Throwable cause) {
public WatcherException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@ -3,7 +3,7 @@
* 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;
package org.elasticsearch.watcher;
import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.ClusterService;
@ -16,34 +16,35 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.gateway.GatewayService;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.watch.WatchService;
/**
*/
public class AlertsLifeCycleService extends AbstractComponent implements ClusterStateListener {
public class WatcherLifeCycleService extends AbstractComponent implements ClusterStateListener {
private final ThreadPool threadPool;
private final AlertsService alertsService;
private final WatchService watchService;
private final ClusterService clusterService;
// Maybe this should be a setting in the cluster settings?
private volatile boolean manuallyStopped;
@Inject
public AlertsLifeCycleService(Settings settings, ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, AlertsService alertsService) {
public WatcherLifeCycleService(Settings settings, ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, WatchService watchService) {
super(settings);
this.clusterService = clusterService;
this.threadPool = threadPool;
this.alertsService = alertsService;
this.watchService = watchService;
clusterService.add(this);
// Close if the indices service is being stopped, so we don't run into search failures (locally) that will
// happen because we're shutting down and an alert is scheduled.
// happen because we're shutting down and an watch is scheduled.
indicesService.addLifecycleListener(new LifecycleListener() {
@Override
public void beforeStop() {
stop(false);
}
});
manuallyStopped = !settings.getAsBoolean("alerts.start_immediately", true);
manuallyStopped = !settings.getAsBoolean("watcher.start_immediately", true);
}
public void start() {
@ -55,19 +56,19 @@ public class AlertsLifeCycleService extends AbstractComponent implements Cluster
}
private synchronized void start(ClusterState state) {
alertsService.start(state);
watchService.start(state);
}
private synchronized void stop(boolean manual) {
manuallyStopped = manual;
alertsService.stop();
watchService.stop();
}
@Override
public void clusterChanged(final ClusterChangedEvent event) {
if (!event.localNodeMaster()) {
// We're no longer the master so we need to stop alerting.
// Stopping alerting may take a while since it will wait on the scheduler to complete shutdown,
// We're no longer the master so we need to stop the watcher.
// Stopping the watcher may take a while since it will wait on the scheduler to complete shutdown,
// so we fork here so that we don't wait too long. Other events may need to be processed and
// other cluster state listeners may need to be executed as well for this event.
threadPool.executor(ThreadPool.Names.GENERIC).execute(new Runnable() {
@ -78,11 +79,11 @@ public class AlertsLifeCycleService extends AbstractComponent implements Cluster
});
} else {
if (event.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
// wait until the gateway has recovered from disk, otherwise we think may not have .alerts and
// a .alerts_history index, but they may not have been restored from the cluster state on disk
// wait until the gateway has recovered from disk, otherwise we think may not have .watchs and
// a .watch_history index, but they may not have been restored from the cluster state on disk
return;
}
if (alertsService.state() == AlertsService.State.STOPPED && !manuallyStopped) {
if (watchService.state() == WatchService.State.STOPPED && !manuallyStopped) {
threadPool.executor(ThreadPool.Names.GENERIC).execute(new Runnable() {
@Override
public void run() {

View File

@ -0,0 +1,55 @@
/*
* 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.watcher;
import org.elasticsearch.watcher.actions.ActionModule;
import org.elasticsearch.watcher.client.WatcherClientModule;
import org.elasticsearch.watcher.condition.ConditionModule;
import org.elasticsearch.watcher.history.HistoryModule;
import org.elasticsearch.watcher.input.InputModule;
import org.elasticsearch.watcher.rest.WatcherRestModule;
import org.elasticsearch.watcher.scheduler.SchedulerModule;
import org.elasticsearch.watcher.support.TemplateUtils;
import org.elasticsearch.watcher.support.clock.ClockModule;
import org.elasticsearch.watcher.support.init.InitializingModule;
import org.elasticsearch.watcher.support.template.TemplateModule;
import org.elasticsearch.watcher.transform.TransformModule;
import org.elasticsearch.watcher.transport.WatcherTransportModule;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.SpawnModules;
import org.elasticsearch.watcher.watch.WatchModule;
public class WatcherModule extends AbstractModule implements SpawnModules {
@Override
public Iterable<? extends Module> spawnModules() {
return ImmutableList.of(
new InitializingModule(),
new WatchModule(),
new TemplateModule(),
new ClockModule(),
new WatcherClientModule(),
new TransformModule(),
new WatcherRestModule(),
new SchedulerModule(),
new WatcherTransportModule(),
new ConditionModule(),
new InputModule(),
new ActionModule(),
new HistoryModule());
}
@Override
protected void configure() {
bind(WatcherLifeCycleService.class).asEagerSingleton();
bind(TemplateUtils.class).asEagerSingleton();
}
}

View File

@ -3,10 +3,10 @@
* 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;
package org.elasticsearch.watcher;
import org.elasticsearch.alerts.actions.email.service.InternalEmailService;
import org.elasticsearch.alerts.support.init.InitializingService;
import org.elasticsearch.watcher.actions.email.service.InternalEmailService;
import org.elasticsearch.watcher.support.init.InitializingService;
import org.elasticsearch.common.collect.ImmutableList;
import org.elasticsearch.common.component.LifecycleComponent;
import org.elasticsearch.common.inject.Module;
@ -18,14 +18,14 @@ import java.util.Collection;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
public class AlertsPlugin extends AbstractPlugin {
public class WatcherPlugin extends AbstractPlugin {
public static final String NAME = "alerts";
public static final String SCHEDULER_THREAD_POOL_NAME = "alerts_scheduler";
public static final String NAME = "watcher";
public static final String SCHEDULER_THREAD_POOL_NAME = "watcher_scheduler";
private final Settings settings;
public AlertsPlugin(Settings settings) {
public WatcherPlugin(Settings settings) {
this.settings = settings;
}
@ -34,12 +34,12 @@ public class AlertsPlugin extends AbstractPlugin {
}
@Override public String description() {
return "Elasticsearch Alerts";
return "Elasticsearch Watcher";
}
@Override
public Collection<Class<? extends Module>> modules() {
return ImmutableList.<Class<? extends Module>>of(AlertsModule.class);
return ImmutableList.<Class<? extends Module>>of(WatcherModule.class);
}
@Override

View File

@ -3,18 +3,18 @@
* 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;
package org.elasticsearch.watcher;
/**
*
*/
public class AlertsSettingsException extends AlertsException {
public class WatcherSettingsException extends WatcherException {
public AlertsSettingsException(String msg, Throwable cause) {
public WatcherSettingsException(String msg, Throwable cause) {
super(msg, cause);
}
public AlertsSettingsException(String msg) {
public WatcherSettingsException(String msg) {
super(msg);
}
}

View File

@ -3,7 +3,7 @@
* 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;
package org.elasticsearch.watcher;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
@ -17,7 +17,7 @@ import java.io.Serializable;
/**
*/
@SuppressWarnings("deprecation")
public class AlertsVersion implements Serializable {
public class WatcherVersion implements Serializable {
// The logic for ID is: XXYYZZAA, where XX is major version, YY is minor version, ZZ is revision, and AA is Beta/RC indicator
// AA values below 50 are beta builds, and below 99 are RC builds, with 99 indicating a release
@ -25,41 +25,41 @@ public class AlertsVersion implements Serializable {
// The first internal beta has already been released, without this class being here, so we start version version 2.
public static final int V_1_0_0_Beta2_ID = /*00*/1000002;
public static final AlertsVersion V_1_0_0_Beta2 = new AlertsVersion(V_1_0_0_Beta2_ID, true, Version.V_1_4_0);
public static final WatcherVersion V_1_0_0_Beta2 = new WatcherVersion(V_1_0_0_Beta2_ID, true, Version.V_1_4_0);
public static final AlertsVersion CURRENT = V_1_0_0_Beta2;
public static final WatcherVersion CURRENT = V_1_0_0_Beta2;
public static AlertsVersion readVersion(StreamInput in) throws IOException {
public static WatcherVersion readVersion(StreamInput in) throws IOException {
return fromId(in.readVInt());
}
public static AlertsVersion fromId(int id) {
public static WatcherVersion fromId(int id) {
switch (id) {
case V_1_0_0_Beta2_ID:
return V_1_0_0_Beta2;
default:
return new AlertsVersion(id, null, Version.CURRENT);
return new WatcherVersion(id, null, Version.CURRENT);
}
}
public static void writeVersion(AlertsVersion version, StreamOutput out) throws IOException {
public static void writeVersion(WatcherVersion version, StreamOutput out) throws IOException {
out.writeVInt(version.id);
}
/**
* Returns the smallest version between the 2.
*/
public static AlertsVersion smallest(AlertsVersion version1, AlertsVersion version2) {
public static WatcherVersion smallest(WatcherVersion version1, WatcherVersion version2) {
return version1.id < version2.id ? version1 : version2;
}
/**
* Returns the version given its string representation, current version if the argument is null or empty
*/
public static AlertsVersion fromString(String version) {
public static WatcherVersion fromString(String version) {
if (!Strings.hasLength(version)) {
return AlertsVersion.CURRENT;
return WatcherVersion.CURRENT;
}
String[] parts = version.split("\\.");
@ -100,7 +100,7 @@ public class AlertsVersion implements Serializable {
public final Version minEsCompatibilityVersion;
// TODO: Once licencing integration has been completed license version should be added to
AlertsVersion(int id, @Nullable Boolean snapshot, Version minEsCompatibilityVersion) {
WatcherVersion(int id, @Nullable Boolean snapshot, Version minEsCompatibilityVersion) {
this.id = id;
this.major = (byte) ((id / 1000000) % 100);
this.minor = (byte) ((id / 10000) % 100);
@ -114,23 +114,23 @@ public class AlertsVersion implements Serializable {
return snapshot != null && snapshot;
}
public boolean after(AlertsVersion version) {
public boolean after(WatcherVersion version) {
return version.id < id;
}
public boolean onOrAfter(AlertsVersion version) {
public boolean onOrAfter(WatcherVersion version) {
return version.id <= id;
}
public boolean before(AlertsVersion version) {
public boolean before(WatcherVersion version) {
return version.id > id;
}
public boolean onOrBefore(AlertsVersion version) {
public boolean onOrBefore(WatcherVersion version) {
return version.id >= id;
}
public boolean compatibleWith(AlertsVersion version) {
public boolean compatibleWith(WatcherVersion version) {
return version.onOrAfter(minimumCompatibilityVersion());
}
@ -145,8 +145,8 @@ public class AlertsVersion implements Serializable {
* is in most of the cases the smallest major version release unless the current version
* is a beta or RC release then the version itself is returned.
*/
public AlertsVersion minimumCompatibilityVersion() {
return AlertsVersion.smallest(this, fromId(major * 1000000 + 99));
public WatcherVersion minimumCompatibilityVersion() {
return WatcherVersion.smallest(this, fromId(major * 1000000 + 99));
}
/**
@ -185,7 +185,7 @@ public class AlertsVersion implements Serializable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AlertsVersion that = (AlertsVersion) o;
WatcherVersion that = (WatcherVersion) o;
if (id != that.id) return false;

View File

@ -3,11 +3,11 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.xcontent.ToXContent;
@ -43,7 +43,7 @@ public abstract class Action<R extends Action.Result> implements ToXContent {
/**
* Executes this action
*/
public R execute(ExecutionContext context) throws IOException {
public R execute(WatchExecutionContext context) throws IOException {
Payload payload = context.payload();
Transform.Result transformResult = null;
if (transform != null) {
@ -57,7 +57,7 @@ public abstract class Action<R extends Action.Result> implements ToXContent {
return result;
}
protected abstract R execute(ExecutionContext context, Payload payload) throws IOException;
protected abstract R execute(WatchExecutionContext context, Payload payload) throws IOException;
/**
* Parses xcontent to a concrete action of the same type.

View File

@ -3,12 +3,12 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.alerts.actions.email.EmailAction;
import org.elasticsearch.alerts.actions.index.IndexAction;
import org.elasticsearch.alerts.actions.webhook.WebhookAction;
import org.elasticsearch.alerts.support.Script;
import org.elasticsearch.watcher.actions.email.EmailAction;
import org.elasticsearch.watcher.actions.index.IndexAction;
import org.elasticsearch.watcher.actions.webhook.WebhookAction;
import org.elasticsearch.watcher.support.Script;
/**
*

View File

@ -3,14 +3,14 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.watcher.WatcherException;
/**
*
*/
public class ActionException extends AlertsException {
public class ActionException extends WatcherException {
public ActionException(String msg) {
super(msg);

View File

@ -3,14 +3,14 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.alerts.actions.email.EmailAction;
import org.elasticsearch.alerts.actions.email.service.EmailService;
import org.elasticsearch.alerts.actions.email.service.InternalEmailService;
import org.elasticsearch.alerts.actions.index.IndexAction;
import org.elasticsearch.alerts.actions.webhook.HttpClient;
import org.elasticsearch.alerts.actions.webhook.WebhookAction;
import org.elasticsearch.watcher.actions.email.EmailAction;
import org.elasticsearch.watcher.actions.email.service.EmailService;
import org.elasticsearch.watcher.actions.email.service.InternalEmailService;
import org.elasticsearch.watcher.actions.index.IndexAction;
import org.elasticsearch.watcher.actions.webhook.HttpClient;
import org.elasticsearch.watcher.actions.webhook.WebhookAction;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;

View File

@ -3,7 +3,7 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.inject.Inject;

View File

@ -3,7 +3,7 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
/**
*

View File

@ -3,7 +3,7 @@
* 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.actions;
package org.elasticsearch.watcher.actions;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;

View File

@ -3,17 +3,17 @@
* 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.actions.email;
package org.elasticsearch.watcher.actions.email;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.actions.Action;
import org.elasticsearch.alerts.actions.ActionSettingsException;
import org.elasticsearch.alerts.actions.email.service.*;
import org.elasticsearch.alerts.support.Variables;
import org.elasticsearch.alerts.support.template.Template;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.alerts.transform.TransformRegistry;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.actions.ActionSettingsException;
import org.elasticsearch.watcher.actions.email.service.*;
import org.elasticsearch.watcher.support.Variables;
import org.elasticsearch.watcher.support.template.Template;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.watcher.transform.TransformRegistry;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.component.AbstractComponent;
@ -67,7 +67,7 @@ public class EmailAction extends Action<EmailAction.Result> {
}
@Override
protected Result execute(ExecutionContext ctx, Payload payload) throws IOException {
protected Result execute(WatchExecutionContext ctx, Payload payload) throws IOException {
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
Email.Builder email = Email.builder()
@ -91,8 +91,8 @@ public class EmailAction extends Action<EmailAction.Result> {
EmailService.EmailSent sent = emailService.send(email.build(), auth, profile, account);
return new Result.Success(sent);
} catch (EmailException ee) {
logger.error("could not send email for alert [{}]", ee, ctx.alert().name());
return new Result.Failure("could not send email for alert [" + ctx.alert().name() + "]. error: " + ee.getMessage());
logger.error("could not send email for watch [{}]", ee, ctx.watch().name());
return new Result.Failure("could not send email for watch [" + ctx.watch().name() + "]. error: " + ee.getMessage());
}
}

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.ImmutableSettings;
@ -166,8 +166,8 @@ public class Account {
* holds email fields that can be configured on the account. These fields
* will hold the default values for missing fields in email messages. Having
* the ability to create these default can substantially reduced the configuration
* needed on each alert (e.g. if all the emails are always sent to the same recipients
* one could set those here and leave them out on the alert definition).
* needed on each watch (e.g. if all the emails are always sent to the same recipients
* one could set those here and leave them out on the watch definition).
*/
static class EmailDefaults {

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;

View File

@ -3,9 +3,9 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.alerts.actions.email.service.support.BodyPartSource;
import org.elasticsearch.watcher.actions.email.service.support.BodyPartSource;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
/**
*

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.base.Charsets;
@ -316,7 +316,7 @@ public class Email implements ToXContent {
}
public Email build() {
assert id != null : "email id should not be null (should be set to the alert id";
assert id != null : "email id should not be null (should be set to the watch id";
return new Email(id, from, replyTo, priority, sentDate, to, cc, bcc, subject, textBody, htmlBody, attachments.build(), inlines.build());
}

View File

@ -3,9 +3,9 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.alerts.actions.ActionException;
import org.elasticsearch.watcher.actions.ActionException;
/**
*

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
/**
*

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
/**
*

View File

@ -3,9 +3,9 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.alerts.actions.email.service.support.BodyPartSource;
import org.elasticsearch.watcher.actions.email.service.support.BodyPartSource;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.inject.Provider;

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.component.AbstractLifecycleComponent;

View File

@ -3,7 +3,7 @@
* 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.actions.email.service;
package org.elasticsearch.watcher.actions.email.service;
import org.elasticsearch.common.base.Charsets;
import org.elasticsearch.common.xcontent.ToXContent;

View File

@ -3,7 +3,7 @@
* 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.actions.email.service.support;
package org.elasticsearch.watcher.actions.email.service.support;
import org.elasticsearch.common.xcontent.ToXContent;

View File

@ -3,19 +3,19 @@
* 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.actions.index;
package org.elasticsearch.watcher.actions.index;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.actions.Action;
import org.elasticsearch.alerts.actions.ActionException;
import org.elasticsearch.alerts.actions.ActionSettingsException;
import org.elasticsearch.alerts.support.init.proxy.ClientProxy;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.alerts.transform.TransformRegistry;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.actions.ActionException;
import org.elasticsearch.watcher.actions.ActionSettingsException;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.watcher.transform.TransformRegistry;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.component.AbstractComponent;
@ -54,7 +54,7 @@ public class IndexAction extends Action<IndexAction.Result> {
}
@Override
protected Result execute(ExecutionContext ctx, Payload payload) throws IOException {
protected Result execute(WatchExecutionContext ctx, Payload payload) throws IOException {
IndexRequest indexRequest = new IndexRequest();
indexRequest.index(index);
indexRequest.type(type);
@ -66,7 +66,7 @@ public class IndexAction extends Action<IndexAction.Result> {
resultBuilder.endObject();
indexRequest.source(resultBuilder);
} catch (IOException ioe) {
logger.error("failed to index result for alert [{}]", ioe, ctx.alert().name());
logger.error("failed to index result for watch [{}]", ioe, ctx.watch().name());
return new Result(null, "failed to build index request. " + ioe.getMessage(), false);
}
@ -80,7 +80,7 @@ public class IndexAction extends Action<IndexAction.Result> {
data.put("index", response.getIndex());
return new Result(new Payload.Simple(data), null, response.isCreated());
} catch (ElasticsearchException e) {
logger.error("failed to index result for alert [{}]", e, ctx.alert().name());
logger.error("failed to index result for watch [{}]", e, ctx.watch().name());
return new Result(null, "failed to build index request. " + e.getMessage(), false);
}
}

View File

@ -3,7 +3,7 @@
* 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.actions.webhook;
package org.elasticsearch.watcher.actions.webhook;
import org.elasticsearch.common.base.Charsets;
import org.elasticsearch.common.component.AbstractComponent;

View File

@ -3,20 +3,20 @@
* 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.actions.webhook;
package org.elasticsearch.watcher.actions.webhook;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.actions.Action;
import org.elasticsearch.alerts.actions.ActionException;
import org.elasticsearch.alerts.actions.ActionSettingsException;
import org.elasticsearch.alerts.support.Script;
import org.elasticsearch.alerts.support.Variables;
import org.elasticsearch.alerts.support.template.Template;
import org.elasticsearch.alerts.support.template.XContentTemplate;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.alerts.transform.TransformRegistry;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.actions.ActionException;
import org.elasticsearch.watcher.actions.ActionSettingsException;
import org.elasticsearch.watcher.support.Script;
import org.elasticsearch.watcher.support.Variables;
import org.elasticsearch.watcher.support.template.Template;
import org.elasticsearch.watcher.support.template.XContentTemplate;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.watcher.transform.TransformRegistry;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.component.AbstractComponent;
@ -57,7 +57,7 @@ public class WebhookAction extends Action<WebhookAction.Result> {
}
@Override
protected Result execute(ExecutionContext ctx, Payload payload) throws IOException {
protected Result execute(WatchExecutionContext ctx, Payload payload) throws IOException {
Map<String, Object> model = Variables.createCtxModel(ctx, payload);
String urlText = url.render(model);
String bodyText = body != null ? body.render(model) : XContentTemplate.YAML.render(model);
@ -74,7 +74,7 @@ public class WebhookAction extends Action<WebhookAction.Result> {
return new Result.Executed(status, urlText, bodyText);
} catch (IOException ioe) {
logger.error("failed to connect to [{}] for alert [{}]", ioe, urlText, ctx.alert().name());
logger.error("failed to connect to [{}] for watch [{}]", ioe, urlText, ctx.watch().name());
return new Result.Failure("failed to send http request. " + ioe.getMessage());
}
}
@ -228,7 +228,7 @@ public class WebhookAction extends Action<WebhookAction.Result> {
try {
urlTemplate = templateParser.parse(parser);
} catch (Template.Parser.ParseException pe) {
throw new AlertsSettingsException("could not parse webhook action [url] template", pe);
throw new WatcherSettingsException("could not parse webhook action [url] template", pe);
}
} else if (BODY_FIELD.match(currentFieldName)) {
try {

View File

@ -3,16 +3,16 @@
* 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.client;
package org.elasticsearch.watcher.client;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.actions.Action;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.condition.ConditionBuilders;
import org.elasticsearch.alerts.input.Input;
import org.elasticsearch.alerts.input.NoneInput;
import org.elasticsearch.alerts.scheduler.schedule.Schedule;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionBuilders;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.input.NoneInput;
import org.elasticsearch.watcher.scheduler.schedule.Schedule;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
@ -29,10 +29,10 @@ import java.util.Set;
/**
*
*/
public class AlertSourceBuilder implements ToXContent {
public class WatchSourceBuilder implements ToXContent {
public static AlertSourceBuilder alertSourceBuilder() {
return new AlertSourceBuilder();
public static WatchSourceBuilder watchSourceBuilder() {
return new WatchSourceBuilder();
}
private Schedule schedule;
@ -43,37 +43,37 @@ public class AlertSourceBuilder implements ToXContent {
private TimeValue throttlePeriod = null;
private Map<String, Object> metadata;
public AlertSourceBuilder schedule(Schedule schedule) {
public WatchSourceBuilder schedule(Schedule schedule) {
this.schedule = schedule;
return this;
}
public AlertSourceBuilder input(Input.SourceBuilder input) {
public WatchSourceBuilder input(Input.SourceBuilder input) {
this.input = input;
return this;
}
public AlertSourceBuilder condition(Condition.SourceBuilder condition) {
public WatchSourceBuilder condition(Condition.SourceBuilder condition) {
this.condition = condition;
return this;
}
public AlertSourceBuilder transform(Transform.SourceBuilder transform) {
public WatchSourceBuilder transform(Transform.SourceBuilder transform) {
this.transform = transform;
return this;
}
public AlertSourceBuilder throttlePeriod(TimeValue throttlePeriod) {
public WatchSourceBuilder throttlePeriod(TimeValue throttlePeriod) {
this.throttlePeriod = throttlePeriod;
return this;
}
public AlertSourceBuilder addAction(Action.SourceBuilder action) {
public WatchSourceBuilder addAction(Action.SourceBuilder action) {
actions.add(action);
return this;
}
public AlertSourceBuilder metadata(Map<String, Object> metadata) {
public WatchSourceBuilder metadata(Map<String, Object> metadata) {
this.metadata = metadata;
return this;
}
@ -82,36 +82,36 @@ public class AlertSourceBuilder implements ToXContent {
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.startObject(Alert.Parser.SCHEDULE_FIELD.getPreferredName())
builder.startObject(Watch.Parser.SCHEDULE_FIELD.getPreferredName())
.field(schedule.type(), schedule)
.endObject();
builder.startObject(Alert.Parser.INPUT_FIELD.getPreferredName())
builder.startObject(Watch.Parser.INPUT_FIELD.getPreferredName())
.field(input.type(), input)
.endObject();
builder.startObject(Alert.Parser.CONDITION_FIELD.getPreferredName())
builder.startObject(Watch.Parser.CONDITION_FIELD.getPreferredName())
.field(condition.type(), condition)
.endObject();
if (transform != null) {
builder.startObject(Alert.Parser.TRANSFORM_FIELD.getPreferredName())
builder.startObject(Watch.Parser.TRANSFORM_FIELD.getPreferredName())
.field(transform.type(), transform)
.endObject();
}
if (throttlePeriod != null) {
builder.field(Alert.Parser.THROTTLE_PERIOD_FIELD.getPreferredName(), throttlePeriod.getMillis());
builder.field(Watch.Parser.THROTTLE_PERIOD_FIELD.getPreferredName(), throttlePeriod.getMillis());
}
builder.startArray(Alert.Parser.ACTIONS_FIELD.getPreferredName());
builder.startArray(Watch.Parser.ACTIONS_FIELD.getPreferredName());
for (Action.SourceBuilder action : actions) {
builder.startObject().field(action.type(), action).endObject();
}
builder.endArray();
if (metadata != null) {
builder.field(Alert.Parser.META_FIELD.getPreferredName(), metadata);
builder.field(Watch.Parser.META_FIELD.getPreferredName(), metadata);
}
return builder.endObject();

View File

@ -3,7 +3,7 @@
* 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.client;
package org.elasticsearch.watcher.client;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestBuilder;
@ -12,11 +12,11 @@ import org.elasticsearch.action.ClientAction;
import org.elasticsearch.client.Client;
/**
* Base alert action class.
* All watcher related actions should extend this base class.
*/
public abstract class AlertsAction<Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder, Client>> extends ClientAction<Request, Response, RequestBuilder> {
public abstract class WatcherAction<Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder, Client>> extends ClientAction<Request, Response, RequestBuilder> {
protected AlertsAction(String name) {
protected WatcherAction(String name) {
super(name);
}

View File

@ -0,0 +1,253 @@
/*
* 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.watcher.client;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchAction;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchRequest;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchRequestBuilder;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchResponse;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchAction;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchRequest;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchRequestBuilder;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchResponse;
import org.elasticsearch.watcher.transport.actions.get.GetWatchAction;
import org.elasticsearch.watcher.transport.actions.get.GetWatchRequest;
import org.elasticsearch.watcher.transport.actions.get.GetWatchRequestBuilder;
import org.elasticsearch.watcher.transport.actions.get.GetWatchResponse;
import org.elasticsearch.watcher.transport.actions.put.PutWatchAction;
import org.elasticsearch.watcher.transport.actions.put.PutWatchRequest;
import org.elasticsearch.watcher.transport.actions.put.PutWatchRequestBuilder;
import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceAction;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceRequest;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceRequestBuilder;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceResponse;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsAction;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequest;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequestBuilder;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
/**
*/
public class WatcherClient {
private final Client client;
@Inject
public WatcherClient(Client client) {
this.client = client;
}
/**
* Creates a request builder that gets an watch by name (id)
*
* @param watchName the name (id) of the watch
* @return The request builder
*/
public GetWatchRequestBuilder prepareGetWatch(String watchName) {
return new GetWatchRequestBuilder(client, watchName);
}
/**
* Creates a request builder that gets an watch
*
* @return the request builder
*/
public GetWatchRequestBuilder prepareGetWatch() {
return new GetWatchRequestBuilder(client);
}
/**
* Gets an watch from the watch index
*
* @param request The get watch request
* @param listener The listener for the get watch response containing the GetResponse for this watch
*/
public void getWatch(GetWatchRequest request, ActionListener<GetWatchResponse> listener) {
client.execute(GetWatchAction.INSTANCE, request, listener);
}
/**
* Gets an watch from the watch index
*
* @param request The get watch request with the watch name (id)
* @return The response containing the GetResponse for this watch
*/
public ActionFuture<GetWatchResponse> getWatch(GetWatchRequest request) {
return client.execute(GetWatchAction.INSTANCE, request);
}
/**
* Creates a request builder to delete an watch by name (id)
*
* @param watchName the name (id) of the watch
* @return The request builder
*/
public DeleteWatchRequestBuilder prepareDeleteWatch(String watchName) {
return new DeleteWatchRequestBuilder(client, watchName);
}
/**
* Creates a request builder that deletes an watch
*
* @return The request builder
*/
public DeleteWatchRequestBuilder prepareDeleteWatch() {
return new DeleteWatchRequestBuilder(client);
}
/**
* Deletes an watch
*
* @param request The delete request with the watch name (id) to be deleted
* @param listener The listener for the delete watch response containing the DeleteResponse for this action
*/
public void deleteWatch(DeleteWatchRequest request, ActionListener<DeleteWatchResponse> listener) {
client.execute(DeleteWatchAction.INSTANCE, request, listener);
}
/**
* Deletes an watch
*
* @param request The delete request with the watch name (id) to be deleted
* @return The response containing the DeleteResponse for this action
*/
public ActionFuture<DeleteWatchResponse> deleteWatch(DeleteWatchRequest request) {
return client.execute(DeleteWatchAction.INSTANCE, request);
}
/**
* Creates a request builder to build a request to put an watch
*
* @param watchName The name of the watch to put
* @return The builder to create the watch
*/
public PutWatchRequestBuilder preparePutWatch(String watchName) {
return new PutWatchRequestBuilder(client, watchName);
}
/**
* Creates a request builder to build a request to put a watch
*
* @return The builder
*/
public PutWatchRequestBuilder preparePutWatch() {
return new PutWatchRequestBuilder(client);
}
/**
* Adds the given watch to the watcher
*
* @param request The request containing the watch to be added
* @param listener The listener for the response containing the IndexResponse for this watch
*/
public void putWatch(PutWatchRequest request, ActionListener<PutWatchResponse> listener) {
client.execute(PutWatchAction.INSTANCE, request, listener);
}
/**
* Adds a new watch
*
* @param request The request containing the watch to be added
* @return The response containing the IndexResponse for this watch
*/
public ActionFuture<PutWatchResponse> putWatch(PutWatchRequest request) {
return client.execute(PutWatchAction.INSTANCE, request);
}
/**
* Gets the watcher stats
*
* @param request The request for the watcher stats
* @return The response containing the StatsResponse for this action
*/
public ActionFuture<WatcherStatsResponse> watcherStats(WatcherStatsRequest request) {
return client.execute(WatcherStatsAction.INSTANCE, request);
}
/**
* Creates a request builder to build a request to get the watcher stats
*
* @return The builder get the watcher stats
*/
public WatcherStatsRequestBuilder prepareWatcherStats() {
return new WatcherStatsRequestBuilder(client);
}
/**
* Gets the watcher stats
*
* @param request The request for the watcher stats
* @param listener The listener for the response containing the WatcherStatsResponse
*/
public void watcherStats(WatcherStatsRequest request, ActionListener<WatcherStatsResponse> listener) {
client.execute(WatcherStatsAction.INSTANCE, request, listener);
}
/**
* Creates a request builder to ack a watch by name (id)
*
* @param watcherName the name (id) of the watch
* @return The request builder
*/
public AckWatchRequestBuilder prepareAckWatch(String watcherName) {
return new AckWatchRequestBuilder(client, watcherName);
}
/**
* Creates a request builder that acks an watch
*
* @return The request builder
*/
public AckWatchRequestBuilder prepareAckWatch() {
return new AckWatchRequestBuilder(client);
}
/**
* Ack a watch
*
* @param request The ack request with the watch name (id) to be acked
* @param listener The listener for the ack watch response
*/
public void ackWatch(AckWatchRequest request, ActionListener<AckWatchResponse> listener) {
client.execute(AckWatchAction.INSTANCE, request, listener);
}
/**
* Acks an watch
*
* @param request The ack request with the watch name (id) to be acked
* @return The AckWatchResponse
*/
public ActionFuture<AckWatchResponse> ackWatch(AckWatchRequest request) {
return client.execute(AckWatchAction.INSTANCE, request);
}
/**
* Prepare a watch service request.
*/
public WatcherServiceRequestBuilder prepareWatchService() {
return new WatcherServiceRequestBuilder(client);
}
/**
* Perform an watcher service request to either start, stop or restart the service.
*/
public void watcherService(WatcherServiceRequest request, ActionListener<WatcherServiceResponse> listener) {
client.execute(WatcherServiceAction.INSTANCE, request, listener);
}
/**
* Perform an watcher service request to either start, stop or restart the service.
*/
public ActionFuture<WatcherServiceResponse> watcherService(WatcherServiceRequest request) {
return client.execute(WatcherServiceAction.INSTANCE, request);
}
}

View File

@ -3,17 +3,17 @@
* 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.client;
package org.elasticsearch.watcher.client;
import org.elasticsearch.common.inject.AbstractModule;
/**
*
*/
public class AlertsClientModule extends AbstractModule {
public class WatcherClientModule extends AbstractModule {
@Override
protected void configure() {
bind(AlertsClient.class).asEagerSingleton();
bind(WatcherClient.class).asEagerSingleton();
}
}

View File

@ -3,9 +3,9 @@
* 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.condition;
package org.elasticsearch.watcher.condition;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.xcontent.ToXContent;
@ -34,7 +34,7 @@ public abstract class Condition<R extends Condition.Result> implements ToXConten
/**
* Executes this condition
*/
public abstract R execute(ExecutionContext ctx) throws IOException;
public abstract R execute(WatchExecutionContext ctx) throws IOException;
/**

View File

@ -3,10 +3,10 @@
* 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.condition;
package org.elasticsearch.watcher.condition;
import org.elasticsearch.alerts.condition.script.ScriptCondition;
import org.elasticsearch.alerts.condition.simple.AlwaysTrueCondition;
import org.elasticsearch.watcher.condition.script.ScriptCondition;
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
/**
*

View File

@ -3,14 +3,14 @@
* 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.condition;
package org.elasticsearch.watcher.condition;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.watcher.WatcherException;
/**
*
*/
public class ConditionException extends AlertsException {
public class ConditionException extends WatcherException {
public ConditionException(String msg) {
super(msg);

View File

@ -3,11 +3,11 @@
* 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.condition;
package org.elasticsearch.watcher.condition;
import org.elasticsearch.alerts.condition.script.ScriptCondition;
import org.elasticsearch.alerts.condition.simple.AlwaysFalseCondition;
import org.elasticsearch.alerts.condition.simple.AlwaysTrueCondition;
import org.elasticsearch.watcher.condition.script.ScriptCondition;
import org.elasticsearch.watcher.condition.simple.AlwaysFalseCondition;
import org.elasticsearch.watcher.condition.simple.AlwaysTrueCondition;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;

View File

@ -3,7 +3,7 @@
* 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.condition;
package org.elasticsearch.watcher.condition;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.inject.Inject;

View File

@ -3,15 +3,15 @@
* 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.condition.script;
package org.elasticsearch.watcher.condition.script;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.condition.ConditionException;
import org.elasticsearch.alerts.support.Script;
import org.elasticsearch.alerts.support.Variables;
import org.elasticsearch.alerts.support.init.proxy.ScriptServiceProxy;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionException;
import org.elasticsearch.watcher.support.Script;
import org.elasticsearch.watcher.support.Variables;
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
@ -52,7 +52,7 @@ public class ScriptCondition extends Condition<ScriptCondition.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
ImmutableMap<String, Object> model = ImmutableMap.<String, Object>builder()
.putAll(script.params())
.putAll(Variables.createCtxModel(ctx, ctx.payload()))
@ -108,7 +108,7 @@ public class ScriptCondition extends Condition<ScriptCondition.Result> {
Script script = Script.parse(parser);
return new ScriptCondition(logger, scriptService, script);
} catch (Script.ParseException pe) {
throw new AlertsSettingsException("could not parse [script] condition", pe);
throw new WatcherSettingsException("could not parse [script] condition", pe);
}
}

View File

@ -3,16 +3,15 @@
* 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.condition.simple;
package org.elasticsearch.watcher.condition.simple;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.condition.ConditionException;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionException;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@ -43,7 +42,7 @@ public class AlwaysFalseCondition extends Condition<Condition.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
return RESULT;
}

View File

@ -3,11 +3,11 @@
* 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.condition.simple;
package org.elasticsearch.watcher.condition.simple;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.condition.ConditionException;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionException;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
@ -41,7 +41,7 @@ public class AlwaysTrueCondition extends Condition<Condition.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
return RESULT;
}

View File

@ -3,13 +3,13 @@
* 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.history;
package org.elasticsearch.watcher.history;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.watcher.WatcherException;
/**
*/
public class HistoryException extends AlertsException {
public class HistoryException extends WatcherException {
public HistoryException(String msg) {
super(msg);

View File

@ -3,7 +3,7 @@
* 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.history;
package org.elasticsearch.watcher.history;
import org.elasticsearch.common.inject.AbstractModule;
@ -11,22 +11,22 @@ import org.elasticsearch.common.inject.AbstractModule;
*/
public class HistoryModule extends AbstractModule {
private final Class<? extends AlertsExecutor> executorClass;
private final Class<? extends WatchExecutor> executorClass;
public HistoryModule() {
this(InternalAlertsExecutor.class);
this(InternalWatchExecutor.class);
}
protected HistoryModule(Class<? extends AlertsExecutor> executorClass) {
protected HistoryModule(Class<? extends WatchExecutor> executorClass) {
this.executorClass = executorClass;
}
@Override
protected void configure() {
bind(FiredAlert.Parser.class).asEagerSingleton();
bind(WatchRecord.Parser.class).asEagerSingleton();
bind(HistoryStore.class).asEagerSingleton();
bind(HistoryService.class).asEagerSingleton();
bind(executorClass).asEagerSingleton();
bind(AlertsExecutor.class).to(executorClass);
bind(WatchExecutor.class).to(executorClass);
}
}

View File

@ -3,18 +3,17 @@
* 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.history;
package org.elasticsearch.watcher.history;
import org.elasticsearch.ElasticsearchIllegalStateException;
import org.elasticsearch.alerts.*;
import org.elasticsearch.alerts.actions.Action;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.input.Input;
import org.elasticsearch.alerts.scheduler.Scheduler;
import org.elasticsearch.alerts.support.Callback;
import org.elasticsearch.alerts.support.clock.Clock;
import org.elasticsearch.alerts.throttle.Throttler;
import org.elasticsearch.alerts.transform.Transform;
import org.elasticsearch.watcher.actions.Action;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.scheduler.Scheduler;
import org.elasticsearch.watcher.support.Callback;
import org.elasticsearch.watcher.support.clock.Clock;
import org.elasticsearch.watcher.throttle.Throttler;
import org.elasticsearch.watcher.transform.Transform;
import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
@ -24,9 +23,11 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.watcher.watch.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -36,24 +37,24 @@ import java.util.concurrent.atomic.AtomicInteger;
public class HistoryService extends AbstractComponent {
private final HistoryStore historyStore;
private final AlertsExecutor executor;
private final AlertsStore alertsStore;
private final WatchExecutor executor;
private final WatchStore watchStore;
private final ClusterService clusterService;
private final AlertLockService alertLockService;
private final WatchLockService watchLockService;
private final Clock clock;
private final AtomicBoolean started = new AtomicBoolean(false);
private final AtomicInteger initializationRetries = new AtomicInteger();
@Inject
public HistoryService(Settings settings, HistoryStore historyStore, AlertsExecutor executor,
AlertsStore alertsStore, AlertLockService alertLockService, Scheduler scheduler,
public HistoryService(Settings settings, HistoryStore historyStore, WatchExecutor executor,
WatchStore watchStore, WatchLockService watchLockService, Scheduler scheduler,
ClusterService clusterService, Clock clock) {
super(settings);
this.historyStore = historyStore;
this.executor = executor;
this.alertsStore = alertsStore;
this.alertLockService = alertLockService;
this.watchStore = watchStore;
this.watchLockService = watchLockService;
this.clusterService = clusterService;
this.clock = clock;
scheduler.addListener(new SchedulerListener());
@ -66,14 +67,14 @@ public class HistoryService extends AbstractComponent {
}
assert executor.queue().isEmpty() : "queue should be empty, but contains " + executor.queue().size() + " elements.";
HistoryStore.LoadResult loadResult = historyStore.loadFiredAlerts(state, FiredAlert.State.AWAITS_EXECUTION);
if (!loadResult.succeeded()) {
Collection<WatchRecord> records = historyStore.loadRecords(state, WatchRecord.State.AWAITS_EXECUTION);
if (records == null) {
retry(callback);
return;
}
if (started.compareAndSet(false, true)) {
logger.debug("starting history service");
executePreviouslyFiredAlerts(loadResult);
executeRecords(records);
logger.debug("started history service");
}
callback.onSuccess(state);
@ -105,55 +106,54 @@ public class HistoryService extends AbstractComponent {
return executor.largestPoolSize();
}
void fire(Alert alert, DateTime scheduledFireTime, DateTime fireTime) throws HistoryException {
void execute(Watch watch, DateTime scheduledFireTime, DateTime fireTime) throws HistoryException {
if (!started.get()) {
throw new ElasticsearchIllegalStateException("not started");
}
FiredAlert firedAlert = new FiredAlert(alert, scheduledFireTime, fireTime);
logger.debug("adding fired alert [{}]", alert.name());
historyStore.put(firedAlert);
executeAsync(firedAlert, alert);
WatchRecord watchRecord = new WatchRecord(watch, scheduledFireTime, fireTime);
logger.debug("saving watch record [{}]", watch.name());
historyStore.put(watchRecord);
executeAsync(watchRecord, watch);
}
/*
The execution of an alert is split into operations, a schedule part which just makes sure that store the fact an alert
has fired and an execute part which actually executed the alert.
The execution of an watch is split into two phases:
1. the trigger part which just makes sure to store the associated watch record in the history
2. the actual processing of the watch
The reason this is split into two operations is that we don't want to lose the fact an alert has fired. If we
would not split the execution of an alert and many alerts fire in a small window of time then it can happen that
thread pool that receives fired jobs from the quartz scheduler is going to reject jobs and then we would never
know about jobs that have fired. By splitting the execution of fired jobs into two operations we lower the chance
we lose fired jobs signficantly.
The reason this split is that we don't want to lose the fact watch was triggered. This way, even if the
thread pool that executes the watches is completely busy, we don't lose the fact that the watch was
triggered (it'll have its history record)
*/
void executeAsync(FiredAlert firedAlert, Alert alert) {
void executeAsync(WatchRecord watchRecord, Watch watch) {
try {
executor.execute(new AlertExecutionTask(firedAlert, alert));
executor.execute(new WatchExecutionTask(watchRecord, watch));
} catch (EsRejectedExecutionException e) {
logger.debug("[{}] failed to execute fired alert", firedAlert.name());
firedAlert.update(FiredAlert.State.FAILED, "failed to run fired alert due to thread pool capacity");
historyStore.update(firedAlert);
logger.debug("failed to execute triggered watch [{}]", watchRecord.name());
watchRecord.update(WatchRecord.State.FAILED, "failed to run triggered watch [" + watchRecord.name() + "] due to thread pool capacity");
historyStore.update(watchRecord);
}
}
AlertExecution execute(ExecutionContext ctx) throws IOException {
Alert alert = ctx.alert();
Input.Result inputResult = alert.input().execute(ctx);
WatchExecution execute(WatchExecutionContext ctx) throws IOException {
Watch watch = ctx.watch();
Input.Result inputResult = watch.input().execute(ctx);
ctx.onInputResult(inputResult);
Condition.Result conditionResult = alert.condition().execute(ctx);
Condition.Result conditionResult = watch.condition().execute(ctx);
ctx.onConditionResult(conditionResult);
if (conditionResult.met()) {
Throttler.Result throttleResult = alert.throttler().throttle(ctx);
Throttler.Result throttleResult = watch.throttler().throttle(ctx);
ctx.onThrottleResult(throttleResult);
if (!throttleResult.throttle()) {
Transform transform = alert.transform();
Transform transform = watch.transform();
if (transform != null) {
Transform.Result result = alert.transform().apply(ctx, inputResult.payload());
Transform.Result result = watch.transform().apply(ctx, inputResult.payload());
ctx.onTransformResult(result);
}
for (Action action : alert.actions()) {
for (Action action : watch.actions()) {
Action.Result actionResult = action.execute(ctx);
ctx.onActionResult(actionResult);
}
@ -162,20 +162,19 @@ public class HistoryService extends AbstractComponent {
return ctx.finish();
}
void executePreviouslyFiredAlerts(HistoryStore.LoadResult loadResult) {
if (loadResult != null) {
int counter = 0;
for (FiredAlert firedAlert : loadResult) {
Alert alert = alertsStore.getAlert(firedAlert.name());
if (alert == null) {
logger.warn("unable to find alert [{}] in alert store, perhaps it has been deleted. skipping...", firedAlert.name());
continue;
}
executeAsync(firedAlert, alert);
counter++;
void executeRecords(Collection<WatchRecord> records) {
assert records != null;
int counter = 0;
for (WatchRecord record : records) {
Watch watch = watchStore.get(record.name());
if (watch == null) {
logger.warn("unable to find watch [{}] in watch store. perhaps it has been deleted. skipping...", record.name());
continue;
}
logger.debug("executed [{}] not executed previous fired alerts from the alert history index ", counter);
executeAsync(record, watch);
counter++;
}
logger.debug("executed [{}] watches from the watch history", counter);
}
private void retry(final Callback<ClusterState> callback) {
@ -204,42 +203,42 @@ public class HistoryService extends AbstractComponent {
clusterService.add(clusterStateListener);
}
private final class AlertExecutionTask implements Runnable {
private final class WatchExecutionTask implements Runnable {
private final FiredAlert firedAlert;
private final Alert alert;
private final WatchRecord watchRecord;
private final Watch watch;
private AlertExecutionTask(FiredAlert firedAlert, Alert alert) {
this.firedAlert = firedAlert;
this.alert = alert;
private WatchExecutionTask(WatchRecord watchRecord, Watch watch) {
this.watchRecord = watchRecord;
this.watch = watch;
}
@Override
public void run() {
if (!started.get()) {
logger.debug("can't run alert execution, because history service is not started, ignoring it...");
logger.debug("can't initiate watch execution as history service is not started, ignoring it...");
return;
}
AlertLockService.Lock lock = alertLockService.acquire(alert.name());
WatchLockService.Lock lock = watchLockService.acquire(watch.name());
try {
firedAlert.update(FiredAlert.State.CHECKING, null);
logger.debug("checking alert [{}]", firedAlert.name());
ExecutionContext ctx = new ExecutionContext(firedAlert.id(), alert, clock.now(), firedAlert.fireTime(), firedAlert.scheduledTime());
AlertExecution alertExecution = execute(ctx);
firedAlert.update(alertExecution);
historyStore.update(firedAlert);
watchRecord.update(WatchRecord.State.CHECKING, null);
logger.debug("checking watch [{}]", watchRecord.name());
WatchExecutionContext ctx = new WatchExecutionContext(watchRecord.id(), watch, clock.now(), watchRecord.fireTime(), watchRecord.scheduledTime());
WatchExecution execution = execute(ctx);
watchRecord.seal(execution);
historyStore.update(watchRecord);
} catch (Exception e) {
if (started()) {
logger.warn("failed to run alert [{}]", e, firedAlert.name());
logger.warn("failed to execute watch [{}]", e, watchRecord.name());
try {
firedAlert.update(FiredAlert.State.FAILED, e.getMessage());
historyStore.update(firedAlert);
watchRecord.update(WatchRecord.State.FAILED, e.getMessage());
historyStore.update(watchRecord);
} catch (Exception e2) {
logger.error("failed to update fired alert [{}] with the error message", e2, firedAlert);
logger.error("failed to update watch record [{}] failure [{}]", e2, watchRecord, e.getMessage());
}
} else {
logger.debug("failed to execute fired alert [{}] after shutdown", e, firedAlert);
logger.debug("failed to execute watch [{}] after shutdown", e, watchRecord);
}
} finally {
lock.release();
@ -254,15 +253,15 @@ public class HistoryService extends AbstractComponent {
if (!started.get()) {
throw new ElasticsearchIllegalStateException("not started");
}
Alert alert = alertsStore.getAlert(name);
if (alert == null) {
logger.warn("unable to find [{}] in the alert store, perhaps it has been deleted", name);
Watch watch = watchStore.get(name);
if (watch == null) {
logger.warn("unable to find watch [{}] in the watch store, perhaps it has been deleted", name);
return;
}
try {
HistoryService.this.fire(alert, scheduledFireTime, fireTime);
HistoryService.this.execute(watch, scheduledFireTime, fireTime);
} catch (Exception e) {
logger.error("failed to fire alert [{}]", e, name);
logger.error("failed to execute watch [{}]", e, name);
}
}
}

View File

@ -0,0 +1,166 @@
/*
* 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.watcher.history;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.watcher.support.TemplateUtils;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.joda.time.DateTime;
import org.elasticsearch.common.joda.time.format.DateTimeFormat;
import org.elasticsearch.common.joda.time.format.DateTimeFormatter;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
import java.util.*;
/**
*/
public class HistoryStore extends AbstractComponent {
public static final String INDEX_PREFIX = ".watch_history_";
public static final String DOC_TYPE = "watch_record";
public static final String INDEX_TEMPLATE_NAME = "watch_history";
static final DateTimeFormatter indexTimeFormat = DateTimeFormat.forPattern("YYYY-MM-dd");
private final ClientProxy client;
private final TemplateUtils templateUtils;
private final int scrollSize;
private final TimeValue scrollTimeout;
private final WatchRecord.Parser recordParser;
@Inject
public HistoryStore(Settings settings, ClientProxy client, TemplateUtils templateUtils, WatchRecord.Parser recordParser) {
super(settings);
this.client = client;
this.templateUtils = templateUtils;
this.recordParser = recordParser;
this.scrollTimeout = componentSettings.getAsTime("scroll.timeout", TimeValue.timeValueSeconds(30));
this.scrollSize = componentSettings.getAsInt("scroll.size", 100);
}
public void put(WatchRecord watchRecord) throws HistoryException {
String index = getHistoryIndexNameForTime(watchRecord.scheduledTime());
try {
IndexResponse response = client.prepareIndex(index, DOC_TYPE, watchRecord.id())
.setSource(XContentFactory.jsonBuilder().value(watchRecord))
.setOpType(IndexRequest.OpType.CREATE)
.get();
watchRecord.version(response.getVersion());
} catch (IOException e) {
throw new HistoryException("failed to persist watch record [" + watchRecord + "]", e);
}
}
public void update(WatchRecord watchRecord) throws HistoryException {
logger.debug("updating watch record [{}]...", watchRecord);
try {
BytesReference bytes = XContentFactory.jsonBuilder().value(watchRecord).bytes();
IndexResponse response = client.prepareIndex(getHistoryIndexNameForTime(watchRecord.scheduledTime()), DOC_TYPE, watchRecord.id())
.setSource(bytes)
.setVersion(watchRecord.version())
.get();
watchRecord.version(response.getVersion());
logger.debug("successfully updated watch record [{}]", watchRecord);
} catch (IOException e) {
throw new HistoryException("failed to update watch record [" + watchRecord + "]", e);
}
}
/**
* tries to load all watch records that await execution. If for some reason the records could not be
* loaded (e.g. the not all primary shards of the history index are active), returns {@code null}.
*/
Collection<WatchRecord> loadRecords(ClusterState state, WatchRecord.State recordState) {
String[] indices = state.metaData().concreteIndices(IndicesOptions.lenientExpandOpen(), INDEX_PREFIX + "*");
if (indices.length == 0) {
logger.debug("No .watch_history indices found. skipping loading awaiting watch records");
templateUtils.ensureIndexTemplateIsLoaded(state, INDEX_TEMPLATE_NAME);
return Collections.emptySet();
}
int numPrimaryShards = 0;
for (String index : indices) {
IndexMetaData indexMetaData = state.getMetaData().index(index);
if (indexMetaData != null) {
if (!state.routingTable().index(index).allPrimaryShardsActive()) {
logger.debug("Not all primary shards of the [{}] index are started. Schedule to retry loading awaiting watch records..", index);
return null;
} else {
numPrimaryShards += indexMetaData.numberOfShards();
}
}
}
RefreshResponse refreshResponse = client.refresh(new RefreshRequest(INDEX_PREFIX + "*"));
if (refreshResponse.getSuccessfulShards() < numPrimaryShards) {
return null;
}
SearchRequest searchRequest = createScanSearchRequest(recordState);
SearchResponse response = client.search(searchRequest);
List<WatchRecord> records = new ArrayList<>();
try {
if (response.getTotalShards() != response.getSuccessfulShards()) {
return null;
}
if (response.getHits().getTotalHits() > 0) {
response = client.searchScroll(response.getScrollId(), scrollTimeout);
while (response.getHits().hits().length != 0) {
for (SearchHit sh : response.getHits()) {
String historyId = sh.getId();
WatchRecord record = recordParser.parse(sh.getSourceRef(), historyId, sh.version());
assert record.state() == recordState;
logger.debug("loaded watch record [{}/{}/{}]", sh.index(), sh.type(), sh.id());
records.add(record);
}
response = client.searchScroll(response.getScrollId(), scrollTimeout);
}
}
} finally {
client.clearScroll(response.getScrollId());
}
templateUtils.ensureIndexTemplateIsLoaded(state, INDEX_TEMPLATE_NAME);
return records;
}
/**
* Calculates the correct history index name for a given time
*/
public static String getHistoryIndexNameForTime(DateTime time) {
return INDEX_PREFIX + indexTimeFormat.print(time);
}
private SearchRequest createScanSearchRequest(WatchRecord.State recordState) {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.termQuery(WatchRecord.Parser.STATE_FIELD.getPreferredName(), recordState.id()))
.size(scrollSize)
.version(true);
SearchRequest searchRequest = new SearchRequest(INDEX_PREFIX + "*");
searchRequest.source(sourceBuilder);
searchRequest.searchType(SearchType.SCAN);
searchRequest.types(DOC_TYPE);
searchRequest.scroll(scrollTimeout);
searchRequest.preference("_primary");
return searchRequest;
}
}

View File

@ -3,9 +3,9 @@
* 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.history;
package org.elasticsearch.watcher.history;
import org.elasticsearch.alerts.AlertsPlugin;
import org.elasticsearch.watcher.WatcherPlugin;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor;
import org.elasticsearch.threadpool.ThreadPool;
@ -15,12 +15,12 @@ import java.util.concurrent.BlockingQueue;
/**
*
*/
public class InternalAlertsExecutor implements AlertsExecutor {
public class InternalWatchExecutor implements WatchExecutor {
private final ThreadPool threadPool;
@Inject
public InternalAlertsExecutor(ThreadPool threadPool) {
public InternalWatchExecutor(ThreadPool threadPool) {
this.threadPool = threadPool;
}
@ -40,6 +40,6 @@ public class InternalAlertsExecutor implements AlertsExecutor {
}
private EsThreadPoolExecutor executor() {
return (EsThreadPoolExecutor) threadPool.executor(AlertsPlugin.NAME);
return (EsThreadPoolExecutor) threadPool.executor(WatcherPlugin.NAME);
}
}

View File

@ -3,14 +3,14 @@
* 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.history;
package org.elasticsearch.watcher.history;
import java.util.concurrent.BlockingQueue;
/**
*
*/
public interface AlertsExecutor {
public interface WatchExecutor {
BlockingQueue queue();

View File

@ -3,19 +3,19 @@
* 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.history;
package org.elasticsearch.watcher.history;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.alerts.Alert;
import org.elasticsearch.alerts.AlertExecution;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.actions.ActionRegistry;
import org.elasticsearch.alerts.condition.Condition;
import org.elasticsearch.alerts.condition.ConditionRegistry;
import org.elasticsearch.alerts.input.Input;
import org.elasticsearch.alerts.input.InputRegistry;
import org.elasticsearch.alerts.transform.TransformRegistry;
import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.watch.WatchExecution;
import org.elasticsearch.watcher.WatcherException;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.actions.ActionRegistry;
import org.elasticsearch.watcher.condition.Condition;
import org.elasticsearch.watcher.condition.ConditionRegistry;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.input.InputRegistry;
import org.elasticsearch.watcher.transform.TransformRegistry;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.bytes.BytesReference;
@ -33,7 +33,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class FiredAlert implements ToXContent {
public class WatchRecord implements ToXContent {
private String id;
private String name;
@ -42,7 +42,7 @@ public class FiredAlert implements ToXContent {
private Input input;
private Condition condition;
private State state;
private AlertExecution execution;
private WatchExecution execution;
private @Nullable String message;
private @Nullable Map<String,Object> metadata;
@ -52,18 +52,18 @@ public class FiredAlert implements ToXContent {
private final AtomicBoolean sealed = new AtomicBoolean(false);
FiredAlert() {
WatchRecord() {
}
public FiredAlert(Alert alert, DateTime scheduledTime, DateTime fireTime) {
this.id = alert.name() + "#" + scheduledTime.toDateTimeISO();
this.name = alert.name();
public WatchRecord(Watch watch, DateTime scheduledTime, DateTime fireTime) {
this.id = watch.name() + "#" + scheduledTime.toDateTimeISO();
this.name = watch.name();
this.fireTime = fireTime;
this.scheduledTime = scheduledTime;
this.condition = alert.condition();
this.input = alert.input();
this.condition = watch.condition();
this.input = watch.input();
this.state = State.AWAITS_EXECUTION;
this.metadata = alert.metadata();
this.metadata = watch.metadata();
this.version = 1;
}
@ -114,8 +114,8 @@ public class FiredAlert implements ToXContent {
this.message = message;
}
public void update(AlertExecution execution) {
assert sealed.compareAndSet(false, true) : "sealing an fired alert should only be done once";
public void seal(WatchExecution execution) {
assert sealed.compareAndSet(false, true) : "sealing a watch record should only be done once";
this.execution = execution;
if (!execution.conditionResult().met()) {
state = State.EXECUTION_NOT_NEEDED;
@ -131,10 +131,10 @@ public class FiredAlert implements ToXContent {
@Override
public XContentBuilder toXContent(XContentBuilder historyEntry, Params params) throws IOException {
historyEntry.startObject();
historyEntry.field(Parser.ALERT_NAME_FIELD.getPreferredName(), name);
historyEntry.field(Parser.WATCH_NAME_FIELD.getPreferredName(), name);
historyEntry.field(Parser.FIRE_TIME_FIELD.getPreferredName(), fireTime.toDateTimeISO());
historyEntry.field(Parser.SCHEDULED_FIRE_TIME_FIELD.getPreferredName(), scheduledTime.toDateTimeISO());
historyEntry.startObject(Alert.Parser.CONDITION_FIELD.getPreferredName()).field(condition.type(), condition, params).endObject();
historyEntry.startObject(Watch.Parser.CONDITION_FIELD.getPreferredName()).field(condition.type(), condition, params).endObject();
historyEntry.field(Parser.STATE_FIELD.getPreferredName(), state.id());
if (message != null) {
@ -145,7 +145,7 @@ public class FiredAlert implements ToXContent {
}
if (execution != null) {
historyEntry.field(Parser.ALERT_EXECUTION_FIELD.getPreferredName(), execution);
historyEntry.field(Parser.WATCH_EXECUTION_FIELD.getPreferredName(), execution);
}
historyEntry.endObject();
@ -157,7 +157,7 @@ public class FiredAlert implements ToXContent {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FiredAlert entry = (FiredAlert) o;
WatchRecord entry = (WatchRecord) o;
if (!id.equals(entry.id)) return false;
return true;
@ -190,7 +190,7 @@ public class FiredAlert implements ToXContent {
try {
return valueOf(id.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException iae) {
throw new AlertsSettingsException("unknown fired alert state [" + id + "]");
throw new WatcherSettingsException("unknown watch record state [" + id + "]");
}
}
@ -202,13 +202,13 @@ public class FiredAlert implements ToXContent {
public static class Parser extends AbstractComponent {
public static final ParseField ALERT_NAME_FIELD = new ParseField("alert_name");
public static final ParseField WATCH_NAME_FIELD = new ParseField("watch_name");
public static final ParseField FIRE_TIME_FIELD = new ParseField("fire_time");
public static final ParseField SCHEDULED_FIRE_TIME_FIELD = new ParseField("scheduled_fire_time");
public static final ParseField MESSAGE_FIELD = new ParseField("message");
public static final ParseField STATE_FIELD = new ParseField("state");
public static final ParseField METADATA_FIELD = new ParseField("meta");
public static final ParseField ALERT_EXECUTION_FIELD = new ParseField("alert_execution");
public static final ParseField WATCH_EXECUTION_FIELD = new ParseField("watch_execution");
private final ConditionRegistry conditionRegistry;
private final ActionRegistry actionRegistry;
@ -225,18 +225,18 @@ public class FiredAlert implements ToXContent {
this.transformRegistry = transformRegistry;
}
public FiredAlert parse(BytesReference source, String historyId, long version) {
public WatchRecord parse(BytesReference source, String historyId, long version) {
try (XContentParser parser = XContentHelper.createParser(source)) {
return parse(parser, historyId, version);
} catch (IOException e) {
throw new ElasticsearchException("Error during parsing alert record", e);
throw new ElasticsearchException("unable to parse watch record", e);
}
}
public FiredAlert parse(XContentParser parser, String id, long version) throws IOException {
FiredAlert alert = new FiredAlert();
alert.id = id;
alert.version = version;
public WatchRecord parse(XContentParser parser, String id, long version) throws IOException {
WatchRecord record = new WatchRecord();
record.id = id;
record.version = version;
String currentFieldName = null;
XContentParser.Token token = parser.nextToken();
@ -245,37 +245,37 @@ public class FiredAlert implements ToXContent {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if (Alert.Parser.INPUT_FIELD.match(currentFieldName)) {
alert.input = inputRegistry.parse(parser);
} else if (Alert.Parser.CONDITION_FIELD.match(currentFieldName)) {
alert.condition = conditionRegistry.parse(parser);
if (Watch.Parser.INPUT_FIELD.match(currentFieldName)) {
record.input = inputRegistry.parse(parser);
} else if (Watch.Parser.CONDITION_FIELD.match(currentFieldName)) {
record.condition = conditionRegistry.parse(parser);
} else if (METADATA_FIELD.match(currentFieldName)) {
alert.metadata = parser.map();
} else if (ALERT_EXECUTION_FIELD.match(currentFieldName)) {
alert.execution = AlertExecution.Parser.parse(parser, conditionRegistry, actionRegistry, inputRegistry, transformRegistry);
record.metadata = parser.map();
} else if (WATCH_EXECUTION_FIELD.match(currentFieldName)) {
record.execution = WatchExecution.Parser.parse(parser, conditionRegistry, actionRegistry, inputRegistry, transformRegistry);
} else {
throw new AlertsException("unable to parse fired alert. unexpected field [" + currentFieldName + "]");
throw new WatcherException("unable to parse watch record. unexpected field [" + currentFieldName + "]");
}
} else if (token.isValue()) {
if (ALERT_NAME_FIELD.match(currentFieldName)) {
alert.name = parser.text();
if (WATCH_NAME_FIELD.match(currentFieldName)) {
record.name = parser.text();
} else if (FIRE_TIME_FIELD.match(currentFieldName)) {
alert.fireTime = DateTime.parse(parser.text());
record.fireTime = DateTime.parse(parser.text());
} else if (SCHEDULED_FIRE_TIME_FIELD.match(currentFieldName)) {
alert.scheduledTime = DateTime.parse(parser.text());
record.scheduledTime = DateTime.parse(parser.text());
} else if (MESSAGE_FIELD.match(currentFieldName)) {
alert.message = parser.textOrNull();
record.message = parser.textOrNull();
} else if (STATE_FIELD.match(currentFieldName)) {
alert.state = State.resolve(parser.text());
record.state = State.resolve(parser.text());
} else {
throw new AlertsException("unable to parse fired alert. unexpected field [" + currentFieldName + "]");
throw new WatcherException("unable to parse watch record. unexpected field [" + currentFieldName + "]");
}
} else {
throw new AlertsException("unable to parse fired alert. unexpected token [" + token + "] for [" + currentFieldName + "]");
throw new WatcherException("unable to parse watch record. unexpected token [" + token + "] for [" + currentFieldName + "]");
}
}
return alert;
return record;
}
}
}

View File

@ -3,10 +3,10 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.xcontent.ToXContent;
@ -34,7 +34,7 @@ public abstract class Input<R extends Input.Result> implements ToXContent {
/**
* Executes this input
*/
public abstract R execute(ExecutionContext ctx) throws IOException;
public abstract R execute(WatchExecutionContext ctx) throws IOException;
/**

View File

@ -3,12 +3,12 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.alerts.input.search.SearchInput;
import org.elasticsearch.alerts.input.simple.SimpleInput;
import org.elasticsearch.watcher.input.search.SearchInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import java.util.HashMap;
import java.util.Map;

View File

@ -3,14 +3,14 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.watcher.WatcherException;
/**
*
*/
public class InputException extends AlertsException {
public class InputException extends WatcherException {
public InputException(String msg) {
super(msg);

View File

@ -3,10 +3,10 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.alerts.input.search.SearchInput;
import org.elasticsearch.alerts.input.simple.SimpleInput;
import org.elasticsearch.watcher.input.search.SearchInput;
import org.elasticsearch.watcher.input.simple.SimpleInput;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;

View File

@ -3,7 +3,7 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.inject.Inject;

View File

@ -3,10 +3,10 @@
* 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.input;
package org.elasticsearch.watcher.input;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.logging.ESLogger;
@ -46,7 +46,7 @@ public class NoneInput extends Input<NoneInput.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
return Result.INSTANCE;
}

View File

@ -3,20 +3,20 @@
* 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.input.search;
package org.elasticsearch.watcher.input.search;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.input.Input;
import org.elasticsearch.alerts.input.InputException;
import org.elasticsearch.alerts.support.AlertUtils;
import org.elasticsearch.alerts.support.SearchRequestEquivalence;
import org.elasticsearch.alerts.support.Variables;
import org.elasticsearch.alerts.support.init.proxy.ClientProxy;
import org.elasticsearch.alerts.support.init.proxy.ScriptServiceProxy;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.input.InputException;
import org.elasticsearch.watcher.support.WatcherUtils;
import org.elasticsearch.watcher.support.SearchRequestEquivalence;
import org.elasticsearch.watcher.support.Variables;
import org.elasticsearch.watcher.support.init.proxy.ClientProxy;
import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
@ -37,10 +37,10 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.alerts.support.AlertsDateUtils.formatDate;
import static org.elasticsearch.watcher.support.WatcherDateUtils.formatDate;
/**
* This class just defines an input that runs a search
* An input that executes search and returns the search response as the initial payload
*/
public class SearchInput extends Input<SearchInput.Result> {
@ -66,17 +66,17 @@ public class SearchInput extends Input<SearchInput.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
SearchRequest request = createSearchRequestWithTimes(this.searchRequest, ctx.scheduledTime(), ctx.fireTime(), ctx.executionTime(), scriptService);
if (logger.isTraceEnabled()) {
logger.trace("[{}] running query for [{}] [{}]", ctx.id(), ctx.alert().name(), XContentHelper.convertToJson(request.source(), false, true));
logger.trace("[{}] running query for [{}] [{}]", ctx.id(), ctx.watch().name(), XContentHelper.convertToJson(request.source(), false, true));
}
// actionGet deals properly with InterruptedException
SearchResponse response = client.search(request);
if (logger.isDebugEnabled()) {
logger.debug("[{}] found [{}] hits", ctx.id(), ctx.alert().name(), response.getHits().getTotalHits());
logger.debug("[{}] found [{}] hits", ctx.id(), ctx.watch().name(), response.getHits().getTotalHits());
for (SearchHit hit : response.getHits()) {
logger.debug("[{}] hit [{}]", ctx.id(), XContentHelper.toString(hit));
}
@ -88,7 +88,7 @@ public class SearchInput extends Input<SearchInput.Result> {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return AlertUtils.writeSearchRequest(searchRequest, builder, params);
return WatcherUtils.writeSearchRequest(searchRequest, builder, params);
}
@Override
@ -153,7 +153,7 @@ public class SearchInput extends Input<SearchInput.Result> {
@Override
protected XContentBuilder toXContentBody(XContentBuilder builder, Params params) throws IOException {
builder.field(Parser.REQUEST_FIELD.getPreferredName());
return AlertUtils.writeSearchRequest(request, builder, params);
return WatcherUtils.writeSearchRequest(request, builder, params);
}
}
@ -177,7 +177,7 @@ public class SearchInput extends Input<SearchInput.Result> {
@Override
public SearchInput parse(XContentParser parser) throws IOException {
SearchRequest request = AlertUtils.readSearchRequest(parser, DEFAULT_SEARCH_TYPE);
SearchRequest request = WatcherUtils.readSearchRequest(parser, DEFAULT_SEARCH_TYPE);
if (request == null) {
throw new InputException("could not parse [search] input. search request is missing or null.");
}
@ -198,7 +198,7 @@ public class SearchInput extends Input<SearchInput.Result> {
if (Input.Result.PAYLOAD_FIELD.match(currentFieldName)) {
payload = new Payload.XContent(parser);
} else if (REQUEST_FIELD.match(currentFieldName)) {
request = AlertUtils.readSearchRequest(parser, DEFAULT_SEARCH_TYPE);
request = WatcherUtils.readSearchRequest(parser, DEFAULT_SEARCH_TYPE);
} else {
throw new InputException("unable to parse [" + TYPE + "] input result. unexpected field [" + currentFieldName + "]");
}
@ -234,7 +234,7 @@ public class SearchInput extends Input<SearchInput.Result> {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
return AlertUtils.writeSearchRequest(request, builder, params);
return WatcherUtils.writeSearchRequest(request, builder, params);
}
}
}

View File

@ -3,22 +3,20 @@
* 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.input.simple;
package org.elasticsearch.watcher.input.simple;
import org.elasticsearch.alerts.ExecutionContext;
import org.elasticsearch.alerts.Payload;
import org.elasticsearch.alerts.input.Input;
import org.elasticsearch.alerts.input.InputException;
import org.elasticsearch.watcher.watch.WatchExecutionContext;
import org.elasticsearch.watcher.watch.Payload;
import org.elasticsearch.watcher.input.Input;
import org.elasticsearch.watcher.input.InputException;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@ -42,7 +40,7 @@ public class SimpleInput extends Input<SimpleInput.Result> {
}
@Override
public Result execute(ExecutionContext ctx) throws IOException {
public Result execute(WatchExecutionContext ctx) throws IOException {
return new Result(TYPE, payload);
}

View File

@ -0,0 +1,33 @@
/*
* 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.watcher.rest;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.watcher.client.WatcherClient;
/**
*
*/
public abstract class WatcherRestHandler extends BaseRestHandler {
protected static String URI_BASE = "_watcher";
public WatcherRestHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
}
@Override
protected final void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
handleRequest(request, channel, new WatcherClient(client));
}
protected abstract void handleRequest(RestRequest request, RestChannel channel, WatcherClient client) throws Exception;
}

View File

@ -3,9 +3,9 @@
* 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.rest;
package org.elasticsearch.watcher.rest;
import org.elasticsearch.alerts.rest.action.*;
import org.elasticsearch.watcher.rest.action.*;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.inject.PreProcessModule;
@ -14,18 +14,19 @@ import org.elasticsearch.rest.RestModule;
/**
*
*/
public class AlertsRestModule extends AbstractModule implements PreProcessModule {
public class WatcherRestModule extends AbstractModule implements PreProcessModule {
@Override
public void processModule(Module module) {
if (module instanceof RestModule) {
RestModule restModule = (RestModule) module;
restModule.addRestAction(RestPutAlertAction.class);
restModule.addRestAction(RestDeleteAlertAction.class);
restModule.addRestAction(RestAlertsStatsAction.class);
restModule.addRestAction(RestGetAlertAction.class);
restModule.addRestAction(RestAlertServiceAction.class);
restModule.addRestAction(RestAckAlertAction.class);
restModule.addRestAction(RestPutWatchAction.class);
restModule.addRestAction(RestDeleteWatchAction.class);
restModule.addRestAction(RestWatcherStatsAction.class);
restModule.addRestAction(RestWatcherInfoAction.class);
restModule.addRestAction(RestGetWatchAction.class);
restModule.addRestAction(RestWatchServiceAction.class);
restModule.addRestAction(RestAckWatchAction.class);
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.watch.Watch;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchRequest;
import org.elasticsearch.watcher.transport.actions.ack.AckWatchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
/**
* The rest action to ack a watch
*/
public class RestAckWatchAction extends WatcherRestHandler {
@Inject
protected RestAckWatchAction(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
controller.registerHandler(RestRequest.Method.PUT, URI_BASE + "/watch/{name}/_ack", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel restChannel, WatcherClient client) throws Exception {
AckWatchRequest ackWatchRequest = new AckWatchRequest(request.param("name"));
client.ackWatch(ackWatchRequest, new RestBuilderListener<AckWatchResponse>(restChannel) {
@Override
public RestResponse buildResponse(AckWatchResponse response, XContentBuilder builder) throws Exception {
return new BytesRestResponse(RestStatus.OK, builder.startObject()
.field(Watch.Parser.STATUS_FIELD.getPreferredName(), response.getStatus().toString())
.endObject());
}
});
}
}

View File

@ -3,19 +3,19 @@
* 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.rest.action;
package org.elasticsearch.watcher.rest.action;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.alerts.AlertsStore;
import org.elasticsearch.alerts.client.AlertsClient;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertRequest;
import org.elasticsearch.alerts.transport.actions.delete.DeleteAlertResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchRequest;
import org.elasticsearch.watcher.transport.actions.delete.DeleteWatchResponse;
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
@ -23,36 +23,27 @@ import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestDeleteAlertAction extends BaseRestHandler {
private final AlertsClient alertsClient;
public class RestDeleteWatchAction extends WatcherRestHandler {
@Inject
public RestDeleteAlertAction(Settings settings, RestController controller, Client client, AlertsClient alertsClient) {
public RestDeleteWatchAction(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
this.alertsClient = alertsClient;
controller.registerHandler(DELETE, AlertsStore.ALERT_INDEX + "/alert/{name}", this);
controller.registerHandler(DELETE, URI_BASE + "/watch/{name}", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
DeleteAlertRequest indexAlertRequest = new DeleteAlertRequest();
indexAlertRequest.setAlertName(request.param("name"));
alertsClient.deleteAlert(indexAlertRequest, new RestBuilderListener<DeleteAlertResponse>(channel) {
protected void handleRequest(RestRequest request, RestChannel channel, WatcherClient client) throws Exception {
DeleteWatchRequest indexWatchRequest = new DeleteWatchRequest(request.param("name"));
client.deleteWatch(indexWatchRequest, new RestBuilderListener<DeleteWatchResponse>(channel) {
@Override
public RestResponse buildResponse(DeleteAlertResponse result, XContentBuilder builder) throws Exception {
public RestResponse buildResponse(DeleteWatchResponse result, XContentBuilder builder) throws Exception {
DeleteResponse deleteResponse = result.deleteResponse();
builder.startObject()
.field("found", deleteResponse.isFound())
.field("_index", deleteResponse.getIndex())
.field("_type", deleteResponse.getType())
.field("_id", deleteResponse.getId())
.field("_version", deleteResponse.getVersion())
.endObject();
RestStatus status = OK;
if (!deleteResponse.isFound()) {
status = NOT_FOUND;
}
RestStatus status = deleteResponse.isFound() ? OK : NOT_FOUND;
return new BytesRestResponse(status, builder);
}
});

View File

@ -0,0 +1,51 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.transport.actions.get.GetWatchRequest;
import org.elasticsearch.watcher.transport.actions.get.GetWatchResponse;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
import static org.elasticsearch.rest.RestStatus.OK;
public class RestGetWatchAction extends WatcherRestHandler {
@Inject
public RestGetWatchAction(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
controller.registerHandler(GET, URI_BASE + "/watch/{name}", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, WatcherClient client) throws Exception {
final GetWatchRequest getWatchRequest = new GetWatchRequest(request.param("name"));
client.getWatch(getWatchRequest, new RestBuilderListener<GetWatchResponse>(channel) {
@Override
public RestResponse buildResponse(GetWatchResponse response, XContentBuilder builder) throws Exception {
GetResponse getResponse = response.getResponse();
builder.startObject()
.field("found", getResponse.isExists())
.field("_id", getResponse.getId())
.field("_version", getResponse.getVersion())
.field("watch", getResponse.getSource())
.endObject();
RestStatus status = getResponse.isExists() ? OK : NOT_FOUND;
return new BytesRestResponse(status, builder);
}
});
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.transport.actions.put.PutWatchRequest;
import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse;
import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT;
import static org.elasticsearch.rest.RestStatus.CREATED;
import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestPutWatchAction extends WatcherRestHandler {
@Inject
public RestPutWatchAction(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
controller.registerHandler(POST, URI_BASE + "/watch/{name}", this);
controller.registerHandler(PUT, URI_BASE + "/watch/{name}", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, WatcherClient client) throws Exception {
PutWatchRequest putWatchRequest = new PutWatchRequest(request.param("name"), request.content(), request.contentUnsafe());
client.putWatch(putWatchRequest, new RestBuilderListener<PutWatchResponse>(channel) {
@Override
public RestResponse buildResponse(PutWatchResponse response, XContentBuilder builder) throws Exception {
IndexResponse indexResponse = response.indexResponse();
builder.startObject()
.field("_id", indexResponse.getId())
.field("_version", indexResponse.getVersion())
.field("created", indexResponse.isCreated())
.endObject();
RestStatus status = indexResponse.isCreated() ? CREATED : OK;
return new BytesRestResponse(status, builder);
}
});
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.watcher.watch.WatchStore;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceRequest;
import org.elasticsearch.watcher.transport.actions.service.WatcherServiceResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
/**
*/
public class RestWatchServiceAction extends BaseRestHandler {
@Inject
protected RestWatchServiceAction(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
controller.registerHandler(RestRequest.Method.PUT, WatchStore.INDEX + "/_restart", this);
controller.registerHandler(RestRequest.Method.PUT, WatchStore.INDEX + "/_start", new StartRestHandler(settings, controller, client));
controller.registerHandler(RestRequest.Method.PUT, WatchStore.INDEX + "/_stop", new StopRestHandler(settings, controller, client));
}
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
new WatcherClient(client).watcherService(new WatcherServiceRequest().restart(), new AcknowledgedRestListener<WatcherServiceResponse>(channel));
}
static class StartRestHandler extends BaseRestHandler {
public StartRestHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
}
@Override
public void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
new WatcherClient(client).watcherService(new WatcherServiceRequest().start(), new AcknowledgedRestListener<WatcherServiceResponse>(channel));
}
}
static class StopRestHandler extends BaseRestHandler {
public StopRestHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
}
@Override
public void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
new WatcherClient(client).watcherService(new WatcherServiceRequest().stop(), new AcknowledgedRestListener<WatcherServiceResponse>(channel));
}
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequest;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK;
public class RestWatcherInfoAction extends WatcherRestHandler {
private final WatcherClient watcherClient;
@Inject
protected RestWatcherInfoAction(Settings settings, RestController controller, Client client, WatcherClient watcherClient) {
super(settings, controller, client);
this.watcherClient = watcherClient;
controller.registerHandler(GET, URI_BASE, this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel restChannel, WatcherClient client) throws Exception {
watcherClient.watcherStats(new WatcherStatsRequest(), new RestBuilderListener<WatcherStatsResponse>(restChannel) {
@Override
public RestResponse buildResponse(WatcherStatsResponse watcherStatsResponse, XContentBuilder builder) throws Exception {
builder.startObject("version")
.field("number", watcherStatsResponse.getVersion().number())
.field("build_hash", watcherStatsResponse.getBuild().hash())
.field("build_timestamp", watcherStatsResponse.getBuild().timestamp())
.field("build_snapshot", watcherStatsResponse.getVersion().snapshot)
.endObject();
return new BytesRestResponse(OK, builder);
}
});
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.watcher.rest.action;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.watcher.client.WatcherClient;
import org.elasticsearch.watcher.rest.WatcherRestHandler;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsResponse;
import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsRequest;
import java.util.Locale;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK;
public class RestWatcherStatsAction extends WatcherRestHandler {
private final WatcherClient watcherClient;
@Inject
protected RestWatcherStatsAction(Settings settings, RestController controller, Client client, WatcherClient watcherClient) {
super(settings, controller, client);
this.watcherClient = watcherClient;
controller.registerHandler(GET, URI_BASE + "/stats", this);
}
@Override
protected void handleRequest(RestRequest request, RestChannel restChannel, WatcherClient client) throws Exception {
watcherClient.watcherStats(new WatcherStatsRequest(), new RestBuilderListener<WatcherStatsResponse>(restChannel) {
@Override
public RestResponse buildResponse(WatcherStatsResponse watcherStatsResponse, XContentBuilder builder) throws Exception {
builder.field("watch_service_state", watcherStatsResponse.getWatchServiceState().toString().toLowerCase(Locale.ROOT))
.field("watch_count", watcherStatsResponse.getWatchesCount());
builder.startObject("execution_queue")
.field("size", watcherStatsResponse.getExecutionQueueSize())
.field("max_size", watcherStatsResponse.getWatchExecutionQueueMaxSize())
.endObject();
return new BytesRestResponse(OK, builder);
}
});
}
}

View File

@ -3,14 +3,14 @@
* 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.scheduler;
package org.elasticsearch.watcher.scheduler;
import org.elasticsearch.alerts.AlertsPlugin;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.scheduler.schedule.CronnableSchedule;
import org.elasticsearch.alerts.scheduler.schedule.IntervalSchedule;
import org.elasticsearch.alerts.scheduler.schedule.Schedule;
import org.elasticsearch.alerts.support.clock.Clock;
import org.elasticsearch.watcher.WatcherPlugin;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.scheduler.schedule.CronnableSchedule;
import org.elasticsearch.watcher.scheduler.schedule.IntervalSchedule;
import org.elasticsearch.watcher.scheduler.schedule.Schedule;
import org.elasticsearch.watcher.support.clock.Clock;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.joda.time.DateTime;
@ -25,7 +25,7 @@ import org.quartz.simpl.SimpleJobFactory;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.elasticsearch.alerts.scheduler.FireAlertQuartzJob.jobDetail;
import static org.elasticsearch.watcher.scheduler.WatcherQuartzJob.jobDetail;
public class InternalScheduler extends AbstractComponent implements Scheduler {
@ -49,7 +49,7 @@ public class InternalScheduler extends AbstractComponent implements Scheduler {
try {
this.defaultTimeZone = DateTimeZone.forID(timeZoneStr);
} catch (IllegalArgumentException iae) {
throw new AlertsSettingsException("unrecognized time zone setting [" + timeZoneStr + "]", iae);
throw new WatcherSettingsException("unrecognized time zone setting [" + timeZoneStr + "]", iae);
}
}
@ -59,7 +59,7 @@ public class InternalScheduler extends AbstractComponent implements Scheduler {
logger.info("Starting scheduler");
// Can't start a scheduler that has been shutdown, so we need to re-create each time start() is invoked
Properties properties = new Properties();
properties.setProperty("org.quartz.threadPool.class", AlertQuartzThreadPool.class.getName());
properties.setProperty("org.quartz.threadPool.class", WatcherQuartzThreadPool.class.getName());
properties.setProperty(StdSchedulerFactory.PROP_SCHED_SKIP_UPDATE_CHECK, "true");
properties.setProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN, "true");
properties.setProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN_WITH_WAIT, "true");
@ -67,8 +67,8 @@ public class InternalScheduler extends AbstractComponent implements Scheduler {
scheduler = schFactory.getScheduler();
scheduler.setJobFactory(new SimpleJobFactory());
Map<JobDetail, Set<? extends Trigger>> quartzJobs = new HashMap<>();
for (Job alert : jobs) {
quartzJobs.put(jobDetail(alert.name(), this), createTrigger(alert.schedule(), defaultTimeZone, clock));
for (Job job : jobs) {
quartzJobs.put(jobDetail(job.name(), this), createTrigger(job.schedule(), defaultTimeZone, clock));
}
scheduler.scheduleJobs(quartzJobs, false);
scheduler.start();
@ -96,16 +96,16 @@ public class InternalScheduler extends AbstractComponent implements Scheduler {
listeners.add(listener);
}
void notifyListeners(String alertName, JobExecutionContext ctx) {
void notifyListeners(String name, JobExecutionContext ctx) {
DateTime scheduledTime = new DateTime(ctx.getScheduledFireTime());
DateTime fireTime = new DateTime(ctx.getFireTime());
for (Listener listener : listeners) {
listener.fire(alertName, scheduledTime, fireTime);
listener.fire(name, scheduledTime, fireTime);
}
}
/**
* Schedules the given alert
* Schedules the given job
*/
public void add(Job job) {
try {
@ -147,13 +147,13 @@ public class InternalScheduler extends AbstractComponent implements Scheduler {
}
// This Quartz thread pool will always accept. On this thread we will only index an alert action and add it to the work queue
public static final class AlertQuartzThreadPool implements org.quartz.spi.ThreadPool {
// This Quartz thread pool will always accept. On this thread we will only index a watch record and add it to the work queue
public static final class WatcherQuartzThreadPool implements org.quartz.spi.ThreadPool {
private final EsThreadPoolExecutor executor;
public AlertQuartzThreadPool() {
this.executor = (EsThreadPoolExecutor) threadPool.executor(AlertsPlugin.SCHEDULER_THREAD_POOL_NAME);
public WatcherQuartzThreadPool() {
this.executor = (EsThreadPoolExecutor) threadPool.executor(WatcherPlugin.SCHEDULER_THREAD_POOL_NAME);
}
@Override

View File

@ -3,9 +3,9 @@
* 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.scheduler;
package org.elasticsearch.watcher.scheduler;
import org.elasticsearch.alerts.scheduler.schedule.Schedule;
import org.elasticsearch.watcher.scheduler.schedule.Schedule;
import org.elasticsearch.common.joda.time.DateTime;
import java.util.Collection;

View File

@ -3,14 +3,14 @@
* 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.scheduler;
package org.elasticsearch.watcher.scheduler;
import org.elasticsearch.alerts.AlertsException;
import org.elasticsearch.watcher.WatcherException;
/**
*
*/
public class SchedulerException extends AlertsException {
public class SchedulerException extends WatcherException {
public SchedulerException(String msg) {
super(msg);

View File

@ -3,9 +3,9 @@
* 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.scheduler;
package org.elasticsearch.watcher.scheduler;
import org.elasticsearch.alerts.scheduler.schedule.*;
import org.elasticsearch.watcher.scheduler.schedule.*;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;

View File

@ -3,30 +3,30 @@
* 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.scheduler;
package org.elasticsearch.watcher.scheduler;
import org.quartz.*;
public class FireAlertQuartzJob implements Job {
public class WatcherQuartzJob implements Job {
static final String SCHEDULER_KEY = "scheduler";
public FireAlertQuartzJob() {
public WatcherQuartzJob() {
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
String alertName = jobExecutionContext.getJobDetail().getKey().getName();
String watchName = jobExecutionContext.getJobDetail().getKey().getName();
InternalScheduler scheduler = (InternalScheduler) jobExecutionContext.getJobDetail().getJobDataMap().get(SCHEDULER_KEY);
scheduler.notifyListeners(alertName, jobExecutionContext);
scheduler.notifyListeners(watchName, jobExecutionContext);
}
static JobKey jobKey(String alertName) {
return new JobKey(alertName);
static JobKey jobKey(String watchName) {
return new JobKey(watchName);
}
static JobDetail jobDetail(String alertName, InternalScheduler scheduler) {
JobDetail job = JobBuilder.newJob(FireAlertQuartzJob.class).withIdentity(alertName).build();
static JobDetail jobDetail(String watchName, InternalScheduler scheduler) {
JobDetail job = JobBuilder.newJob(WatcherQuartzJob.class).withIdentity(watchName).build();
job.getJobDataMap().put("scheduler", scheduler);
return job;
}

View File

@ -3,9 +3,9 @@
* 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.scheduler.schedule;
package org.elasticsearch.watcher.scheduler.schedule;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.quartz.CronExpression;
@ -69,24 +69,24 @@ public class CronSchedule extends CronnableSchedule {
crons.add(parser.text());
break;
default:
throw new AlertsSettingsException("could not parse [cron] schedule. expected a string value in the cron array but found [" + token + "]");
throw new WatcherSettingsException("could not parse [cron] schedule. expected a string value in the cron array but found [" + token + "]");
}
}
if (crons.isEmpty()) {
throw new AlertsSettingsException("could not parse [cron] schedule. no cron expression found in cron array");
throw new WatcherSettingsException("could not parse [cron] schedule. no cron expression found in cron array");
}
return new CronSchedule(crons.toArray(new String[crons.size()]));
} else {
throw new AlertsSettingsException("could not parse [cron] schedule. expected either a cron string value or an array of cron string values, but found [" + token + "]");
throw new WatcherSettingsException("could not parse [cron] schedule. expected either a cron string value or an array of cron string values, but found [" + token + "]");
}
} catch (ValidationException ve) {
throw new AlertsSettingsException("could not parse [cron] schedule. invalid cron expression [" + ve.expression + "]", ve);
throw new WatcherSettingsException("could not parse [cron] schedule. invalid cron expression [" + ve.expression + "]", ve);
}
}
}
public static class ValidationException extends AlertsSettingsException {
public static class ValidationException extends WatcherSettingsException {
private String expression;

View File

@ -3,7 +3,7 @@
* 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.scheduler.schedule;
package org.elasticsearch.watcher.scheduler.schedule;
import java.util.Arrays;
import java.util.Objects;

View File

@ -3,10 +3,10 @@
* 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.scheduler.schedule;
package org.elasticsearch.watcher.scheduler.schedule;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.scheduler.schedule.support.DayTimes;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.scheduler.schedule.support.DayTimes;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@ -92,19 +92,19 @@ public class DailySchedule extends CronnableSchedule {
try {
times.add(DayTimes.parse(parser, token));
} catch (DayTimes.ParseException pe) {
throw new AlertsSettingsException("could not parse [daily] schedule. invalid time value for field [at] - [" + token + "]", pe);
throw new WatcherSettingsException("could not parse [daily] schedule. invalid time value for field [at] - [" + token + "]", pe);
}
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
try {
times.add(DayTimes.parse(parser, token));
} catch (DayTimes.ParseException pe) {
throw new AlertsSettingsException("could not parse [daily] schedule. invalid time value for field [at] - [" + token + "]", pe);
throw new WatcherSettingsException("could not parse [daily] schedule. invalid time value for field [at] - [" + token + "]", pe);
}
}
}
} else {
throw new AlertsSettingsException("could not parse [daily] schedule. unexpected field [" + currentFieldName + "]");
throw new WatcherSettingsException("could not parse [daily] schedule. unexpected field [" + currentFieldName + "]");
}
}

View File

@ -3,10 +3,10 @@
* 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.scheduler.schedule;
package org.elasticsearch.watcher.scheduler.schedule;
import org.elasticsearch.alerts.AlertsSettingsException;
import org.elasticsearch.alerts.scheduler.schedule.support.DayTimes;
import org.elasticsearch.watcher.WatcherSettingsException;
import org.elasticsearch.watcher.scheduler.schedule.support.DayTimes;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.primitives.Ints;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -70,7 +70,7 @@ public class HourlySchedule extends CronnableSchedule {
sb.append(",");
}
if (!validMinute(minutes[i])) {
throw new AlertsSettingsException("invalid hourly minute [" + minutes[i] + "]. minute must be between 0 and 59 incl.");
throw new WatcherSettingsException("invalid hourly minute [" + minutes[i] + "]. minute must be between 0 and 59 incl.");
}
sb.append(minutes[i]);
}
@ -104,21 +104,21 @@ public class HourlySchedule extends CronnableSchedule {
try {
minutes.add(DayTimes.parseMinuteValue(parser, token));
} catch (DayTimes.ParseException pe) {
throw new AlertsSettingsException("could not parse [hourly] schedule. invalid value for [minute]", pe);
throw new WatcherSettingsException("could not parse [hourly] schedule. invalid value for [minute]", pe);
}
} else if (token == XContentParser.Token.START_ARRAY) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
try {
minutes.add(DayTimes.parseMinuteValue(parser, token));
} catch (DayTimes.ParseException pe) {
throw new AlertsSettingsException("could not parse [hourly] schedule. invalid value for [minute]", pe);
throw new WatcherSettingsException("could not parse [hourly] schedule. invalid value for [minute]", pe);
}
}
} else {
throw new AlertsSettingsException("could not parse [hourly] schedule. invalid minute value. expected either string/value or an array of string/number values, but found [" + token + "]");
throw new WatcherSettingsException("could not parse [hourly] schedule. invalid minute value. expected either string/value or an array of string/number values, but found [" + token + "]");
}
} else {
throw new AlertsSettingsException("could not parse [hourly] schedule. unexpected field [" + currentFieldName + "]");
throw new WatcherSettingsException("could not parse [hourly] schedule. unexpected field [" + currentFieldName + "]");
}
}

Some files were not shown because too many files have changed in this diff Show More