Java API
Deprecated in 7.0.0.
The TransportClient
is deprecated in favour of the Java High Level REST Client and will be removed in Elasticsearch 8.0. The migration guide describes all the steps needed to migrate.
X-Pack provides a Java client called WatcherClient
that adds native Java support for the Watcher.
To obtain a WatcherClient
instance, make sure you first set up the XPackClient
.
Installing XPackClient
You first need to make sure the x-pack-transport-7.9.1
JAR file is in the classpath. You can extract this jar from the downloaded X-Pack bundle.
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>https://artifacts.elastic.co/maven</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
...
</repositories>
...
<dependencies>
<!-- add the x-pack jar as a dependency -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>x-pack-transport</artifactId>
<version>7.9.1</version>
</dependency>
...
</dependencies>
...
</project>
If you use Gradle, add the dependencies to build.gradle
:
repositories {
/* ... Any other repositories ... */
// Add the Elasticsearch Maven Repository
maven {
name "elastic"
url "https://artifacts.elastic.co/maven"
}
}
dependencies {
// Provide the x-pack jar on the classpath for compilation and at runtime
compile "org.elasticsearch.client:x-pack-transport:7.9.1"
/* ... */
}
You can also download the X-Pack Transport JAR manually, directly from our Maven repository.
Obtaining the WatcherClient
To obtain an instance of the WatcherClient
you first need to create the XPackClient
. The XPackClient
is a wrapper around the standard Java Elasticsearch Client
:
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
import org.elasticsearch.xpack.core.XPackClient;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.core.watcher.client.WatcherClient;
...
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
.put("cluster.name", "myClusterName")
...
.build())
.addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));
XPackClient xpackClient = new XPackClient(client);
WatcherClient watcherClient = xpackClient.watcher();
Put watch API
The 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 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 the Elasticsearch security features are enabled, make sure no write
privileges are granted to anyone over the .watches
index.
The following example adds a watch with the my-watch
id that has the following characteristics:
- The watch schedule triggers every minute.
- The watch search input looks for any 404 HTTP responses that occurred in the last five minutes.
- The watch condition checks if any hits where found.
- When hits are found, the watch action sends an email to the administrator.
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(boolQuery()
.must(matchQuery("response", 404))
.filter(rangeQuery("date").gt("{{ctx.trigger.scheduled_time}}"))
.filter(rangeQuery("date").lt("{{ctx.execution_time}}"))
));
// Create the search input
SearchInput input = new SearchInput(new WatcherSearchTemplateRequest(new String[]{"idx"}, null, SearchType.DEFAULT,
WatcherSearchTemplateRequest.DEFAULT_INDICES_OPTIONS, new BytesArray(request.source().toString())), null, null, null);
// Set the input
watchSourceBuilder.input(input);
// Set the condition
watchSourceBuilder.condition(new ScriptCondition(new Script("ctx.payload.hits.total.value > 1")));
// 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);
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 putWatchResponse2 = watcherClient.preparePutWatch("my-watch")
.setSource(watchBuilder()
.trigger(schedule(cron("0 0/1 * * * ?")))
.input(searchInput(new WatcherSearchTemplateRequest(new String[]{"idx"}, null, SearchType.DEFAULT,
WatcherSearchTemplateRequest.DEFAULT_INDICES_OPTIONS, searchSource()
.query(boolQuery()
.must(matchQuery("response", 404))
.filter(rangeQuery("date").gt("{{ctx.trigger.scheduled_time}}"))
.filter(rangeQuery("date").lt("{{ctx.execution_time}}"))
).buildAsBytes())))
.condition(compareCondition("ctx.payload.hits.total.value", CompareCondition.Op.GT, 1L))
.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
This 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
The delete watch API removes a watch (identified by its id
) from Watcher. Once removed, the document representing the watch in the .watches
index is gone and it will never be executed again.
Please note 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. If the Elasticsearch security features are enabled, make sure no write
privileges are granted to anyone over the .watches
index.
The following example deletes a watch with the my-watch
id:
DeleteWatchResponse deleteWatchResponse = watcherClient.prepareDeleteWatch("my-watch").get();
Execute watch API
This API enables on-demand execution of a watch stored in the .watches
index. It can be used to test a watch without executing all its actions or by ignoring its condition. The response contains a BytesReference
that represents the record that would be written to the .watcher-history
index.
The following example executes a watch with the name my-watch
ExecuteWatchResponse executeWatchResponse = watcherClient.prepareExecuteWatch("my-watch")
// execute the actions, ignoring the watch condition
.setIgnoreCondition(true)
// A map containing alternative input to use instead of the output of
// 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 `.watcher-history`
// index and reflected in the persisted Watch
.setRecordExecution(false)
// Indicates whether the watch should execute in debug mode. In debug mode the
// returned watch record will hold the execution vars
.setDebug(true)
.get();
Once the response is returned, you can explore it by getting execution record source:
The XContentSource
class provides convenient methods to explore the source
XContentSource source = executeWatchResponse.getRecordSource();
String actionId = source.getValue("result.actions.0.id");
Ack watch API
Acknowledging a watch enables you to manually throttle execution of the watch actions. The action’s acknowledgement state is stored in the status.actions.<id>.ack.state
structure.
The current status of the watch and the state of its actions are returned as part of the get watch API response:
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get();
State 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 state changes to ackable
. Acknowledging the action sets the state 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 condition is no longer met (the condition evaluates to false
).
The following snippet shows how to acknowledge an 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").setActionIds("my-action").get();
As a response to this request, the status of the watch and the state of the action are returned and can be obtained from AckWatchResponse
object:
WatchStatus 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 actions of a watch, specify only the watch ID:
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch").get();
Activate watch API
A 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();
The following snippet shows how you can activate a watch:
ActivateWatchResponse activateResponse = watcherClient.prepareActivateWatch("my-watch", true).get();
boolean active = activateResponse.getStatus().state().isActive();
The new state of the watch is returned as part of its overall status.
Deactivate watch API
A 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();
The following snippet shows how you can deactivate a watch:
ActivateWatchResponse activateResponse = watcherClient.prepareActivateWatch("my-watch", false).get();
boolean active = activateResponse.getStatus().state().isActive();
The new state of the watch is returned as part of its overall status.
Stats API
The stats
API returns the current Watcher metrics. You can control what metrics this API returns using the metric
parameter.
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 current size of the watcher execution queue
long executionQueueSize = watcherStatsResponse.getThreadPoolQueueSize();
// The maximum size the watch execution queue has grown to
long executionQueueMaxSize = watcherStatsResponse.getThreadPoolQueueSize();
// 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
The Watcher service
API allows the control the lifecycle of 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();