Java API
editJava API
editWatcher provides a Java client called WatcherClient that adds support for the Watcher APIs to the standard Java client that ships with Elasticsearch (Transport Client.
Installing WatcherClient
editTo use the WatcherClient
you will need to make sure the watcher
JAR file is in the classpath. You can
extract the jar from the downloaded watcher plugin itself.
If you use Maven to manage dependencies, add the following to the pom.xml
:
<project ...> <repositories> <!-- add the elasticsearch repo --> <repository> <id>elasticsearch-releases</id> <url>http://artifacts.elastic.co/maven</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> ... </repositories> ... <dependencies> <!-- add the Watcher jar as a dependency --> <dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>watcher</artifactId> <version>2.3.5</version> </dependency> ... </dependencies> ... </project>
If you use Gradle, add the dependencies to build.gradle
:
repositories { /* ... Any other repositories ... */ // Add the Elasticsearch Maven Repository maven { url "http://artifacts.elastic.co/maven" } } dependencies { // Provide the Watcher jar on the classpath for compilation and at runtime compile "org.elasticsearch.plugin:watcher:2.3.5" /* ... */ }
You can manually download the Watcher JAR directly from our Maven repository.
Creating the WatcherClient
editCreating the WatcherClient
can simply be done as the following snippet shows:
import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.watcher.client.WatcherClient; import org.elasticsearch.watcher.WatcherPlugin; ... TransportClient client = TransportClient.builder() .settings(Settings.builder() .put("cluster.name", "myClusterName") ... .build()) .addPlugin(WatcherPlugin.class) .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)); WatcherClient watcherClient = new WatcherClient(client);
PUT Watch API
editThe PUT watch API either registers a new watch in Watcher or update an existing one. Once registered, a new document
will be added to the .watches
index, representing the watch, and the watch’s trigger will immediately be registered
with the relevant trigger engine (typically the scheduler, for the schedule
trigger).
Putting a watch must be done via this API only. Do not put a watch directly to the .watches
index
using Elasticsearch’s Index API. When integrating with Shield, a best practice is to make sure
no write
privileges are granted to anyone over the .watches
API.
The following example adds an watch with the my-watch
id that has the following qualities:
- The watch schedule triggers every minute.
- The watch search input finds any 404 HTTP responses that occurred in the past five minutes.
- The watch condition checks the search results for 404s.
- The watch action sends an email if there are any 404s.
WatchSourceBuilder watchSourceBuilder = WatchSourceBuilders.watchBuilder(); // Set the trigger watchSourceBuilder.trigger(TriggerBuilders.schedule(Schedules.cron("0 0/1 * * * ?"))); // Create the search request to use for the input SearchRequest request = Requests.searchRequest("idx").source(searchSource() .query(filteredQuery(matchQuery("response", 404), boolFilter() .must(rangeFilter("date").gt("{{ctx.trigger.scheduled_time}}")) .must(rangeFilter("date").lt("{{ctx.execution_time}}"))))); // Set the input watchSourceBuilder.input(new SearchInput(request, null)); // Set the condition watchSourceBuilder.condition(new ScriptCondition(Script.inline("ctx.payload.hits.total > 1").build())); // Create the email template to use for the action EmailTemplate.Builder emailBuilder = EmailTemplate.builder(); emailBuilder.to("someone@domain.host.com"); emailBuilder.subject("404 recently encountered"); EmailAction.Builder emailActionBuilder = EmailAction.builder(emailBuilder.build()); // Add the action watchSourceBuilder.addAction("email_someone", emailActionBuilder.build()); PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("my-watch") .setSource(watchSourceBuilder) .get();
While the above snippet flashes out all the concrete classes that make our watch, using the available builder classes along with static imports can significantly simplify and compact your code:
PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("my-watch") .setSource(watchBuilder() .trigger(schedule(cron("0 0/1 * * * ?"))) .input(searchInput(searchRequest("idx").source(searchSource() .query(filteredQuery(matchQuery("response", 404), boolFilter() .must(rangeFilter("date").gt("{{ctx.trigger.scheduled_time}}")) .must(rangeFilter("date").lt("{{ctx.execution_time}}"))))))) .condition(scriptCondition("ctx.payload.hits.total > 1")) .addAction("email_someone", emailAction(EmailTemplate.builder() .to("someone@domain.host.com") .subject("404 recently encountered")))) .get();
-
Use
TriggerBuilders
andSchedules
classes to define the trigger -
Use
InputBuilders
class to define the input -
Use
ConditionBuilders
class to define the condition -
Use
ActionBuilders
to define the actions
Get Watch API
editThis API retrieves a watch by its id.
The following example gets a watch with my-watch
id:
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get();
You can access the watch definition by accessing the source of the response:
XContentSource source = getWatchResponse.getSource();
The XContentSource
provides you methods to explore the source:
Map<String, Object> map = source.getAsMap();
Or get a specific value associated with a known key:
String host = source.getValue("input.http.request.host");
Delete Watch API
editThe DELETE watch API removes a specific watch (identified by its id
) from Watcher. Once removed, the document
representing the watchin the .watches
index will be gone and it will never be executed again.
Please not that deleting a watch does not delete any watch execution records related to this watch from the Watch History.
Deleting a watch must be done via this API only. Do not delete the watch directly from the .watches
index
using Elasticsearch’s DELETE Document API. When integrating with Shield, a best practice is to make sure
no write
privileges are granted to anyone over the .watches
API.
The following example deletes a watch with the my-watch
id:
DeleteWatchResponse deleteWatchResponse = watcherClient.prepareDeleteWatch("my-watch").get();
Execute Watch API
editThis API forces the execution of a watch stored in the .watches
index.
It can be used to test a watch without executing all the actions or by ignoring the condition.
The response contains a BytesReference
that represents the record that would be written to the .watch_history
index.
The following example executes a watch with the name my-watch
ExecuteWatchResponse executeWatchResponse = watcherClient.prepareExecuteWatch("my-watch") // Will execute the actions no matter what the condition returns .setIgnoreCondition(true) // A map containing alternative input to use instead of the input result from the watch's input .setAlternativeInput(new HashMap<String, Object>()) // Trigger data to use (Note that "scheduled_time" is not provided to the ctx.trigger by this // execution method so you may want to include it here) .setTriggerData(new HashMap<String, Object>()) // Simulating the "email_admin" action while ignoring its throttle state. Use // "_all" to set the action execution mode to all actions .setActionMode("_all", ActionExecutionMode.FORCE_SIMULATE) // If the execution of this watch should be written to the `.watch_history` index and reflected // in the persisted Watch .setRecordExecution(false) .get()
Once the response is returned, you can explore it by getting execution record source:
XContentSource source = executeWatchResponse.getRecordSource();
The XContentSource
provides you methods to explore the source:
Map<String, Object> map = source.getAsMap();
Or get a specific value associated with a known key:
String actionId = source.getValue("result.actions.0.id");
Ack Watch API
editAcknowledging a watch enables you to manually throttle
execution of the watch’s actions. An action’s acknowledgement state is stored in the
_status.actions.<id>.ack.state
structure.
The current status of a watch and the state of its actions is returned with the watch definition when you call the Get Watch API:
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get(); String state = getWatchResponse.getStatus().actionStatus("my-action").ackStatus().state();
The action state of a newly-created watch is awaits_successful_execution
. When the watch
runs and its condition is met, the value changes to ackable
. Acknowledging the action
(using the ACK API) sets this value to acked
.
When an action state is set to acked
, further executions of that action are throttled
until its state is reset to awaits_successful_execution
. This happens when the watch’s
condition is checked and is not met (the condition evaluates to false
).
The following snippet shows how to acknowledge a particular action. You specify the IDs of
the watch and the action you want to acknowledge—in this example my-watch
and my-action
.
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch", "my-action").get();
As a response to this request, the status of the watch and the state of the action will be
returned in the AckWatchResponse
object
Watch.Status status = ackResponse.getStatus(); ActionStatus actionStatus = status.actionStatus("my-action"); ActionStatus.AckStatus ackStatus = actionStatus.ackStatus(); ActionStatus.AckStatus.State ackState = ackStatus.state();
You can acknowledge multiple actions:
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch") .setActionIds("action1", "action2") .get();
To acknowledge all of a watch’s actions, specify _all
as the action ID or simply omit the
actions altogether.
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch").get();
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch", "_all").get();
Activate Watch API
editA watch can be either active or inactive. This API enables you to activate a currently inactive watch.
The status of an inactive watch is returned with the watch definition when you call the Get Watch API:
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get(); boolean active = getWatchResponse.getStatus().state().isActive(); assert !active;
You can activate the watch by executing the following API call:
ActivateWatchResponse activateResponse = watcherClient.prepareActivateWatch("my-watch", true).get(); boolean active = activateResponse.getStatus().state().isActive(); assert active;
The new state of the watch is returned as part of its overall status.
Deactivate Watch API
editA watch can be either active or inactive. This API enables you to deactivate a currently active watch.
The status of an active watch is returned with the watch definition when you call the Get Watch API:
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get(); boolean active = getWatchResponse.getStatus().state().isActive(); assert active;
You can deactivate the watch by executing the following API call:
ActivateWatchResponse activateResponse = watcherClient.prepareActivateWatch("my-watch", false).get(); boolean active = activateResponse.getStatus().state().isActive(); assert !active;
The new state of the watch is returned as part of its overall status.
Stats API
editThe Watcher stats
API returns information on the aspects of Watcher on your cluster.
The following example queries the stats
API :
WatcherStatsResponse watcherStatsResponse = watcherClient.prepareWatcherStats().get();
A successful call returns a response structure that can be accessed as shown:
WatcherBuild build = watcherStatsResponse.getBuild(); // The Version of watcher currently running WatcherVersion version = watcherStatsResponse.getVersion(); // The current size of the watcher execution queue long executionQueueSize = watcherStatsResponse.getExecutionQueueSize(); // The maximum size the watch execution queue has grown to long executionQueueMaxSize = watcherStatsResponse.getWatchExecutionQueueMaxSize(); // The total number of watches registered in the system long totalNumberOfWatches = watcherStatsResponse.getWatchesCount(); // Watcher state (STARTING,STOPPED or STARTED) WatcherState watcherState = watcherStatsResponse.getWatcherState();
Service API
editThe service
watcher API allows the control of stopping and starting the watcher service.
The following example starts the watcher service:
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().start().get();
The following example stops the watcher service:
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().stop().get();
The following example restarts the watcher service:
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().restart().get();