[DOCS] Copy watcher docs from x-pack to x-pack-elasticsearch repo (elastic/x-pack-elasticsearch#863)

Original commit: elastic/x-pack-elasticsearch@c4b2bbc975
This commit is contained in:
lcawl 2017-03-28 14:23:01 -07:00 committed by GitHub
parent 991e5d8833
commit 84645fc578
58 changed files with 6740 additions and 0 deletions

View File

@ -0,0 +1,217 @@
[[actions]]
== Actions
When a watch's condition is met, it's actions are executed unless it is being
<<actions-ack-throttle, throttled>>. A watch can perform multiple actions.
The actions are executed one at a time and each action executes independently.
Any failures encountered while executing an action are recorded in the
action result and in the watch history.
NOTE: If no actions are defined for a watch, no actions are executed.
However, a `watch_record` is still written to the watch history.
Actions have access to the payload in the execution context. They can use it to
support their execution in any way they need. For example, the payload might
serve as a model for a templated email body.
{watcher} supports the following types of actions:
<<actions-email, email>>, <<actions-webhook, webhook>>, <<actions-index, index>>,
<<actions-logging, logging>>, <<actions-hipchat, hipchat>>, <<actions-slack,
Slack>>, and <<actions-pagerduty, pagerduty>>.
[float]
[[actions-ack-throttle]]
=== Acknowledgement and Throttling
During the watch execution, once the condition is met, a decision is made per
configured action as to whether it should be throttled. The main purpose of
action throttling is to prevent too many executions of the same action for the
same watch.
For example, suppose you have a watch that detects errors in an application's log
entries. The watch is triggered every five minutes and searches for errors during
the last hour. In this case, if there are errors, there is a period of time where
the watch is checked and its actions are executed multiple times based on the same
errors. As a result, the system administrator receives multiple notifications about
the same issue, which can be annoying.
To address this issue, {watcher} supports time-based throttling. You can define
a throttling period as part of the action configuration to limit how often the
action is executed. When you set a throttling period, {watcher} prevents repeated
execution of the action if it has already executed within the throttling period
time frame (`now - throttling period`).
The following snippet shows a watch for the scenario described above - associating
a throttle period with the `email_administrator` action:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/error_logs_alert
{
"metadata" : {
"color" : "red"
},
"trigger" : {
"schedule" : {
"interval" : "5m"
}
},
"input" : {
"search" : {
"request" : {
"indices" : "log-events",
"body" : {
"size" : 0,
"query" : { "match" : { "status" : "error" } }
}
}
}
},
"condition" : {
"compare" : { "ctx.payload.hits.total" : { "gt" : 5 }}
},
"actions" : {
"email_administrator" : {
"throttle_period": "15m", <1>
"email" : { <2>
"to" : "sys.admino@host.domain",
"subject" : "Encountered {{ctx.payload.hits.total}} errors",
"body" : "Too many error in the system, see attached data",
"attachments" : {
"attached_data" : {
"data" : {
"format" : "json"
}
}
},
"priority" : "high"
}
}
}
}
--------------------------------------------------
// CONSOLE
<1> There will be at least 15 minutes between subsequent `email_administrator`
action executions.
<2> See <<actions-email, Email Action>> for more information.
You can also define a throttle period at the watch level. The watch-level
throttle period serves as the default throttle period for all of the actions
defined in the watch:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/log_event_watch
{
"trigger" : {
...
},
"input" : {
...
},
"condition" : {
...
},
"throttle_period" : "15m", <1>
"actions" : {
"email_administrator" : {
"email" : {
"to" : "sys.admino@host.domain",
"subject" : "Encountered {{ctx.payload.hits.total}} errors",
"body" : "Too many error in the system, see attached data",
"attachments" : {
"attached_data" : {
"data" : {
"format" : "json"
}
}
},
"priority" : "high"
}
},
"notify_pager" : {
"condition": { <2>
"compare" : { "ctx.payload.hits.total" : { "gt" : 5 }}
}
"webhook" : {
"method" : "POST",
"host" : "pager.service.domain",
"port" : 1234,
"path" : "/{{watch_id}}",
"body" : "Encountered {{ctx.payload.hits.total}} errors"
}
}
}
}
--------------------------------------------------
<1> There will be at least 15 minutes between subsequent action executions
(applies to both `email_administrator` and `notify_pager` actions)
<2> A `condition` that only applies to the `notify_pager` action, which
restricts its execution to when the condition succeeds (at least 6 hits in this case).
If you do not define a throttle period at the action or watch level, the global
default throttle period is applied. Initially, this is set to 5 seconds. To
change the global default, configure the `xpack.watcher.execution.default_throttle_period`
setting in `elasticsearch.yml`:
[source,yaml]
--------------------------------------------------
xpack.watcher.execution.default_throttle_period: 15m
--------------------------------------------------
{watcher} also supports acknowledgement-based throttling. You can acknowledge a
watch using the <<watcher-api-ack-watch, Ack Watch API>> to prevent the watch actions
from being executed again while the watch condition remains `true`. This essentially
tells {watcher} "I received the notification and I'm handling it, please do not
notify me about this error again". An acknowledged watch action remains in the
`acked` state until the watch's condition evaluates to `false`. When that happens,
the action's state changes to `awaits_successful_execution`.
To acknowledge an action, you use the <<watcher-api-ack-watch,Ack Watch API>>:
[source,js]
----------------------------------------------------------------------
POST _xpack/watcher/watch/<id>/_ack/<action_ids>
----------------------------------------------------------------------
// CONSOLE
// TEST[skip:https://github.com/elastic/x-plugins/issues/2513]
Where `<id>` is the id of the watch and `<action_ids>` is a comma-separated list
of the action ids you want to acknowledge. To acknowledge all actions, omit the
`actions` parameter.
The following diagram illustrates the throttling decisions made for each action
of a watch during its execution:
image::action-throttling.jpg[align="center"]
include::actions/email.asciidoc[]
include::actions/webhook.asciidoc[]
include::actions/index.asciidoc[]
include::actions/logging.asciidoc[]
include::actions/hipchat.asciidoc[]
include::actions/slack.asciidoc[]
include::actions/pagerduty.asciidoc[]
include::actions/jira.asciidoc[]
[float]
[[actions-ssl-openjdk]]
=== Using SSL/TLS with OpenJDK
As each distributor is free to choose how to package OpenJDK, it may happen,
that even despite the exact same version, an OpenJDK distribution contains
different parts under different Linux distributions.
This can lead to issues with any action or input that uses TLS, like the `jira`,
`pagerduty`, `slack`, `hipchat` or `webhook` one, because of missing CA certs.
If you encounter TLS errors, when writing watches that connect to TLS endpoints,
you should try to upgrade to the latest available OpenJDK distribution for your
platform and if that does not help, try to upgrade to Oracle JDK.

View File

@ -0,0 +1,447 @@
[[actions-email]]
=== Email Action
Use the `email` action to send email notifications. To send email, you must
<<configuring-email, configure at least one email account>> in
`elasticsearch.yml`.
Email notifications can be plain text or styled using HTML. You can include
information from the watch execution payload using <<templates, templates>>
and attach the entire watch payload to the message.
See <<email-action-attributes>> for the supported attributes. Any attributes that
are missing from the email action definition are looked up in the email
account configuration. The required attributes must either be set in the email
action definition or the account's `email_defaults`.
[[configuring-email-actions]]
==== Configuring Email Actions
You configure email actions in the `actions` array. Action-specific attributes
are specified using the `email` keyword.
For example, the following email action uses a template to include data from
the watch payload in the email body:
[source,js]
--------------------------------------------------
"actions" : {
"send_email" : { <1>
"email" : { <2>
"to" : "<username>@<domainname>", <3>
"subject" : "Watcher Notification", <4>
"body" : "{{ctx.payload.hits.total}} error logs found" <5>
}
}
}
--------------------------------------------------
<1> The id of the action.
<2> The action type is set to `email`.
<3> One or more addresses to send the email to. Must be specified in the
action definition or in the email account configuration.
<4> The subject of the email can contain static text and Mustache <<templates,
templates>>.
<5> The body of the email can contain static text and Mustache <<templates,
templates>>. Must be specified in the action definition or in the email
account configuration.
[[configuring-email-attachments]]
==== Configuring Email Attachments
You can attach the execution context payload or data from an any HTTP service to
the email notification. There is no limit on the number of attachments you can
configure.
To configure attachments, specify a name for the attached file and the type of
attachment: `data`, `http` or `reporting`. The `data` attachment type attaches the execution
context payload to the email message. The `http` attachment type enables
you to issue an HTTP request and attach the response to the email message. When
configuring the `http` attachment type, you must specify the request URL. The
`reporting` attachment type is a special type to include PDF rendered dashboards
from kibana. This type is consistently polling the kibana app if the dashboard
rendering is done, preventing long running HTTP connections, that are potentially
killed by firewalls or load balancers inbetween.
[source,js]
--------------------------------------------------
"actions" : {
"email_admin" : {
"email": {
"to": "'John Doe <john.doe@example.com>'",
"attachments" : {
"my_image.png" : { <1>
"http" : { <2>
"content_type" : "image.png",
"request" : {
"url": "http://example.org/foo/my-image.png" <3>
}
}
},
"dashboard.pdf" : {
"reporting" : {
"url": "http://example.org:5601/api/reporting/generate/dashboard/Error-Monitoring"
}
},
"data.yml" : {
"data" : {
"format" : "yaml" <4>
}
}
}
}
}
}
--------------------------------------------------
<1> The ID of the attachment, which is used as the file name in the email
attachment.
<2> The type of the attachment and its specific configuration.
<3> The URL from which to retrieve the attachment.
<4> Data attachments default to JSON if you don't specify the format.
.`http` attachment type attributes
[options="header"]
|=====
| Name | Description
| `content_type` | Sets the content type for the email attachment. By default,
the content type is extracted from the response sent by the
HTTP service. You can explicitly specify the content type to
ensure that the type is set correctly in the email in case
the response does not specify the content type or it's specified
incorrectly. Optional.
| `inline` | Configures as an attachment to sent with disposition `inline`. This
allows the use of embedded images in HTML bodies, which are displayed
in certain email clients. Optional. Defaults to `false`.
| `request` | Contains the HTTP request attributes. At a minimum, you must
specify the `url` attribute to configure the host and path to
the service endpoint. See <<webhook-action-attributes>> for
the full list of HTTP request attributes. Required.
|======
.`data` attachment type attributes
[options="header"]
|=====
| Name | Description
| `format` | Attaches the watch data, equivalent to specifying `attach_data`
in the watch configuration. Possible values are `json` or `yaml`.
Defaults to `json` if not specified.
|======
.`reporting` attachment type attributes
[options="header"]
|=====
| Name | Description
| `url` | The URL to trigger the dashboard creation
| `inline` | Configures as an attachment to sent with disposition `inline`. This
allows the use of embedded images in HTML bodies, which are displayed
in certain email clients. Optional. Defaults to `false`.
| `retries` | The reporting attachment type tries to poll regularly to receive the
created PDF. This configures the number of retries. Defaults to `40`.
The setting `xpack.notification.reporting.retries` can be configured
globally to change the default.
| `interval` | The time to wait between two polling tries. Defaults to `15s` (this
means, by default watcher tries to download a dashboard for 10 minutes,
forty times fifteen seconds). The setting `xpack.notification.reporting.interval`
can be configured globally to change the default.
| `request.auth` | Additional auth information for the request
|======
[[email-action-reports]]
===== Attaching Reports to an Email
You can use the `http` attachment type in an `email` action to automatically
generate a Kibana report and distribute it via email.
include::../../{xkb-repo-dir}/reporting/watch-example.asciidoc[]
include::../../{xkb-repo-dir}/reporting/report-intervals.asciidoc[]
For more information, see <<automating-report-generation,
Automating Report Generation>>.
[[email-action-attributes]]
==== Email Action Attributes
[cols=",^,,", options="header"]
|======
| Name |Required | Default | Description
| `account` | no | the default account | The <<configuring-email, email account>> to use to send the email.
| `from` | no | - | The email <<email-address,address>> from which the email
will be sent. The `from` field can contain Mustache
<<templates, templates>> as long as it resolves to a
valid email address.
| `to` | yes | - | The email <<email-address,addresses>> of the `to` recipients.
The `to` field can contain Mustache <<templates, templates>>
as long as it resolves to a valid email address.
| `cc` | no | - | The email <<email-address,addresses>> of the `cc` recipients.
The `cc` field can contain Mustache <<templates, templates>>
as long as it resolves to a valid email address.
| `bcc` | no | - | The email <<email-address,addresses>> of the `bcc` recipients.
The `bcc` field can contain Mustache <<templates, templates>>
as long as it resolves to a valid email address.
| `reply_to` | no | - | The email <<email-address,addresses>> that will be set on the
message's `Reply-To` header. The `reply_to` field can contain
Mustache <<templates, templates>> as long as it resolves to
a valid email address.
| `subject` | no | - | The subject of the email. The subject can be static text or
contain Mustache <<templates, templates>>.
| `body` | no | - | The body of the email. When this field holds a string, it
will default to the text body of the email. Set as an object
to specify either the text or the html body or both (using
the fields below)
| `body.text` | yes | - | The plain text body of the email. The body can be static text
or contain Mustache <<templates, templates>>. The email `body`
must contain at least one `text` or `html` field.
| `body.html` | yes | - | The html body of the email. The body can be static text or
contain Mustache <<templates, templates>>. This body will be
sanitized to remove dangerous content such as scripts. This
behavior can be disabled by setting
`xpack.notification.email.html.sanitization.enabled: false` in
`elasticsearch.yaml`. The email `body` must contain at least
one `text` or `html` field.
| `priority` | no | - | The priority of this email. Valid values are: `lowest`, `low`,
`normal`, `high` and `highest`. The priority can contain a
Mustache <<templates, template>> as long as it resolves to
one of the valid values.
| `attachments` | no | - | Attaches the watch payload (`data` attachment) or a file
retrieved from an HTTP service (`http` attachment) to the
email. For more information, see
<<configuring-email-attachments, Configuring Email Attachments>>.
| `attach_data` | no | false | Indicates whether the watch execution data should be attached
to the email. You can specify a Boolean value or an object.
If `attach_data` is set to `true`, the data is attached as a
YAML file. This attribute is deprecated, use the `attachments`
attribute to add a `data` attachment to attach the watch payload.
| `attach_data.format` | no | yaml | When `attach_data` is specified as an object, this field
controls the format of the attached data. The supported formats
are `json` and `yaml`. This attribute is deprecated, use the
`attachments` attribute to add a `data` attachment to attach
the watch payload.
|======
[[email-address]]
Email Address::
An email address can contain two possible parts--the address itself and an
optional personal name as described in http://www.ietf.org/rfc/rfc822.txt[RFC 822].
The address can be represented either as a string of the form `user@host.domain`
or `Personal Name <user@host.domain>`. You can also specify an email address as
an object that contains `name` and `address` fields.
[[address-list]]
Address List::
A list of addresses can be specified as a an
array: `[ 'Personal Name <user1@host.domain>', 'user2@host.domain' ]`.
[[configuring-email]]
==== Configuring Email Accounts
{watcher} can send email using any SMTP email service. Email
messages can contain basic HTML tags. You can control which groups of tags are
allowed by <<email-html-sanitization, Configuring HTML Sanitization Options>>.
You configure the accounts {watcher} can use to send email in the
`xpack.notification.email` namespace in `elasticsearch.yml`.
If your email account is configured to require two step verification, you need
to generate and use a unique App Password to send email from {watcher}.
Authentication will fail if you use your primary password.
IMPORTANT: Currently, neither Watcher nor Shield provide a mechanism to encrypt
settings in `elasticsearch.yml`. Because the email account credentials appear
in plain text, you should limit access to `elasticsearch.yml` to the user that
you use to run Elasticsearch.
[[email-profile]]
{watcher} provides three email profiles that control how MIME messages are
structured: `standard` (default), `gmail`, and `outlook`. These profiles
accommodate differences in how various email systems interpret the MIME
standard. If you are using Gmail or Outlook, we recommend using the
corresponding profile. Use the `standard` profile if you are using another
email system.
For more information about configuring {watcher} to work with different email
systems, see:
* <<gmail, Sending Email from Gmail>>
* <<outlook, Sending Email from Outlook>>
* <<exchange, Sending Email from Exchange>>
* <<amazon-ses, Sending Email from Amazon SES>>
If you configure multiple email accounts, you must either configure a default
account or specify which account the email should be sent with in the
<<actions-email, `email`>> action.
[source,yaml]
--------------------------------------------------
xpack.notification.email:
default_account: team1
account:
team1:
...
team2:
...
--------------------------------------------------
[float]
[[gmail]]
===== Sending Email From Gmail
Use the following email account settings to send email from the
https://mail.google.com[Gmail] SMTP service:
[source,yaml]
--------------------------------------------------
xpack.notification.email.account:
gmail_account:
profile: gmail
smtp:
auth: true
starttls.enable: true
host: smtp.gmail.com
port: 587
user: <username>
password: <password>
--------------------------------------------------
If you get an authentication error that indicates that you need to continue the
sign-in process from a web browser when {watcher} attempts to send email, you need
to configure Gmail to https://support.google.com/accounts/answer/6010255?hl=en[Allow
Less Secure Apps to access your account].
If two-step verification is enabled for your account, you must generate and use
a unique App Password to send email from {watcher}. See
https://support.google.com/accounts/answer/185833?hl=en[Sign in using App Passwords]
for more information.
[float]
[[outlook]]
===== Sending Email from Outlook.com
Use the following email account settings to send email action from the
https://www.outlook.com/[Outlook.com] SMTP service:
[source,yaml]
--------------------------------------------------
xpack.notification.email.account:
outlook_account:
profile: outlook
smtp:
auth: true
starttls.enable: true
host: smtp-mail.outlook.com
port: 587
user: <username>
password: <password>
--------------------------------------------------
NOTE: You need to use a unique App Password if two-step verification is enabled.
See http://windows.microsoft.com/en-us/windows/app-passwords-two-step-verification[App
passwords and two-step verification] for more information.
[float]
[[amazon-ses]]
===== Sending Email from Amazon SES (Simple Email Service)
Use the following email account settings to send email from the
http://aws.amazon.com/ses[Amazon Simple Email Service] (SES) SMTP service:
[source,yaml]
--------------------------------------------------
xpack.notification.email.account:
ses_account:
smtp:
auth: true
starttls.enable: true
starttls.required: true
host: email-smtp.us-east-1.amazonaws.com <1>
port: 587
user: <username>
password: <password>
--------------------------------------------------
<1> `smtp.host` varies depending on the region
NOTE: You need to use your Amazon SES SMTP credentials to send email through
Amazon SES. For more information, see
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html[Obtaining
Your Amazon SES SMTP Credentials]. You might also need to verify
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses.html[your email address]
or https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domains.html[your whole domain]
at AWS.
[float]
[[exchange]]
===== Sending Email from Microsoft Exchange
Use the following email account settings to send email action from Microsoft
Exchange:
[source,yaml]
--------------------------------------------------
xpack.notification.email.account:
exchange_account:
profile: outlook
email_defaults:
from: <email address of service account> <1>
smtp:
auth: true
starttls.enable: true
host: <your exchange server>
port: 587
user: <email address of service account> <2>
password: <password>
--------------------------------------------------
<1> Some organizations configure Exchange to validate that the `from` field is a
valid local email account.
<2> Many organizations support use of your email address as your username, though
it is a good idea to check with your system administrator if you receive
authentication-related failures.
[float]
[[email-html-sanitization]]
===== Configuring HTML Sanitization Options
The `email` action supports sending messages with an HTML body. However, for
security reasons, {watcher} https://en.wikipedia.org/wiki/HTML_sanitization[sanitizes]
the HTML.
You can control which HTML features are allowed or disallowed by configuring the
`xpack.notification.email.html.sanitization.allow` and
`xpack.notification.email.html.sanitization.disallow` settings in
`elasticsearch.yml`. You can specify individual HTML elements and
<<html-feature-groups, HTML feature groups>>. By default, {watcher} allows the following
features: `body`, `head`, `_tables`, `_links`, `_blocks`, `_formatting` and
`img:embedded`.
For example, the following settings allow the HTML to contain tables and block
elements, but disallow `<h4>`, `<h5>` and `<h6>` tags.
[source,yaml]
--------------------------------------------------
xpack.notification.email.html.sanitization:
allow: _tables, _blocks
disallow: h4, h5, h6
--------------------------------------------------
To disable sanitization entirely, add the following setting to
`elasticsearch.yml`:
[source,yaml]
--------------------------------------------------
xpack.notification.email.html.sanitization.enabled: false
--------------------------------------------------

View File

@ -0,0 +1,377 @@
[[actions-hipchat]]
=== HipChat Action
Use the `hipchat` action to send messages to https://www.hipchat.com[HipChat]
rooms or users. To send HipChat messages, you must <<<<configuring-hipchat,
configure at least one HipChat account>> in `elasticsearch.yml`.
[[configuring-hipchat-actions]]
==== Configuring HipChat Actions
You configure HipChat actions in a `actions` array. Action-specific attributes
are specified using the `hipchat` keyword. You must specify the `message`
attribute for all `hipchat` actions. If you omit the `account` attribute, the
message is sent using the default HipChat account configured in
`elasticsearch.yml`.
For example, the following action is configured to send messages using a HipChat
account that uses the <<hipchat-api-integration, integration>> profile. Because
this type of account can only send messages to a specific room, the only required
attribute is the message itself:
[source,js]
--------------------------------------------------
"actions" : {
"notify-hipchat" : {
"transform" : { ... },
"throttle_period" : "5m",
"hipchat" : {
"account" : "integration-account", <1>
"message" : {
"body" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)", <2>
"format" : "text",
"color" : "red",
"notify" : true
}
}
}
}
--------------------------------------------------
<1> The name of a HipChat account configured in `elasticsearch.yml`.
<2> The message you want to send to HipChat.
To send messages with a HipChat account that uses the <<hipchat-api-user, user>>
profile, you need to specify what rooms and users you want to send the message to.
For example, the following action is configured to send messages to the
`mission-control` and `devops` rooms as well as the user `website-admin@example.com`.
(To send to multiple users or rooms, specify an array of strings):
[source,js]
--------------------------------------------------
"actions" : {
"notify-hipchat" : {
"transform" : { ... },
"throttle_period" : "5m",
"hipchat" : {
"account" : "user-account",
"message" : {
"room" : [ "mission-control", "devops" ],
"user" : "website-admin@example.com",
"body" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)",
"format" : "text",
"color" : "red",
"notify" : true
}
}
}
}
--------------------------------------------------
To send messages with a HipChat account that uses the <<hipchat-api-v1, v1>>
profile, you need to specify what room or rooms you want to send the message to.
For example, the following action is configured to send messages to the
`server-status` room. (To send to multiple rooms, specify an array of strings.)
[source,js]
--------------------------------------------------
"actions" : {
"notify-hipchat" : {
"transform" : { ... },
"throttle_period" : "5m",
"hipchat" : {
"account" : "v1-account",
"message" : {
"from" : "Watcher",
"room" : [ "server-status", "infra-team" ],
"body" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)",
"format" : "text",
"color" : "red",
"notify" : true
}
}
}
}
--------------------------------------------------
[[hipchat-action-attributes]]
==== HipChat Action Attributes
[cols=",^,,", options="header"]
|======
| Name |Required | Default | Description
| `account` | no | Default account | The HipChat account to use to send the message.
| `proxy.host` | no | - | The proxy host to use (only in combination with `proxy.port`)
| `proxy.port` | no | - | The proxy port to use (only in combination with `proxy.host`)
| `message.body` | yes | - | The message content. Can contain up to 1000 characters.
| `message.format` | no | html | The format of the message: `text` or `html`.
| `message.color` | no | yellow | The background color of the notification in the room:
`gray`, `green`, `purple`, `red`, `yellow`.
| `message.notify` | no | false | Indicates whether people in the room should be actively
notified
| `message.from` | no | the watch ID | The name that appears as the notification sender. Only
valid for accounts that use the v1 profile.
| `message.room` | no | - | The rooms that the notification should go to. Accepts
a string value or an array of string values. Must be
specified when using the v1 profile. At least one room
or user must be specified when using the `user` profile.
Not valid for the `integration` profile.
| `message.user` | no | - | The users that the notification should go to. Accepts
a string value or an array of string values. At least
one room or user must be specified when using the `user`
profile. Not valid for the `integration` or `v1` profiles.
|======
[[configuring-hipchat]]
==== Configuring HipChat Accounts
You configure the accounts {watcher} can use to communicate with HipChat in the
`xpack.notification.hipchat` namespace in `elasticsearch.yml`. Both
https://www.hipchat.com/docs/api[v1] and
https://www.hipchat.com/docs/apiv2[v2] HipChat APIs are supported.
{watcher} provides three HipChat API profiles:
<<hipchat-api-integration,integration>>::
Sends messages to a specific room using HipChat's v2 API
https://www.hipchat.com/docs/apiv2/method/send_room_notification[Send room
notification].
<<hipchat-api-user, user>>::
Sends messages as a particular user through the HipChat v2 API. Enables you to
send messages to arbitrary rooms or users.
<<hipchat-api-v1, v1>>::
Sends messages to rooms using HipChat's v1 API
https://www.hipchat.com/docs/api/method/rooms/message[rooms/message].
+
NOTE: The `v1` profile is provided because it is simple to set up and this API
is familiar to many users. That said, HipChat has deprecated the v1 API
and is encouraging users to migrate to v2. Both the `integration` and
`user` profiles are based on the HipChat v2 API.
If you configure multiple HipChat accounts, you either need to set a default
HipChat account or specify which account the notification should be sent with
in the <<actions-hipchat, hipchat>> action.
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
default_account: team1
account:
team1:
...
team2:
...
--------------------------------------------------
[[hipchat-api-integration]]
===== Using the Hipchat Integration Profile
You can use the `integration` profile to send messages to specific rooms. When
you set an account's profile to `integration`, the messages are sent through
HipChat's v2 https://www.hipchat.com/docs/apiv2/method/send_room_notification[
Send room notification] API.
When you use the `integration` profile, you need to configure a separate HipChat
account for each room you want to send messages--the account configuration
contains a room-specific authentication token. Alternatively, you can use the
<<hipchat-api-user, `user`>> or <<hipchat-api-v1, `v1`>> profile to send messages
to multiple rooms.
NOTE: The `integration` profile only supports sending messages to rooms, it does
not support sending private messages. Use the <<hipchat-api-user, `user`>>
profile to notify a particular HipChat user.
You need a room-specific authentication token to configure an `integration`
account. To generate an authentication token:
. Log in to http://hipchat.com[hipchat.com] or your HipChat server as a group
administrator.
. Go to *Group admin > Rooms*.
. Click the name of the room you want to send messages to.
. Click the *Tokens* link.
. Enter a name for the token in the *Label* field.
+
image::hipchat-generate-room-token.jpg[]
. Select the *Send Notification* scope.
. Click *Create*.
. Copy the generated token so you can paste it into your HipChat account
configuration in `elasticsearch.yml`.
+
image::hipchat-copy-room-token.jpg[]
To configure a HipChat account that uses the `integration` profile:
. Set the `type` to `integration`.
. Set `room` to the name of the room you want to send messages to.
. Set `auth_token` to the room-specific authentication token.
For example, the following snippet configures an account called
`notify-monitoring` that sends messages to the `monitoring` room:
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: integration
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
room: monitoring
--------------------------------------------------
You can also specify defaults for the <<hipchat-account-attributes,
message attributes>>:
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: integration
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
room: monitoring
message:
format: text
color: blue
notify: true
--------------------------------------------------
[[hipchat-api-user]]
===== Using the HipChat User Profile
You can use the `user` profile to send messages to rooms as well as individual
HipChat users. When you set an account's profile to `user`, {watcher} sends
messages as a particular user through the HipChat v2 API.
Before you can configure a `user` account, you need to:
. Add a HipChat user for {watcher}. When setting the user name, keep in mind that
the messages are sent on behalf of this user.
. Create an API token for the {watcher} user:
.. Log in to HipChat as the {watcher} user.
.. Go to `https://<hipchat-server>/account/api`. For example,
`https://www.hipchat.com/account/api`.
.. Confirm the user password.
.. Enter a name for the token in the *Label* field.
+
image::hipchat-generate-user-token.jpg[]
. Select the *Send Notification* and *Send Message* scopes.
. Click *Create*.
. Copy the generated token so you can paste it into your HipChat account
configuration in `elasticsearch.yml`.
+
image::hipchat-copy-room-token.jpg[]
To configure a HipChat account that uses the `user` profile:
. Set the `type` to `user`.
. Set `user` to the email address associated with the {watcher} user.
. Set `auth_token` to the {watcher} user's authentication token.
For example, the following configuration creates an account called
`notify-monitoring` that sends messages to the `monitoring` room:
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: user
user: watcher-user@example.com
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
--------------------------------------------------
You can also specify defaults for the <<hipchat-account-attributes,
message attributes>>:
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: user
user: watcher-user@example.com
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
message:
format: text
color: blue
notify: true
--------------------------------------------------
[[hipchat-api-v1]]
===== Using the HipChat v1 Profile
You can use the `v1` profile to send messages to particular rooms. When you set
an account's profile to `v1`, messages are sent through HipChat's v1
https://www.hipchat.com/docs/api/method/rooms/message[rooms/message] API.
WARNING: The `v1` profile uses a deprecated API that is expected to be removed
by HipChat in the future.
The `v1` profile only supports sending messages to rooms, it does not support
sending private messages. Use the <<hipchat-api-user, `user`>> profile to send
private messages to HipChat users.
Before you can configure a `v1` account, you need to generate a `v1` API token:
. Log in to your HipChat server as a group admin.
. Go to `https://<hipchat-server>/admin/api`. For example,
`https://hipchat.com/admin/api`.
. Confirm your admin password.
. Select the *Notification* type.
+
image::hipchat-generate-v1-token.jpg[]
. Enter a name for the token in the *Label* field.
. Click *Create*.
. Copy the generated token so you can paste it into your HipChat account
configuration in `elasticsearch.yml`.
+
image::hipchat-copy-v1-token.jpg[]
To configure a HipChat account that uses the `v1` profile:
. Set the `type` to `v1`.
. Set `auth_token` to the v1 authentication token you generated.
For example, the following configuration creates an account called
`notify-monitoring`:
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: v1
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
--------------------------------------------------
You can also specify defaults for the <<hipchat-account-attributes,
message attributes>>.
[source,yaml]
--------------------------------------------------
xpack.notification.hipchat:
account:
notify-monitoring:
profile: v1
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
message:
format: text
color: blue
notify: true
--------------------------------------------------

View File

@ -0,0 +1,75 @@
[[actions-index]]
=== Index Action
Use the `index` action to index data into Elasticsearch.
See <<index-action-attributes>> for the supported attributes.
==== Configuring Index Actions
The following snippet shows a simple `index` action definition:
[source,js]
--------------------------------------------------
"actions" : {
"index_payload" : { <1>
"condition": { ... }, <2>
"transform": { ... }, <3>
"index" : {
"index" : "my-index", <4>
"doc_type" : "my-type", <5>
"doc_id": "my-id" <6>
}
}
}
--------------------------------------------------
<1> The id of the action
<2> An optional <<condition, condition>> to restrict action execution
<3> An optional <<transform, transform>> to transform the payload and prepare the data that should be indexed
<4> The elasticsearch index to store the data to
<5> The document type to store the data as
<6> An optional `_id` for the document, if it should always be the same document.
[[index-action-attributes]]
==== Index Action Attributes
[options="header"]
|======
|Name |Required | Default | Description
| `index` | yes | - | The Elasticsearch index to index into.
| `doc_type` | yes | - | The type of the document the data will be indexed as.
| `doc_id` | no | - | The optional `_id` of the document.
| `execution_time_field` | no | - | The field that will store/index the watch execution
time.
| `timeout` | no | 60s | The timeout for waiting for the index api call to
return. If no response is returned within this time,
the index action times out and fails. This setting
overrides the default timeouts.
|======
[[anatomy-actions-index-multi-doc-support]]
==== Multi-Document Support
Like with all other actions, you can use a <<transform, transform>> to replace
the current execution context payload with another and by that change the document
that will end up indexed.
The index action plays well with transforms with its support for the special `_doc`
payload field.
When resolving the document to be indexed, the index action first looks up for a
`_doc` field in the payload. When not found, the payload is indexed as a single
document.
When a `_doc` field exists, if the field holds an object, it is extracted and indexed
as a single document. If the field holds an array of objects, each object is treated as
a document and the index action indexes all of them in a bulk.
An `_id` value can be added per document to dynamically set the ID of the indexed
document.

View File

@ -0,0 +1,172 @@
[[actions-jira]]
=== Jira Action
Use the `jira` action to create issues in https://www.atlassian.com/software/jira[Atlassian's Jira Software].
To create issues you need to <<configuring-jira, configure at least one Jira account>> in `elasticsearch.yml`.
[[configuring-jira-actions]]
==== Configuring Jira Actions
You configure Jira actions in the `actions` array. Action-specific attributes
are specified using the `jira` keyword.
The following snippet shows a simple jira action definition:
[source,js]
--------------------------------------------------
"actions" : {
"create-jira-issue" : {
"transform" : { ... },
"throttle_period" : "5m",
"jira" : {
"account" : "integration-account", <1>
"fields" : {
"issue" : {
"project" : {
"key": "PROJ" <2>
},
"issuetype" : {
"name": "Bug" <3>
},
"summary" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes", <4>
"description" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)", <5>
"labels" : ["auto"], <6>
"priority" : {
"name" : "High" <7>
}
}
}
}
}
}
--------------------------------------------------
<1> The name of a Jira account configured in `elasticsearch.yml`.
<2> The key of the Jira project in which the issue will be created.
<3> The name of the issue type.
<4> The summary of the Jira issue.
<5> The description of the Jira issue.
<6> The labels to apply to the Jira issue.
<7> The priority of the Jira issue.
[[jira-action-attributes]]
==== Jira Action Attributes
Depending of how Jira projects are configured, the issues can have many different fields and values. Therefore
the `jira` action can accept any type of sub fields within its `issue` field. These fields will be directly used
when calling Jira's https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-createIssue[Create Issue API], allowing
any type of custom fields to be used.
NOTE: The `project.key` (or `project.id`), the `issuetype.name` (or `issuetype.id`) and `issue.summary` are
always required to create an issue in Jira.
[cols=",^,", options="header"]
|======
| Name |Required | Description
| `account` | no | The Jira account to use to send the message.
| `proxy.host` | no | The proxy host to use (only in combination with `proxy.port`)
| `proxy.port` | no | The proxy port to use (only in combination with `proxy.host`)
| `fields.project.key` | yes | The key of the Jira project in which the issue will be created.
It can be replaced by `issue.project.id` if the identifier of the
project is known.
| `fields.issuetype.name` | yes | A name that identifies the type of the issue. Jira provides default
issue types like `Bug`, `Task`, `Story`, `New Feature` etc. It can
be replaced by `issue.issuetype.id` if the identifier of the type
is known.
| `fields.summary` | yes | The summary (or title) of the issue.
| `fields.description` | no | The description of the issue.
| `fields.labels` | no | The labels to apply to the Jira issue.
| `fields.priority.name` | no | The priority of the Jira issue. Jira provides default `High`,
`Medium` and `Low` priority levels.
| `fields.assignee.name` | no | Name of the user to assign the issue to.
| `fields.reporter.name` | no | Name of the user identified as the reporter of the issue.
Defaults to the user account.
| `fields.environment` | no | Name of the environment related to the issue.
| `fields.customfield_XXX` | no | Custom field XXX of the issue (ex: "customfield_10000": "09/Jun/81")
|======
[[configuring-jira]]
==== Configuring Jira Accounts
You configure the accounts {watcher} can use to communicate with Jira in the
`xpack.notification.jira` namespace in `elasticsearch.yml`.
{watcher} supports Basic Authentication for Jira Software. To configure a
Jira account you need to specify:
[source,yaml]
--------------------------------------------------
xpack.notification.jira:
account:
monitoring:
url: https://internal-jira.elastic.co:443
user: B0A6D1PRD
password: mslNSCnJR
--------------------------------------------------
To avoid credentials that transit in clear text over the network, {watcher} will
reject `url` settings like `http://internal-jira.elastic.co` that are based on
plain text HTTP protocol. This default behavior can be disabled with the explicit
`allow_http setting`:
[source,yaml]
--------------------------------------------------
xpack.notification.jira:
account:
monitoring:
url: http://unsecure-jira.elastic.co/
allow_http: true
user: B0A6D1PRD
password: mslNSCnJR
--------------------------------------------------
WARNING: It is strongly advised to use Basic Authentication with secured HTTPS
protocol only.
You can also specify defaults for the <<jira-account-attributes, Jira issues>>:
[source,yaml]
--------------------------------------------------
xpack.notification.jira:
account:
monitoring:
url: https://internal-jira.elastic.co:443
user: B0A6D1PRD
password: mslNSCnJR
issue_defaults:
project:
key: proj
issuetype:
name: Bug
summary: "X-Pack Issue"
labels: ["auto"]
--------------------------------------------------
If you configure multiple Jira accounts, you either need to configure a default
account or specify which account the notification should be sent with in the
<<actions-jira, jira>> action.
[source,yaml]
--------------------------------------------------
xpack.notification.jira:
default_account: team1
account:
team1:
...
team2:
...
--------------------------------------------------

View File

@ -0,0 +1,48 @@
[[actions-logging]]
=== Logging Action
Use the `logging` action to log text to the standard Elasticsearch
logs. See <<logging-action-attributes>> for the supported attributes.
This action is primarily used during development and for debugging purposes.
[[configuring-logging-actions]]
==== Configuring Logging Actions
You configure logging actions in the `actions` array. Action-specific attributes
are specified using the `logging` keyword.
The following snippet shows a simple logging action definition:
[source,js]
--------------------------------------------------
"actions" : {
"log" : { <1>
"transform" : { ... }, <2>
"logging" : {
"text" : "executed at {{ctx.execution_time}}" <3>
}
}
}
--------------------------------------------------
<1> The id of the action.
<2> An optional <<transform, transform>> to transform the payload before
executing the `logging` action.
<3> The text to be logged.
[[logging-action-attributes]]
==== Logging Action Attributes
[options="header"]
|======
| Name |Required | Default | Description
| `text` | yes | - | The text that should be logged. Can be static text or
include Mustache <<templates, templates>>.
| `category` | no | xpack.watcher.actions.logging | The category under which the text will be logged.
| `level` | no | info | The logging level. Valid values are: `error`, `warn`,
`info`, `debug` and `trace`.
|======

View File

@ -0,0 +1,191 @@
[[actions-pagerduty]]
=== PagerDuty Action
Use the PagerDuty action to create events in https://pagerduty.com/[
PagerDuty]. To create PagerDuty events, you must <<configuring-pagerduty,
configure at least one PagerDuty account>> in `elasticsearch.yml`.
[[configuring-pagerduty-actions]]
==== Configuring PagerDuty Actions
You configure PagerDuty actions in the `actions` array. Action-specific attributes
are specified using the `pagerduty` keyword.
The following snippet shows a simple PagerDuty action definition:
[source,js]
--------------------------------------------------
"actions" : {
"notify-pagerduty" : {
"transform" : { ... },
"throttle_period" : "5m",
"pagerduty" : {
"description" : "Main system down, please check!" <1>
}
}
}
--------------------------------------------------
<1> Description of the message
[[adding-context-and-payloads-to-pagerduty-actions]]
==== Adding Meta Information to a PagerDuty Incident
To give the PagerDuty incident some more context, you can attach the
payload as well as an array of contexts to the action.
[source,js]
--------------------------------------------------
"actions" : {
"notify-pagerduty" : {
"throttle_period" : "5m",
"pagerduty" : {
"account" : "team1",
"description" : "Main system down, please check! Happened at {{ctx.execution_time}}"
"attach_payload" : true,
"client" : "/foo/bar/{{ctx.watch_id}}",
"client_url" : "http://www.example.org/",
"context" : [
{
"type": "link",
"href": "http://acme.pagerduty.com"
},{
"type": "link",
"href": "http://acme.pagerduty.com",
"text": "View the incident on {{ctx.payload.link}}"
}
]
}
}
}
--------------------------------------------------
[[pagerduty-action-attributes]]
==== Pagerduty Action Attributes
[cols=",^,", options="header"]
|======
| Name |Required | Description
| `account` | no | The account to use, falls back to the default one.
The account needs a `service_key_api` attribute.
|======
[[pagerduty-event-trigger-incident-attributes]]
.Pagerduty Event Trigger Incident Attributes
[cols=",^,", options="header"]
|======
| Name |Required | Description
| `description` | yes | A quick description for this event
| `event_type` | no | The event type to sent. Must be one of `trigger`,
`resolve` or `acknowledge`. Defaults to `trigger`.
| `incident_key` | no | The incident key on the pagerduty side, also used
for de-duplication and allows to resolve or acknowledge
incidents.
| `client` | no | Name of the client triggering the incident, i.e.
`Watcher Monitoring`
| `client_url` | no | A client URL to visit to get more detailed information.
| `attach_payload` | no | If set to `true` the payload is attached as a detail
to the API call. Defaults to `false`.
| `contexts` | no | An array of objects, that allow you to provide
additional links or images in order to provide more
context to the trigger.
| `proxy.host` | no | The proxy host to use (only in combination with `proxy.port`)
| `proxy.port` | no | The proxy port to use (only in combination with `proxy.host`)
|======
You can configure defaults for the above values for the whole service using the
`xpack.notification.pagerduty.event_defaults.*` properties as well as
per account using `xpack.notification.pagerduty.account.your_account_name.event_defaults.*`
NOTE: All of those objects have templating support, so you can use data from the
context and the payload as part of all the fields.
[[pagerduty-event-trigger-context-attributes]]
.Pagerduty Event Trigger Context Attributes
[cols=",^,", options="header"]
|======
| Name |Required | Description
| `type` | yes | One of `link` or `image`.
| `href` | yes/no | A link to include more information. Must be there if the
type is `link`, optional if the type is `image`
| `src` | no | A src attribute for the `image` type.
|======
[[configuring-pagerduty]]
==== Configuring PagerDuty Accounts
You configure the accounts {watcher} uses to communicate with PagerDuty in
the `xpack.notification.pagerduty` namespace in `elasticsearch.yml`.
To configure a PagerDuty account, you need the API integration key for
the PagerDuty service you want to send notifications to. To get the
key:
. Log in to http://pagerduty.com[pagerduty.com] as an account administrator.
. Go to **Configuration > Services** and select the PagerDuty service. The
service must use the API integration.
+
image::pagerduty-services.jpg[]
. Click the **Integrations** tab and copy the API integration key.
+
image::pagerduty-integrations.jpg[]
To configure a PagerDuty account in `elasticsearch.yml`, at a minimum you
must specify an account name and integration key:
[source,yaml]
--------------------------------------------------
xpack.notification.pagerduty:
account:
my_pagerduty_account:
service_api_key: d3b07384d113edec49eaa6238ad5ff0
--------------------------------------------------
You can also specify defaults for the <<pagerduty-event-trigger-incident-attributes,
PagerDuty event attributes>>:
.
[source,yaml]
--------------------------------------------------
xpack.notification.pagerduty:
account:
my_pagerduty_account:
service_api_key: d3b07384d113edec49eaa6238ad5ff0
event_defaults:
description: "Watch notification"
incident_key: "my_incident_key"
client: "my_client"
client_url: http://www.example.org
event_type: trigger
attach_payload: true
--------------------------------------------------
If you configure multiple PagerDuty accounts, you either need to set a default
account or specify which account the event should be sent with in the
<<actions-pagerduty, `pagerduty`>> action.
[source,yaml]
--------------------------------------------------
xpack.notification.pagerduty:
default_account: team1
account:
team1:
...
team2:
...
--------------------------------------------------

View File

@ -0,0 +1,240 @@
[[actions-slack]]
=== Slack Action
Use the `slack` action to send messages to a https://slack.com/[Slack]
team's channels or users. To send Slack messages, you need to
<<configuring-slack, configure at least one Slack account>> in
`elasticsearch.yml`.
[[configuring-slack-actions]]
==== Configuring Slack Actions
You configure Slack actions in the `actions` array. Action-specific attributes
are specified using the `slack` keyword.
The following snippet shows a simple slack action definition:
[source,js]
--------------------------------------------------
"actions" : {
"notify-slack" : {
"transform" : { ... },
"throttle_period" : "5m",
"slack" : {
"message" : {
"to" : [ "#admins", "@chief-admin" ], <1>
"text" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)" <2>
}
}
}
}
--------------------------------------------------
<1> The channels and users you want to send the message to.
<2> The content of the message.
[[formatting-slack-messages]]
==== Using Attachments to Format Slack Messages
In addition to sending simple text-based messages, you can use the Slack
https://api.slack.com/docs/attachments[attachment] mechanism to send formatted
messages. {watcher} leverages Slack attachments to enable you to dynamically
populate templated messages from the execution context payload.
The following snippet shows a standard message attachment:
[source,js]
--------------------------------------------------
"actions" : {
"notify-slack" : {
"throttle_period" : "5m",
"slack" : {
"account" : "team1",
"message" : {
"from" : "watcher",
"to" : [ "#admins", "@chief-admin" ],
"text" : "System X Monitoring",
"attachments" : [
{
"title" : "Errors Found",
"text" : "Encountered {{ctx.payload.hits.total}} errors in the last 5 minutes (facepalm)",
"color" : "danger"
}
]
}
}
}
}
--------------------------------------------------
[[slack-dynamic-attachment]]
To define an attachment template that is dynamically populated from the payload,
you specify `dynamic_attachments` in the watch action. For example, a dynamic
attachment could reference histogram buckets in the payload and build an
attachment per bucket.
In the following example, the watch input executes a search with a date histogram
aggregation and the Slack action:
. Transforms the payload to a list where each item in the list holds the month,
the user count for that month, and the color that represents the sentiment
associated with that count (danger or bad).
. Defines an attachment template that references items in the list generated by
the transform.
[source,js]
--------------------------------------------------
"input" : {
"search" : {
"request" : {
"body" : {
"aggs" : {
"users_per_month" : {
"date_histogram" : {
"field" : "@timestamp",
"interval" : "month"
}
}
}
}
}
}
},
...
"actions" : {
"notify-slack" : {
"throttle_period" : "5m",
"transform" : {
"script" : {
"inline" : "['items': ctx.payload.aggregations.users_per_month.buckets.collect(bucket -> ['count': bucket.doc_count, 'name': bucket.key_as_string, 'color': bucket.doc_count < 100 ? 'danger' : 'good'])]",
"lang" : "painless"
}
},
"slack" : {
"account" : "team1",
"message" : {
"from" : "watcher",
"to" : [ "#admins", "@chief-admin" ],
"text" : "System X Monitoring",
"dynamic_attachments" : {
"list_path" : "ctx.payload.items" <1>
"attachment_template" : {
"title" : "{{month}}", <2>
"text" : "Users Count: {{count}}",
"color" : "{{color}}"
}
}
}
}
}
}
--------------------------------------------------
<1> The list generated by the action's transform.
<2> The parameter placeholders refer to attributes in each item of the list
generated by the transform.
[[slack-action-attributes]]
==== Slack Action Attributes
[cols=",^,", options="header"]
|======
| Name |Required | Description
| `message.from` | no | The sender name to display in the Slack message.
Overrides the incoming webhook's configured name.
| `message.to` | yes | The channels and users you want to send the message
to. Channel names must start with `#` and user names
must start with `@`. Accepts a string value or an
array of string values.
| `message.icon` | no | The icon to display in the Slack messages. Overrides
the incoming webhook's configured icon. Accepts a
public URL to an image.
| `message.text` | yes | The message content.
| `message.attachments` | no | Slack message attachments. Message attachments enable
you to create more richly-formatted messages. Specified
array as defined in the
https://api.slack.com/docs/attachments[Slack attachments documentation].
| `message.dynamic_attachments` | no | Slack message attachments that can be populated
dynamically based on the current watch payload. For
more information, see
<<slack-dynamic-attachment, Using Attachments to Format Slack Messages>>.
| `proxy.host` | no | - | The proxy host to use (only in combination with `proxy.port`)
| `proxy.port` | no | - | The proxy port to use (only in combination with `proxy.host`)
|======
[[configuring-slack]]
==== Configuring Slack Accounts
You configure the accounts {watcher} can use to communicate with Slack in the
`xpack.notification.slack` namespace in `elasticsearch.yml`.
You need a https://api.slack.com/incoming-webhooks[Slack webhook URL] to
configure a Slack account. To create a webhook
URL, set up an an _Incoming Webhook Integration_ through the Slack console:
. Log in to http://slack.com[slack.com] as a team administrator.
. Go to https://my.slack.com/services/new/incoming-webhook.
. Select a default channel for the integration.
+
image::slack-add-webhook-integration.jpg[]
. Click *Add Incoming Webhook Integration*.
. Copy the generated webhook URL so you can paste it into your Slack account
configuration in `elasticsearch.yml`.
+
image::slack-copy-webhook-url.jpg[]
To configure a Slack account, at a minimum you need to specify the account
name and webhook URL:
[source,yaml]
--------------------------------------------------
xpack.notification.slack:
account:
monitoring:
url: https://hooks.slack.com/services/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
--------------------------------------------------
You can also specify defaults for the <<slack-account-attributes, Slack
notification attributes>>:
[source,yaml]
--------------------------------------------------
xpack.notification.slack:
account:
monitoring:
url: https://hooks.slack.com/services/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
message_defaults:
from: x-pack
to: notifications
icon: http://example.com/images/watcher-icon.jpg
attachment:
fallback: "X-Pack Notification"
color: "#36a64f"
title: "X-Pack Notification"
title_link: "https://www.elastic.co/guide/en/x-pack/current/index.html"
text: "One of your watches generated this notification."
--------------------------------------------------
If you configure multiple Slack accounts, you either need to configure a default
account or specify which account the notification should be sent with in the
<<actions-slack, slack>> action.
[source,yaml]
--------------------------------------------------
xpack.notification.slack:
default_account: team1
account:
team1:
...
team2:
...
--------------------------------------------------

View File

@ -0,0 +1,182 @@
[[actions-webhook]]
=== Webhook Action
Use the `webhook` action to send a request to any web service. The
webhook action supports both HTTP and HTTPS connections. See
<<webhook-action-attributes, Webhook Action Attributes>> for the supported
attributes.
[[configuring-webook-actions]]
==== Configuring Webhook Actions
You configure webhook actions in the `actions` array. Action-specific attributes
are specified using the `webhook` keyword.
The following snippet shows a simple webhook action definition:
[source,js]
--------------------------------------------------
"actions" : {
"my_webhook" : { <1>
"transform" : { ... }, <2>
"throttle_period" : "5m", <3>
"webhook" : {
"method" : "POST", <4>
"host" : "mylisteningserver", <5>
"port" : 9200, <6>
"path": ":/{{ctx.watch_id}", <7>
"body" : "{{ctx.watch_id}}:{{ctx.payload.hits.total}}" <8>
}
}
}
--------------------------------------------------
<1> The id of the action
<2> An optional <<transform, transform>> to transform the payload before
executing the `webhook` action
<3> An optional <<actions-ack-throttle, throttle period>> for the action
(5 minutes in this example)
<4> The HTTP method to use when connecting to the host
<5> The host to connect to
<6> The port to connect to
<7> The path (URI) to use in the HTTP request
<8> The body to send with the request
You can use basic authentication when sending a request to a secured webservice.
For example, the following `webhook` action creates a new issue in GitHub:
[source,js]
--------------------------------------------------
"actions" : {
"create_github_issue" : {
"webhook" : {
"method" : "POST",
"url" : "https://api.github.com/repos/<owner>/<repo>/issues",
"body" : "{
\"title\": \"Found errors in 'contact.html'\",
\"body\": \"Found {{ctx.payload.hits.total}} errors in the last 5 minutes\",
\"assignee\": \"web-admin\",
\"labels\": [ \"bug\", \"sev2\" ]
}",
"auth" : {
"basic" : {
"username" : "<username>", <1>
"password" : "<password>"
}
}
}
}
}
--------------------------------------------------
<1> The username and passwword for the user creating the issue
NOTE: By default, both the username and the password are stored in the `.watches`
index in plain text. When {security} is enabled, {watcher} can encrypt the
password before storing it.
You can also use PKI-based authentication when submitting requests to a cluster
secured with {security}. When you use PKI-based authentication instead of HTTP
basic auth, you don't need to store any authentication information in the watch
itself. To use PKI-based authentication, you <<ssl-notification-settings,
configure the SSL key settings>> for {watcher} in `elasticsearch.yml`.
[[webhook-query-parameters]]
==== Query Parameters
You can specify query parameters to send with the request with the `params` field.
This field simply holds an object where the keys serve as the parameter names and
the values serve as the parameter values:
[source,js]
--------------------------------------------------
"actions" : {
"my_webhook" : {
"webhook" : {
"method" : "POST",
"host" : "mylisteningserver",
"port" : 9200,
"path": ":/alert",
"params" : {
"watch_id" : "{{ctx.watch_id}}" <1>
}
}
}
}
--------------------------------------------------
<1> The parameter values can contain templated strings.
[[webhook-custom-request-headers]]
==== Custom Request Headers
You can specify request headers to send with the request with the `headers` field.
This field simply holds an object where the keys serve as the header names and
the values serve as the header values:
[source,js]
--------------------------------------------------
"actions" : {
"my_webhook" : {
"webhook" : {
"method" : "POST",
"host" : "mylisteningserver",
"port" : 9200,
"path": ":/alert/{{ctx.watch_id}}",
"headers" : {
"Content-Type" : "application/yaml" <1>
},
"body" : "count: {{ctx.payload.hits.total}}"
}
}
}
--------------------------------------------------
<1> The header values can contain templated strings.
==== Webhook Action Attributes
[[webhook-action-attributes]]
[cols=",^,^,", options="header"]
|======
| Name |Required | Default | Description
| `scheme` | no | http | The connection scheme. Valid values are: `http` or `https`.
| `host` | yes | - | The host to connect to.
| `port` | yes | - | The port the HTTP service is listening on.
| `path` | no | - | The URL path. The path can be static text or include Mustache
<<templates, templates>>. URL query string parameters must be
specified via the `request.params` attribute.
| `method` | no | get | The HTTP method. Valid values are: `head`, `get`, `post`, `put`
and `delete`.
| `headers` | no | - | The HTTP request headers. The header values can be static text
or include Mustache <<templates, templates>>.
| `params` | no | - | The URL query string parameters. The parameter values can be
static text or include Mustache <<templates, templates>>.
| `auth` | no | - | Authentication related HTTP headers. Currently, only basic
authentication is supported.
| `body` | no | - | The HTTP request body. The body can be static text or include
Mustache <<templates, templates>>. When not specified, an empty
body is sent.
| `proxy.host` | no | - | The proxy host to use when connecting to the host.
| `proxy.port` | no | - | The proxy port to use when connecting to the host.
| `connection_timeout` | no | 10s | The timeout for setting up the http connection. If the connection
could not be set up within this time, the action will timeout and
fail.
| `read_timeout` | no | 10s | The timeout for reading data from http connection. If no response
was received within this time, the action will timeout and fail.
| `url` | no | - | A shortcut for specifying the request scheme, host, port, and
path as a single string. For example, `http://example.org/foo/my-service`.
|======

View File

@ -0,0 +1,40 @@
[[condition]]
== Conditions
When a watch is triggered, its condition determines whether or not to execute
the watch actions. {watcher} supports the following condition types:
* <<condition-always, `always`>>: set the watch condition to `true` so the watch
actions are always executed.
* <<condition-never, `never`>>: set the watch condition to `false` so the watch
actions are never executed.
* <<condition-compare, `compare`>>: perform simple comparisons against values
in the watch payload to determine whether or not to execute the watch actions.
* <<condition-array-compare, `array_compare`>>: compare an array of values in the
watch payload to a given value to determine whether or not to execute the watch
actions.
* <<condition-script, `script`>>: use a script to determine wehther or not to
execute the watch actions.
NOTE: If you omit the condition definition from a watch, the condition defaults
to `always`.
When a condition is evaluated, it has full access to the watch execution context,
including the watch payload (`ctx.payload.*`). The <<condition-script, script>>,
<<condition-compare, compare>> and <<condition-array-compare, array_compare>>
conditions can use the payload data to determine whether or not the necessary
conditions are met.
include::condition/always.asciidoc[]
include::condition/never.asciidoc[]
include::condition/compare.asciidoc[]
include::condition/array-compare.asciidoc[]
include::condition/script.asciidoc[]

View File

@ -0,0 +1,24 @@
[[condition-always]]
=== Always Condition
Use the `always` condition to set the condition to `true`. This forces the watch
actions to be executed unless they are <<actions-ack-throttle, throttled>>.
The `always` condition enables you to perform watch actions on a fixed schedule,
such as, _"Every Friday at noon, send a status report email to
sys.admin@example.com."_
==== Using the Always Condition
This is the default if you omit the condition definition from a watch.
There are no attributes to specify for the `always` condition. To explicitly
use this condition, specify the condition type and associate it with an empty
object:
[source,js]
--------------------------------------------------
"condition" : {
"always" : {}
}
--------------------------------------------------

View File

@ -0,0 +1,65 @@
[[condition-array-compare]]
=== Array Compare Condition
Use `array_compare` to compare an array of values in the execution context to a
given value. See <<condition-compare-operators, Supported Comparison Operators>>
for the operators you can use.
==== Using an Array Compare Condition
To use the `array_compare` condition, you specify the array in the execution
context that you want to evaluate, a <<condition-compare-operators,comparison
operator>>, and the value you want to compare against. Optionally, you
can specify the path to the field in each array element that you want to
evaluate.
For example, the following `array_compare` condition returns `true` if there
is at least one bucket in the aggregation that has a `doc_count` greater
than or equal to 25:
[source,js]
--------------------------------------------------
{
"condition": {
"array_compare": {
"ctx.payload.aggregations.top_tweeters.buckets" : { <1>
"path": "doc_count" <2>,
"gte": { <3>
"value": 25, <4>
}
}
}
}
}
--------------------------------------------------
<1> The path to the array in the execution
context that you want to evaluate, specified in dot notation.
<2> The path to the field in each array element that you want to evaluate.
<3> The <<condition-compare-operators, comparison operator>> to use.
<4> The comparison value. Supports date math like the
<<compare-condition-date-math, compare condition>>.
==== Array-Compare Condition Attributes
[options="header"]
|======
| Name | Description
|`<array path>` | The path to the array in the execution
context, specified in dot notation.
For example, `ctx.payload.aggregations.top_tweeters.buckets`.
| `<array path>.path` | The path to the field in each array element
that you want to evaluate. For example,
`doc_count`. Defaults to an empty string.
| `<array path>.<operator>.quantifier` | How many matches are required for the
comparison to evaluate to `true`: `some`
or `all`. Defaults to `some`--there must
be at least one match. If the array is
empty, the comparison evaluates to `true`
if the quantifier is set to `all` and
`false` if the quantifier is set to
`some`.
| `<array path>.<operator>.value` | The value to compare against.
|======

View File

@ -0,0 +1,107 @@
[[condition-compare]]
=== Compare Condition
Use the `compare` condition to perform a simple comparison against a value in
the watch payload. You can use the `compare` condition without enabling
dynamic scripting.
[[condition-compare-operators]]
. Supported Comparison Operators
[options="header"]
|======
| Name | Description
| `eq` | Returns `true` when the resolved value equals the given one (applies
to numeric, string, list, object and values)
| `not_eq` | Returns `true` when the resolved value does not equal the given one
(applies to numeric, string, list, object and null values)
| `gt` | Returns `true` when the resolved value is greater than the given
one (applies to numeric and string values)
| `gte` | Returns `true` when the resolved value is greater/equal than/to the
given one (applies to numeric and string values)
| `lt` | Returns `true` when the resolved value is less than the given one
(applies to numeric and string values)
| `lte` | Returns `true` when the resolved value is less/equal than/to the
given one (applies to numeric and string values)
|======
==== Using a Compare Condition
To use the `compare` condition, you specify the value in the execution context
that you want to evaluate, a <<condition-compare-operators,comparison operator>>,
and the value you want to compare against. For example, the following `compare`
condition returns `true` if the number of the total hits in the <<input-search,
search result>> is greater than or equal to 5:
[source,js]
--------------------------------------------------
{
"condition" : {
"compare" : {
"ctx.payload.hits.total" : { <1>
"gte" : 5 <2>
}
}
}
--------------------------------------------------
<1> Use dot notation to reference a value in the execution context.
<2> Specify a comparison operator and the value you want to compare against.
[[compare-condition-date-math]]
When comparing dates and times, you can use date math expressions
of the form `<{expression}>`. For example, the following expression returns
`true` if the watch was executed within the last five minutes:
[source,js]
--------------------------------------------------
{
"condition" : {
"compare" : {
"ctx.execution_time" : {
"gte" : "<{now-5m}>"
}
}
}
--------------------------------------------------
You can also compare two values in the execution context by specifying the
compared value as a path of the form of `{{path}}`. For example, the following
condition compares the `ctx.payload.aggregations.status.buckets.error.doc_count`
to the `ctx.payload.aggregations.handled.buckets.true.doc_count`:
[source,js]
--------------------------------------------------
{
"condition" : {
"compare" : {
"ctx.payload.aggregations.status.buckets.error.doc_count" : {
"not_eq" : "{{ctx.payload.aggregations.handled.buckets.true.doc_count}}"
}
}
}
--------------------------------------------------
==== Accessing Values in the Execution Context
You use "dot-notation" to access values in the execution context. Values loaded
into the execution context by the input are prefixed by `ctx.payload`.
You can reference entries in arrays using their zero-based array indices.
For example, to access the third element of the `ctx.payload.hits.hits`
array, use `ctx.payload.hits.hits.2`.
[options="header"]
|======
| Name | Description
| `ctx.watch_id` | The id of the watch that is currently executing.
| `ctx.execution_time` | The time execution of this watch started.
| `ctx.trigger.triggered_time` | The time this watch was triggered.
| `ctx.trigger.scheduled_time` | The time this watch was supposed to be triggered.
| `ctx.metadata.*` | Any metadata associated with the watch.
| `ctx.payload.*` | The payload data loaded by the watch's input.
|======

View File

@ -0,0 +1,19 @@
[[condition-never]]
=== Never Condition
Use the `never` condition to set the condition to `false`. This means the
watch actions are never executed when the watch is triggered. The watch input is
executed, a record is added to the watch history, and the watch execution ends.
This condition is generally used for testing.
==== Using the Never Condition
There are no attributes to specify for the `never` condition. To use the it,
you specify the condition type and associate it with an empty object:
[source,js]
--------------------------------------------------
"condition" : {
"never" : {}
}
--------------------------------------------------

View File

@ -0,0 +1,180 @@
[[condition-script]]
=== Script Condition
A watch <<condition, condition>> that evaluates a script. The default scripting
language is `painless`. You can use any of the scripting languages supported by
Elasticsearch as long as the language supports evaluating expressions to Boolean
values. Note that the `mustache` and `expression` languages are too limited to be
used by this condition. For more information, see {ref}/modules-scripting.html[Scripting]
in the Elasticsearch Reference.
==== Using a Script Condition
The following snippet configures an inline `script` condition that always returns
`true`:
[source,js]
--------------------------------------------------
"condition" : {
"script" : "return true"
}
--------------------------------------------------
This example defines a script as a simple string. This format is actually a
shortcut for defining an <<condition-script-inline, inline>> script. The
formal definition of a script is an object that specifies the script type and
optional language and parameter values. If the `lang` attribute is omitted, the
language defaults to `painless`. Elasticsearch supports three script types:
<<condition-script-inline, Inline>>, <<condition-script-file, File>>, and
<<condition-script-stored, Stored>>.
For example, the following snippet shows a formal definition of an `inline`
script that explicitly specifies the language and defines a single script
parameter, `result`:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"inline" : "return result",
"lang" : "painless",
"params" : {
"result" : true
}
}
}
--------------------------------------------------
[[condition-script-inline]]
==== Inline Scripts
Inline scripts are scripts that are defined in the condition itself. The
following snippet shows the formal configuration of a simple painless script that
always returns `true`.
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"inline" : "return true"
}
}
--------------------------------------------------
[[condition-script-file]]
==== File Scripts
File scripts are scripts that are defined in files stored in the `config/scripts`
directory. The following snippet shows how to refer to the `my_script.painless`
file:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"file" : "my_script"
}
}
--------------------------------------------------
As with <<condition-script-inline, Inline>> scripts, you can also specify the
script language and parameters:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"file" : "my_script",
"lang" : "javascript",
"params" : {
"result" : true
}
}
}
--------------------------------------------------
[[condition-script-stored]]
==== Stored Scripts
Stored scripts refer to scripts that were {ref}/modules-scripting-using.html#modules-scripting-stored-scripts[stored]
in Elasticsearch. The following snippet shows how to refer to a script by its `id`:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"id" : "my_script"
}
}
--------------------------------------------------
As with <<condition-script-file, File>> and <<condition-script-inline, Inline>>
scripts, you can also specify the script language and parameters:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"id" : "my_script",
"lang" : "javascript",
"params" : { "color" : "red" }
}
}
--------------------------------------------------
[[accessing-watch-payload]]
==== Accessing the Watch Payload
A script can access the current watch execution context, including the payload
data, as well as any parameters passed in through the condition definition.
For example, the following snippet defines a watch that uses a <<input-search, `search` input>>
and uses a `script` condition to check if the number of hits is above a specified
threshold:
[source,js]
--------------------------------------------------
{
"input" : {
"search" : {
"indices" : "log-events",
"body" : {
"size" : 0,
"query" : { "match" : { "status" : "error" } }
}
}
},
"condition" : {
"script" : {
"inline" : "return ctx.payload.hits.total > threshold",
"params" : {
"threshold" : 5
}
}
}
}
--------------------------------------------------
When you're using a scripted condition to evaluate an Elasticsearch response,
keep in mind that the fields in the response are no longer in their native data
types. For example, the `@timestamp` in the response is a string, rather than a
`DateTime`. To compare the response `@timestamp` against the `ctx.execution_time`,
you need to parse the `@timestamp` string into a `DateTime`. For example:
[source,js]
--------------------------------------------------
org.elasticsearch.common.joda.time.DateTime.parse(@timestamp)
--------------------------------------------------
You can reference the following variables in the watch context:
[options="header"]
|======
| Name | Description
| `ctx.watch_id` | The id of the watch that is currently executing.
| `ctx.execution_time` | The time execution of this watch started.
| `ctx.trigger.triggered_time` | The time this watch was triggered.
| `ctx.trigger.scheduled_time` | The time this watch was supposed to be triggered.
| `ctx.metadata.*` | Any metadata associated with the watch.
| `ctx.payload.*` | The payload data loaded by the watch's input.
|======

View File

@ -0,0 +1,268 @@
[[customizing-watches]]
== Customizing Watches
Now that you've seen how to set up simple watches to <<watch-log-data, watch your log data>>
and <<watch-cluster-status, monitor your cluster health>>, let's take a closer
look at how you can customize a watch by modifying its <<changing-inputs, inputs>>,
<<changing-conditions, conditions>>, <<using-transforms, transforms>>, and
<<customizing-actions, actions>>.
[[changing-inputs]]
=== Changing Inputs
The Watch Input is called when the watch triggered to load an initial payload.
This payload is stored in the _Watch Execution Context_ and from then on is
available for other watch elements to access (e.g. watch conditions can
be evaluated based on the data in this payload).
{watcher} supports four types of inputs <<loading-static-data, simple>>,
<<loading-search-results, search>>, <<loading-http-data, http>>, and
<<input-chain, chain>>.
[[loading-static-data]]
==== Loading a Static Payload with the Simple Input
To load static data into the watch payload for testing purposes, you can use the
<<input-simple, simple>> input. For example, the following input stores three
fields in the payload:
[source,js]
-------------------------------------
"input" : {
"simple" : {
"color" : "red",
"status" : "error",
"count" : 3
}
}
-------------------------------------
See <<input-simple>> for more details.
[[loading-search-results]]
==== Loading a Payload from Elasticsearch with the Search Input
You can use the `search` input to load Elasticsearch search results as the watch
initial payload.
A <<input-search, search>> input contains a `request` object that specifies the
indices you want to search, the {ref}/search-request-search-type.html[search type],
and the search request body. The `body` field of a search input is the same as
the body of an Elasticsearch `_search` request, making the full Elaticsearch
Query DSL available for you to use.
For example, the following `search` input loads the latest VIX quote:
[source,js]
--------------------------------------------------
{
"input" : {
"search" : {
"request" : {
"indices" : [ "<stock-quotes-{now/d}>" ], <1>
"body" : {
"size" : 1,
"sort" : {
"timestamp" : { "order" : "desc"}
},
"query" : {
"term" : { "symbol" : "vix"}
}
}
}
}
}
}
--------------------------------------------------
<1> Will resolve to today's daily quotes index
See <<input-search>> for more details.
[[loading-http-data]]
==== Loading a Payload from a remote HTTP Service with HTTP Input
Use the `http` input to issue a HTTP request and load the returned response as
the watch initial payload. This input expects the response body content type
to either be JSON or YAML.
For example, the following `http` input loads the current weather forecast for
Amsterdam using http://openweathermap.org/appid[OpenWeatherMap] online service:
[source,js]
--------------------------------------------------
{
"input" : {
"http" : {
"request" : {
"url" : "http://api.openweathermap.org/data/2.5/weather",
"params" : {
"lat" : "52.374031",
"lon" : "4.88969",
"appid" : "<your openweathermap appid>"
}
}
}
}
}
--------------------------------------------------
See <<input-http>> for more details.
[[chaining-inputs]]
==== Chaining Inputs
You can create an <<input-chain, input chain>> to load data from multiple sources
into a watch payload. The inputs in a chain are processed in order, so the the
data loaded by one input can be used by subsequent inputs.
See <<input-chain>> for more details.
[[changing-conditions]]
=== Changing Conditions
The Watch Condition is evaluated as part of the watch execution. The condition
determines whether the actions associated with the watch should execute or not.
{watcher} supports four types of conditions <<condition-always, always>>,
<<condition-never, never>>, <<condition-compare, compare>>, and
<<condition-script, script>>.
The first two are pretty self-explanatory--they are shortcuts for setting a
watch's condition to `true` or `false`.
==== Simple Value Comparison with the Compare Condition
The `compare` condition enables you to perform simple comparisons against values
in the Watch payload. While you can also do this with a `script` condition, with
`compare` you can define inline comparisons without having to enable dynamic
scripting.
For example, the following compare condition checks to see if the `search` input
returned any hits:
[source,js]
--------------------------------------------------
"condition" : {
"compare" : { "ctx.payload.hits.total" : { "gt" : 0 }}
},
--------------------------------------------------
See <<condition-compare>> for more details.
==== Powerful Comparison Logic with the Script Condition
For more complex conditional logic you can use the `script` condition. The
`script` condition accepts a script that when executed returns `true` (indicating
the condition is met) or `false` (indicating the condition is not met). The script
language defaults to the default script language in Elasticsearch, but you can
also use any other supported language in the system.
NOTE: Starting with 5.0, Elasticsearch is shipped with the new
{ref}/modules-scripting-painless.html[Painless] scripting language.
Painless was created and designed specifically for use in Elasticsearch.
Beyond providing an extensive feature set, its biggest trait is that it's
properly sandboxed and safe to use anywhere in the system (including in
{watcher}) without the need to enable dynamic scripting.
For example, the following `script` condition checks if the change in the latest
VIX quote loaded by the `http` input is either greater than 5% or lower than -5%:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"inline" : "Math.abs(ctx.payload.hits.hits[0]._source.ChangePercent) > 5",
"lang" : "painless"
}
}
--------------------------------------------------
See <<condition-script>> for more details.
[[using-transforms]]
=== Using Transforms
Transforms are constructs in a watch that can change the current payload
associated with the watch execution context.
{watcher} supports three types of transforms <<transform-search, search>>,
<<transform-script, script>> and <<transform-chain, chain>>. A `search` transform
replaces the existing payload with the response of a new search request. You can
use `script` transforms to modify the existing payload. A `chain` transform
enables you to perform a series of `search` and `script` transforms.
See <<transform>> for more details.
[[customizing-actions]]
=== Customizing Actions
Actions are associated with a watch and are executed as part of the watch execution
only when the watch condition is met.
{watcher} supports the following action types: <<actions-email, email>>,
<<actions-slack, slack>>, <<actions-hipchat, hipchat>>, <<actions-pagerduty, pagerduty>>,
<<actions-index, index>>, <<actions-logging, logging>>, and <<actions-webhook, webhook>>.
To use the `email` action, you need to <<configuring-email, configure an email account>>
in `elasticsearch.yml` that {watcher} can use to send email. Your custom email
messages can be plain text or styled using HTML. You can include information from
the watch execution payload using <<templates, templates>>, as well as attach the
entire watch payload to the message.
For example, the following email action uses a template in the email body and
attaches the payload data to the message:
[source,js]
--------------------------------------------------
"actions" : {
"send_email" : { <1>
"email" : { <2>
"to" : "<username>@<domainname>",
"subject" : "Watcher Notification",
"body" : "{{ctx.payload.hits.total}} error logs found",
"attachments" : {
"data_attachment" : {
"data" : {
"format" : "json"
}
}
}
}
}
}
--------------------------------------------------
<1> The id of the action
<2> The action type, in this case it's an `email` action
Another example for an action is the `webhook` action. This enables you to send
a request to any external webservice. For example, the following `webhook` action
creates a new issue in GitHub
[source,js]
--------------------------------------------------
"actions" : {
"create_github_issue" : {
"webhook" : {
"method" : "POST",
"url" : "https://api.github.com/repos/<owner>/<repo>/issues", <1>
"body" : "{
\"title\": \"Found errors in 'contact.html'\",
\"body\": \"Found {{ctx.payload.hits.total}} errors in this page in the last 5 minutes\",
\"assignee\": \"web-admin\",
\"labels\": [ \"bug\", \"sev2\" ]
}",
"auth" : {
"basic" : {
"username" : "<username>", <2>
"password" : "<password>" <3>
}
}
}
}
}
--------------------------------------------------
<1> `<owner>` is the owner of the GitHub repo and `<repo>` is the name of the repo.
<2> The username that creates the issue
<3> The password of that user
To learn how to create other actions see <<actions>>.

View File

@ -0,0 +1,14 @@
[[example-watches]]
== Example Watches
The following examples show how to set up watches to:
* <<watch-cluster-status, Monitor the Status of an Elasticsearch Cluster>>
* <<watching-meetup-data, Monitor Event Data>>
For more example watches you can use as a starting point for building custom
watches, see the https://github.com/elastic/examples/tree/master/Alerting[Example
Watches] in the Elastic Examples repo.
include::example-watches/example-watch-clusterstatus.asciidoc[]
include::example-watches/example-watch-meetupdata.asciidoc[]

View File

@ -0,0 +1,287 @@
[[watch-cluster-status]]
=== Watching the Status of an Elasticsearch Cluster
You can easily configure a basic watch to monitor the health of your
Elasticsearch cluster:
* <<health-add-input, Schedule the watch and define an input>> that gets the
cluster health status.
* <<health-add-condition, Add a condition>> that evaluates the health status to
determine if action is required.
* <<health-take-action, Take action>> if the cluster is RED.
[float]
[[health-add-input]]
==== Schedule the Watch and Add an Input
A watch <<trigger-schedule, schedule>> controls how often a watch is triggered.
The watch <<input, input>> gets the data that you want to evaluate.
The simplest way to define a schedule is to specify an interval. For example,
the following schedule runs every 10 seconds:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/cluster_health_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" } <1>
}
}
--------------------------------------------------
// CONSOLE
<1> Schedules are typically configured to run less frequently. This example sets
the interval to 10 seconds to you can easily see the watches being triggered.
Since this watch runs so frequently, don't forget to <<health-delete, delete the watch>>
when you're done experimenting.
To get the status of your cluster, you can call the Elasticsearch
{ref}//cluster-health.html[cluster health] API:
[source,js]
--------------------------------------------------
GET _cluster/health?pretty
--------------------------------------------------
// CONSOLE
// TEST[continued]
To load the health status into your watch, you simply add an
<<input-http, HTTP input>> that calls the cluster health API:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/cluster_health_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" }
},
"input" : {
"http" : {
"request" : {
"host" : "localhost",
"port" : 9200,
"path" : "/_cluster/health"
}
}
}
}
--------------------------------------------------
// CONSOLE
If you're using Security, then you'll also need to supply some authentication credentials as part of the watch configuration:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/cluster_health_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" }
},
"input" : {
"http" : {
"request" : {
"host" : "localhost",
"port" : 9200,
"path" : "/_cluster/health",
"auth": {
"basic": {
"username": "elastic",
"password": "changeme"
}
}
}
}
}
}
--------------------------------------------------
// CONSOLE
It would be a good idea to create a user with the minimum privileges required for use with such a watch configuration.
Depending on how your cluster is configured, there may be additional settings required before the watch can access your cluster such as keystores, truststores or certificates.
See the {ref}//notification-settings.html[Notification Settings] section of the X-Pack Settings documentation.
If you check the watch history, you'll see that the cluster status is recorded
as part of the `watch_record` each time the watch executes.
For example, the following request retrieves the last ten watch records from
the watch history:
[source,js]
--------------------------------------------------
GET .watcher-history*/_search
{
"sort" : [
{ "result.execution_time" : "desc" }
]
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[health-add-condition]]
==== Add a Condition
A <<condition, condition>> evaluates the data you've loaded into the watch and
determines if any action is required. Since you've defined an input that loads
the cluster status into the watch, you can define a condition that checks that
status.
For example, you could add a condition to check to see if the status is RED.
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/cluster_health_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" } <1>
},
"input" : {
"http" : {
"request" : {
"host" : "localhost",
"port" : 9200,
"path" : "/_cluster/health"
}
}
},
"condition" : {
"compare" : {
"ctx.payload.status" : { "eq" : "red" }
}
}
}
--------------------------------------------------
// CONSOLE
<1> Schedules are typically configured to run less frequently. This example sets
the interval to 10 seconds to you can easily see the watches being triggered.
If you check the watch history, you'll see that the condition result is recorded
as part of the `watch_record` each time the watch executes.
To check to see if the condition was met, you can run the following query.
[source,js]
------------------------------------------------------
GET .watcher-history*/_search?pretty
{
"query" : {
"match" : { "result.condition.met" : true }
}
}
------------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[health-take-action]]
==== Take Action
Recording `watch_records` in the watch history is nice, but the real power of
{watcher} is being able to do something in response to an alert. A watch's
<<actions, actions>> define what to do when the watch condition is true--you
can send emails, call third-party webhooks, or write documents to an
Elasticsearch index or log when the watch condition is met.
For example, you could add an action to index the cluster status information
when the status is RED.
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/cluster_health_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" }
},
"input" : {
"http" : {
"request" : {
"host" : "localhost",
"port" : 9200,
"path" : "/_cluster/health"
}
}
},
"condition" : {
"compare" : {
"ctx.payload.status" : { "eq" : "red" }
}
},
"actions" : {
"send_email" : {
"email" : {
"to" : "<username>@<domainname>",
"subject" : "Cluster Status Warning",
"body" : "Cluster status is RED"
}
}
}
}
--------------------------------------------------
// CONSOLE
For {watcher} to send email, you must configure an email account in your
`elasticsearch.yml` configuration file and restart Elasticsearch. To add an email
account, set the `xpack.notification.email.account` property.
For example, the following snippet configures a single Gmail account named `work`:
[source,yaml]
----------------------------------------------------------
xpack.notification.email.account:
work:
profile: gmail
email_defaults:
from: <email> <1>
smtp:
auth: true
starttls.enable: true
host: smtp.gmail.com
port: 587
user: <username> <2>
password: <password> <3>
----------------------------------------------------------
<1> Replace `<email>` with the email address from which you want to send
notifications.
<2> Replace `<username>` with your Gmail user name (typically your Gmail address).
<3> Replace `<password>` with your Gmail password.
NOTE: If you have advanced security options enabled for your email account,
you need to take additional steps to send email from {watcher}. For more
information, see <<configuring-email, Working with Various Email Services>>.
You can check the watch history or the `status_index` to see that the action was
performed.
[source,js]
-------------------------------------------------------
GET .watcher-history*/_search?pretty
{
"query" : {
"match" : { "result.condition.met" : true }
}
}
-------------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[health-delete]]
==== Delete the Watch
Since the `cluster_health_watch` is configured to run every 10 seconds, make
sure you delete it when you're done experimenting. Otherwise, you'll spam yourself
indefinitely.
To remove the watch, use the <<watcher-api-delete-watch, DELETE watch>> API:
[source,js]
-------------------------------------------------------
DELETE _xpack/watcher/watch/cluster_health_watch
-------------------------------------------------------
// CONSOLE
// TEST[continued]

View File

@ -0,0 +1,285 @@
[[watching-meetup-data]]
=== Watching Event Data
If you are indexing event data, such as log messages, network traffic, or a web feed, you can create a watch to email notifications when certain events occur.
For example, if you index a feed of RSPVs for meetup events happening around the world, you can create a watch that alerts you to interesting events.
To index the meetup data, you can use https://www.elastic.co/products/logstash[Logstash] to ingest live data from the Meetup.com streaming API, `http://stream.meetup.com/2/rsvps`.
To ingest this data with Logstash:
. https://www.elastic.co/downloads/logstash[Download Logstash] and unpack the
archive file.
. Create a Logstash configuration file that uses the {logstash-ref}/plugins-inputs-stdin.html[Logstash standard input] and the {logstash-ref}/plugins-outputs-stdout.html[Logstash standard output] and save it in `logstash-{version}` directory as `livestream.conf`:
+
[source,ruby]
----------------------------------------------------------
input {
stdin {
codec => json <1>
}
}
filter {
date {
match => [ "event.time", "UNIX_MS" ]
target => "event_time"
}
}
output { <2>
stdout {
codec => rubydebug
}
elasticsearch {
hosts => "http://localhost:9200"
user => "elastic"
password => "changeme"
}
}
----------------------------------------------------------
<1> The meetup data stream is formatted in JSON.
<2> Index the meetup data into Elasticsearch.
. To start indexing the meetup data, pipe the RSVP stream into Logstash and specify your `livestream.conf` configuration file.
+
[source,she]
----------------------------------------------------------
curl http://stream.meetup.com/2/rsvps | bin/logstash -f livestream.conf
---------------------------------------------------------
Now that you're indexing the meetup RSVPs, you can set up a watch that lets you know about events you might be interested in. For example, let's create a watch that runs every hour, looks for events that talk about about _Open Source_, and sends an email with information about the events.
To set up the watch:
. Specify how often you want to run the watch by adding a schedule trigger to the watch:
+
[source,js]
--------------------------------------------------
{
"trigger": {
"schedule": {
"interval": "1h"
}
},
--------------------------------------------------
. Load data into the watch payload by creating an input that searches the meetup data for events that have _Open Source_ as a topic. You can use aggregations to group the data by city, consolidate references to the same events, and sort the events by date.
+
[source,js]
-------------------------------------------------
"input": {
"search": {
"request": {
"indices": [
"<logstash-{now-1h}>", <1>
"<logstash-{now}>"
],
"body": {
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-3h"
}
}
},
{
"match": {
"group.group_topics.topic_name": "Open Source" <2>
}
}
]
}
},
"aggs": {
"group_by_city": {
"terms": {
"field": "group.group_city.raw", <3>
"size": 5
},
"aggs": {
"group_by_event": {
"terms": {
"field": "event.event_url.raw", <4>
"size": 5
},
"aggs": {
"get_latest": {
"terms": {
"field": "@timestamp", <5>
"size": 1,
"order": {
"_term": "desc"
}
},
"aggs": {
"group_by_event_name": {
"terms": {
"field": "event.event_name.raw" <6>
}
}
}
}
}
}
}
}
}
}
}
}
},
--------------------------------------------------
<1> Elasticsearch Date math is used to select the Logstash indices that contain the meetup data. The second pattern is needed in case the previous hour crosses days.
<2> Find all of the RSVPs with `Open Source` as a topic.
<3> Group the RSVPs by city.
<4> Consolidate multiple RSVPs for the same event.
<5> Sort the events so the latest events are listed first.
<6> Group the events by name.
. To determine whether or not there are any Open Source events, add a compare condition that checks the watch payload to see if there were any search hits.
[source,js]
--------------------------------------------------
"compare" : { "ctx.payload.hits.total" : { "gt" : 0 }}
--------------------------------------------------
. To send an email when _Open Source_ events are found, add an email action:
[source,js]
--------------------------------------------------
"actions": {
"email_me": {
"throttle_period": "10m",
"email": {
"from": "<from:email address>",
"to": "<to:email address>",
"subject": "Open Source Events",
"body": {
"html": "Found events matching Open Source: <ul>{{#ctx.payload.aggregations.group_by_city.buckets}}< li>{{key}} ({{doc_count}})<ul>{{#group_by_event.buckets}}
<li><a href=\"{{key}}\">{{get_latest.buckets.0.group_by_event_name.buckets.0.key}}</a>
({{doc_count}})</li>{{/group_by_event.buckets}}</ul></li>
{{/ctx.payload.aggregations.group_by_city.buckets}}</ul>"
}
}
}
}
---------------------------------------------------
NOTE: To enable Watcher to send emails, you must configure an email account in `elasticsearch.yml`. For more information, see <<configuring-email, Working with Various Email Services>>.
The complete watch looks like this:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/meetup
{
"trigger": {
"schedule": {
"interval": "1h"
}
},
"input": {
"search": {
"request": {
"indices": [
"<logstash-{now-1h}>",
"<logstash-{now}>"
],
"body": {
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-3h"
}
}
},
{
"match": {
"group.group_topics.topic_name": "Open Source"
}
}
]
}
},
"aggs": {
"group_by_city": {
"terms": {
"field": "group.group_city.raw",
"size": 5
},
"aggs": {
"group_by_event": {
"terms": {
"field": "event.event_url.raw",
"size": 5
},
"aggs": {
"get_latest": {
"terms": {
"field": "@timestamp",
"size": 1,
"order": {
"_term": "desc"
}
},
"aggs": {
"group_by_event_name": {
"terms": {
"field": "event.event_name.raw"
}
}
}
}
}
}
}
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 0
}
}
},
"actions": { <1>
"email_me": {
"throttle_period": "10m",
"email": {
"from": "<username>@<domainname>", <2>
"to": "<username@<domainname>", <3>
"subject": "Open Source events",
"body": {
"html": "Found events matching Open Source: <ul>{{#ctx.payload.aggregations.group_by_city.buckets}}<li>{{key}} ({{doc_count}})<ul>{{#group_by_event.buckets}}<li><a href=\"{{key}}\">{{get_latest.buckets.0.group_by_event_name.buckets.0.key}}</a> ({{doc_count}})</li>{{/group_by_event.buckets}}</ul></li>{{/ctx.payload.aggregations.group_by_city.buckets}}</ul>"
}
}
}
}
}
--------------------------------------------------
// CONSOLE
<1> The email body can include Mustache templates to reference data in the watch payload. By default,it will be <<email-html-sanitization, sanitized>> to block dangerous content.
<2> Replace the `from` address with the email address you configured in `elasticsearch.yml`.
<3> Replace the `to` address with your email address to receive notifications.
Now that you've created your watch, you can use the <<watcher-api-execute-watch, `_execute`>> API to run it without waiting for the schedule to trigger execution:
[source,js]
--------------------------------------------------
POST _xpack/watcher/watch/meetup/_execute
--------------------------------------------------
// CONSOLE
// TEST[continued]

View File

@ -0,0 +1,229 @@
[[watching-time-series-data]]
=== Watching Time Series Data
If you are indexing time-series data such as logs, RSS feeds, or network traffic,
you can use {watcher} to send notifications when certain events occur.
For example, you could index an RSS feed of posts on Stack Overflow that are
tagged with Elasticsearch, Logstash, Beats, or Kibana, set up a watch to check
daily for new posts about a problem or failure, and send an email if any are
found.
The simplest way to index an RSS feed is to use https://www.elastic.co/products/logstash[Logstash].
To install Logstash and set up the RSS input plugin:
. https://www.elastic.co/downloads/logstash[Download Logstash] and unpack the
archive file.
. Go to the `logstash-{version}` directory and install the
{logstash-ref}/plugins-inputs-rss.html[RSS input] plugin:
+
[source,sh]
----------------------------------------------------------
cd logstash-<logstash_version>
bin/logstash-plugin install logstash-input-rss
----------------------------------------------------------
. Create a Logstash configuration file that uses the RSS input plugin to get
data from an RSS/atom feed and outputs the data to Elasticsearch. For example,
the following `rss.conf` file gets events from the Stack Overflow feed that
are tagged with `elasticsearch`, `logstash`, `beats` or `kibana`.
+
[source,ruby]
----------------------------------------------------------
input {
rss {
url => "http://stackoverflow.com/feeds/tag/elasticsearch+or+logstash+or+beats+or+kibana"
interval => 3600 <1>
}
}
output {
elasticsearch { }
stdout { }
}
----------------------------------------------------------
<1> Checks the feed every hour.
+
For more information see {logstash-ref}/plugins-outputs-elasticsearch.html[Elasticsearch output]
in the Logstash Reference.
. Run Logstash with the `rss.conf` config file to start indexing the feed:
+
[source,she]
----------------------------------------------------------
bin/logstash -f rss.conf
----------------------------------------------------------
Once you have Logstash set up to input data from the RSS feed into Elasticsearch,
you can set up a daily watch that runs at noon to check for new posts that
contain the words "error" or "problem".
To set up the watch:
. Define the watch trigger--a daily schedule that runs at 12:00 UTC:
+
[source,js]
--------------------------------------------------
"trigger" : {
"schedule" : {
"daily" : { "at" : "12:00" }
}
}
--------------------------------------------------
+
NOTE: In {watcher}, you specify times in UTC time. Don't forget to do the
conversion from your local time so the schedule triggers at the time
you intend.
. Define the watch input--a search that uses a filter to constrain the results
to the past day.
+
[source,js]
--------------------------------------------------
"input" : {
"search" : {
"request" : {
"indices" : [ "logstash*" ],
"body" : {
"query" : {
"bool" : {
"must" : { "match" : { "message": "error problem" }},
"filter" : { "range" : { "@timestamp" : { "gte" : "now-1d" }}}
}
}
}
}
}
}
--------------------------------------------------
. Define a watch condition to check the payload to see if the input search
returned any hits. If it did, the condition resolves to `true` and the watch
actions will be executed.
+
You define the condition with the following script:
+
[source,text]
--------------------------------------------------
return ctx.payload.hits.total > threshold
--------------------------------------------------
+
If you store the script in a file at `$ES_HOME/config/scripts/threshold_hits.painless`,
you can then reference it by name in the watch condition.
+
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"file" : "threshold_hits",
"params" : {
"threshold" : 0 <1>
}
}
}
--------------------------------------------------
<1> The threshold parameter value you want to pass to the script.
+
. Define a watch action to send an email that contains the relevant messages
from the past day as an attachment.
+
[source,js]
--------------------------------------------------
"actions" : {
"send_email" : {
"email" : {
"to" : "<username>@<domainname>",
"subject" : "Somebody needs help with the Elastic Stack",
"body" : "The attached Stack Overflow posts were tagged with Elasticsearch, Logstash, Beats or Kibana and mentioned an error or problem.",
"attachments" : {
"attached_data" : {
"data" : {
"format" : "json"
}
}
}
}
}
}
--------------------------------------------------
+
NOTE: To use the email action, you must configure at least one email account in
`elasticsearch.yml`. If you configure multiple email accounts, you need to
specify which one you want to send the email with. For more information, see
<<configuring-email, Working with Various Email Services>>.
The complete watch looks like this:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/rss_watch
{
"trigger" : {
"schedule" : {
"daily" : { "at" : "12:00" }
}
},
"input" : {
"search" : {
"request" : {
"indices" : [ "logstash*" ],
"body" : {
"query" : {
"bool" : {
"must" : { "match" : { "message": "error problem" }},
"filter" : { "range" : { "@timestamp" : { "gte" : "now-1d" }}}
}
}
}
}
}
},
"condition" : {
"script" : {
"file" : "threshold_hits",
"params" : {
"threshold" : 0
}
}
},
"actions" : {
"send_email" : {
"email" : {
"to" : "<username>@<domainname>", <1>
"subject" : "Somebody needs help with the Elastic Stack",
"body" : "The attached Stack Overflow posts were tagged with Elasticsearch, Logstash, Beats or Kibana and mentioned an error or problem.",
"attachments" : {
"attached_data" : {
"data" : {}
}
}
}
}
}
}
--------------------------------------------------
// CONSOLE
// TEST[s/"file" : "threshold_hits"/"inline": "return ctx.payload.hits.total > params.threshold"/]
<1> Replace `<username>@<domainname>` with your email address to receive
notifications.
[TIP]
=================================================
To execute a watch immediately (without waiting for the schedule to trigger),
use the <<watcher-api-execute-watch, `_execute`>> API:
[source,js]
--------------------------------------------------
POST _xpack/watcher/watch/rss_watch/_execute
{
"ignore_condition" : true,
"action_modes" : {
"_all" : "force_execute"
},
"record_execution" : true
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
=================================================

View File

@ -0,0 +1,224 @@
[[watcher-getting-started]]
== Getting Started with {watcher}
{Watcher} is automatically enabled when you <<installing-xpack, install
{xpack}>> into Elasticsearch and Kibana.
[[watch-log-data]]
To set up a watch to start sending alerts:
* <<log-add-input, Schedule the watch and define an input>>.
* <<log-add-condition, Add a condition>> that checks to see if an alert
needs to be sent.
* <<log-take-action, Configure an action>> to send an alert when the
condition is met.
[float]
[[log-add-input]]
=== Schedule the Watch and Define an Input
A watch <<trigger-schedule, schedule>> controls how often a watch is triggered.
The watch <<input, input>> gets the data that you want to evaluate.
To periodically search log data and load the results into the
watch, you could use an <<schedule-interval, interval>> schedule and a
<<input-search, search>> input. For example, the following Watch searches
the `logs` index for errors every 10 seconds:
[source,js]
------------------------------------------------------------
PUT _xpack/watcher/watch/log_error_watch
{
"trigger" : {
"schedule" : { "interval" : "10s" } <1>
},
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"body" : {
"query" : {
"match" : { "message": "error" }
}
}
}
}
}
}
------------------------------------------------------------
// CONSOLE
<1> Schedules are typically configured to run less frequently. This example sets
the interval to 10 seconds so you can easily see the watches being triggered.
Since this watch runs so frequently, don't forget to <<log-delete, delete the watch>>
when you're done experimenting.
If you check the watch history you'll see that the watch is being triggered every
10 seconds. However, the search isn't returning any results so nothing is loaded
into the watch payload.
For example, the following request retrieves the last ten watch executions (watch
records) from the watch history:
[source,js]
------------------------------------------------------------
GET .watcher-history*/_search?pretty
{
"sort" : [
{ "result.execution_time" : "desc" }
]
}
------------------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[log-add-condition]]
=== Add a Condition
A <<condition, condition>> evaluates the data you've loaded into the watch and
determines if any action is required. Now that you've loaded log errors into
the watch, you can define a condition that checks to see if any errors were
found.
For example, the following compare condition simply checks to see if the
search input returned any hits.
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/log_error_watch
{
"trigger" : { "schedule" : { "interval" : "10s" }},
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"body" : {
"query" : {
"match" : { "message": "error" }
}
}
}
}
},
"condition" : {
"compare" : { "ctx.payload.hits.total" : { "gt" : 0 }} <1>
}
}
--------------------------------------------------
// CONSOLE
<1> The <<condition-compare, compare>> condition lets you easily compare against
values in the execution context.
For this compare condition to evaluate to `true`, you need to add an event
to the `logs` index that contains an error. For example, the following request
adds a 404 error to the `logs` index:
[source,js]
--------------------------------------------------
POST logs/event
{
"timestamp" : "2015-05-17T18:12:07.613Z",
"request" : "GET index.html",
"status_code" : 404,
"message" : "Error: File not found"
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
Once you add this event, the next time the watch executes its condition will
evaluate to `true`. The condition result is recorded as part of the
`watch_record` each time the watch executes, so you can verify whether or
not the condition was met by searching the watch history:
[source,js]
--------------------------------------------------
GET .watcher-history*/_search?pretty
{
"query" : {
"bool" : {
"must" : [
{ "match" : { "result.condition.met" : true }},
{ "range" : { "result.execution_time" : { "from" : "now-10s" }}}
]
}
}
}
--------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[log-take-action]]
=== Configure an Action
Recording watch records in the watch history is nice, but the real power of
{watcher} is being able to do something when the watch condition is met. A
watch's <<actions, actions>> define what to do when the watch condition
evaluates to `true`. You can send emails, call third-party webhooks, write
documents to an Elasticsearch index, or log messages to the standard
Elasticsearch log files.
For example, the following action writes a message to the Elasticsearch
log when an error is detected.
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/log_error_watch
{
"trigger" : { "schedule" : { "interval" : "10s" }},
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"body" : {
"query" : {
"match" : { "message": "error" }
}
}
}
}
},
"condition" : {
"compare" : { "ctx.payload.hits.total" : { "gt" : 0 }}
},
"actions" : {
"log_error" : {
"logging" : {
"text" : "Found {{ctx.payload.hits.total}} errors in the logs"
}
}
}
}
--------------------------------------------------
// CONSOLE
[float]
[[log-delete]]
=== Delete the Watch
Since the `log_error_watch` is configured to run every 10 seconds, make sure you
delete it when you're done experimenting. Otherwise, the noise from this sample
watch will make it hard to see what else is going on in your watch history and
log file.
To remove the watch, use the <<watcher-api-delete-watch, DELETE watch>> API:
[source,js]
--------------------------------------------------
DELETE _xpack/watcher/watch/log_error_watch
--------------------------------------------------
// CONSOLE
// TEST[continued]
[float]
[[next-steps]]
=== Where to Go Next
* See <<how-watcher-works, How {watcher} Works>> for more information about the
anatomy of a watch and the watch lifecycle.
* See <<example-watches, Example Watches>> for more examples of setting up
a watch.
* See the https://github.com/elastic/examples/tree/master/Alerting[Example
Watches] in the Elastic Examples repo for additional sample watches you can use
as a starting point for building custom watches.

View File

@ -0,0 +1,445 @@
[[how-watcher-works]]
== How {watcher} Works
You <<watch-definition, add watches>> to automatically perform an action when
certain conditions are met. The conditions are generally based on data you've
loaded into the watch, also known as the _Watch Payload_. This payload can be
loaded from different sources - from Elasticsearch, an external HTTP service, or
even a combination of the two.
For example, you could configure a watch to send an email to the sysadmin when a
search in the logs data indicates that there are too many 503 errors in the last
5 minutes.
This topic describes the elements of a watch and how watches operate.
[float]
[[watch-definition]]
=== Watch Definition
A watch consists of a _trigger_, _input_, _condition_, and _actions_. The actions
define what needs to be done once the condition is met. In addition, you can
define _conditions_ and _transforms_ to process and prepare the watch payload before
executing the actions.
<<trigger,Trigger>>::
Determines when the watch is checked. A watch must have a trigger.
<<input,Input>>::
Loads data into the watch payload. If no input is specified, an empty payload is
loaded.
<<condition,Condition>>::
Controls whether the watch actions are executed. If no condition is specified,
the condition defaults to `always`.
<<transform,Transform>>::
Processes the watch payload to prepare it for the watch actions. You can define
transforms at the watch level or define action-specific transforms. Optional.
<<actions,Actions>>::
Specify what happens when the watch condition is met.
[[watch-definition-example]]
For example, the following snippet shows a <<watcher-api-put-watch, Put Watch>>
request that defines a watch that looks for log error events:
[source,js]
--------------------------------------------------
PUT _xpack/watcher/watch/log_errors
{
"metadata" : { <1>
"color" : "red"
},
"trigger" : { <2>
"schedule" : {
"interval" : "5m"
}
},
"input" : { <3>
"search" : {
"request" : {
"indices" : "log-events",
"body" : {
"size" : 0,
"query" : { "match" : { "status" : "error" } }
}
}
}
},
"condition" : { <4>
"compare" : { "ctx.payload.hits.total" : { "gt" : 5 }}
},
"transform" : { <5>
"search" : {
"request" : {
"indices" : "log-events",
"body" : {
"query" : { "match" : { "status" : "error" } }
}
}
}
},
"actions" : { <6>
"my_webhook" : {
"webhook" : {
"method" : "POST",
"host" : "mylisteninghost",
"port" : 9200,
"path" : "/{{watch_id}}",
"body" : "Encountered {{ctx.payload.hits.total}} errors"
}
},
"email_administrator" : {
"email" : {
"to" : "sys.admino@host.domain",
"subject" : "Encountered {{ctx.payload.hits.total}} errors",
"body" : "Too many error in the system, see attached data",
"attachments" : {
"attached_data" : {
"data" : {
"format" : "json"
}
}
},
"priority" : "high"
}
}
}
}
--------------------------------------------------
// CONSOLE
<1> Metadata - You can attach optional static metadata to a watch.
<2> Trigger - This schedule trigger executes the watch every 5 minutes.
<3> Input - This input searches for errors in the `log-events` index and
loads the response into the watch payload.
<4> Condition - This condition checks to see if there are more than 5 error
events (hits in the search response). If there are, execution
continues for all `actions`.
<5> Transform - If the watch condition is met, this transform loads all of the
errors into the watch payload by searching for the errors using
the default search type, `query_then_fetch`. All of the watch
actions have access to this payload.
<6> Actions - This watch has two actions. The `my_webhook` action notifies a
3rd party system about the problem. The `email_administrator`
action sends a high priority email to the system administrator.
The watch payload that contains the errors is attached to the
email.
[float]
[[watch-execution]]
=== Watch Execution
[[schedule-scheduler]]
When you add a watch, {watcher} immediately registers its trigger with the
appropriate trigger engine. Watches that have a `schedule` trigger are
registered with the `scheduler` trigger engine.
The scheduler tracks time and triggers watches according to their schedules.
The scheduler runs on the master node and is bound to the lifecycle of the
{watcher} service. When the {watcher} service is stopped, the scheduler
stops with it. Trigger engines use a separate thread pool from the one used
to execute watches.
When a watch is triggered, {watcher} queues it up for execution. A `watch_record`
document is created and added to the watch history and the watch's status is set
to `awaits_execution`.
When execution starts, {watcher} creates a watch execution context for the watch.
The execution context provides scripts and templates with access to the watch
metadata, payload, watch ID, execution time, and trigger information. For more
information, see <<watch-execution-context, Watch Execution Context>>.
During the execution process, {watcher}:
. Loads the input data as the payload in the watch execution context. This makes
the data available to all subsequent steps in the execution process. This step
is controlled by the input of the watch.
. Evaluates the watch condition to determine whether or not to continue processing
the watch. If the condition is met (evaluates to `true`), processing advances
to the next step. If it is not met (evaluates to `false`), execution of the watch
stops.
. Applies transforms to the watch payload (if needed).
. Executes the watch actions granted the condition is met and the watch is not
<<watch-acknowledgment-throttling, throttled>>.
When the watch execution finishes, the execution result is recorded as a
_Watch Record_ in the watch history. The watch record includes the execution
time and duration, whether the watch condition was met, and the status of each
action that was executed.
The following diagram shows the watch execution process:
image::watch-execution.jpg[align="center"]
[float]
[[watch-acknowledgment-throttling]]
=== Watch Acknowledgment and Throttling
{watcher} supports both time-based and acknowledgment-based throttling. This
enables you to prevent actions from being repeatedly executed for the same event.
By default, {watcher} uses time-based throttling with a throttle period of 5
seconds. This means that if a watch is executed every second, its actions are
performed a maximum of once every 5 seconds, even when the condition is always
met. You can configure the throttle period on a per-action basis or at the
watch level.
Acknowledgment-based throttling enables you to tell {watcher} not to send any more
notifications about a watch as long as its condition is met. Once the condition
evaluates to `false`, the acknowledgment is cleared and {watcher} resumes executing
the watch actions normally.
For more information, see <<actions-ack-throttle>>.
[float]
[[watch-active-state]]
=== Watch Active State
By default, when you add a watch it is immediately set to the _active_ state,
registered with the appropriate trigger engine, and executed according
to its configured trigger.
You can also set a watch to the _inactive_ state. Inactive watches are not
registered with a trigger engine and can never be triggered.
To set a watch to the inactive state when you create it, set the
<<watcher-api-put-watch-active-state, `active`>> parameter to _inactive_.
To deactivate an existing watch, use the <<watcher-api-deactivate-watch, D
eactivate Watch API>>. To reactivate an inactive watch, use the
<<watcher-api-activate-watch, Activate Watch API>>.
NOTE: You can use the <<watcher-api-execute-watch, Execute Watch API>> to
force the execution of a watch even when it is inactive.
Deactivating watches is useful in a variety of situations. For example, if you
have a watch that monitors an external system and you need to take that system
down for maintenance, you can deactivate the watch to prevent it from falsely
reporting availability issues during the maintenance window.
Deactivating a watch also enables you to keep it around for future use without
deleting it from the system.
[float]
[[scripts-templates]]
=== Scripts and Templates
You can use scripts and templates when defining a watch. Scripts and templates
can reference elements in the watch execution context, including the watch payload.
The execution context defines variables you can use in a script and parameter
placeholders in a template.
{watcher} uses the Elasticsearch script infrastructure, which supports
<<inline-templates-scripts,inline>>, <<stored-templates-scripts, stored>>, and
<<file-templates-scripts, file-based scripts>>. Scripts and templates are compiled
and cached by Elasticsearch to optimize recurring execution.
{ref}/modules-scripting-using.html#reload-scripts[Autoloading] is also
supported. For more information, see {ref}/modules-scripting.html[Scripting]
in the Elasticsearch Reference.
[float]
[[watch-execution-context]]
==== Watch Execution Context
The following snippet shows the basic structure of the _Watch Execution Context_:
[source,js]
----------------------------------------------------------------------
{
"ctx" : {
"metadata" : { ... }, <1>
"payload" : { ... }, <2>
"watch_id" : "<id>", <3>
"execution_time" : "20150220T00:00:10Z", <4>
"trigger" : { <5>
"triggered_time" : "20150220T00:00:10Z",
"scheduled_time" : "20150220T00:00:00Z"
},
"vars" : { ... } <6>
}
----------------------------------------------------------------------
<1> Any static metadata specified in the watch definition.
<2> The current watch payload.
<3> The id of the executing watch.
<4> A timestamp that shows when the watch execution started.
<5> Information about the trigger event. For a `schedule` trigger, this
consists of the `triggered_time` (when the watch was triggered)
and the `scheduled_time` (when the watch was scheduled to be triggered).
<6> Dynamic variables that can be set and accessed by different constructs
during the execution. These variables are scoped to a single execution
(i.e they're not persisted and can't be used between different executions
of the same watch)
[float]
[[scripts]]
==== Using Scripts
You can use scripts to define <<condition-script, conditions>> and
<<transform-script, transforms>>. The default scripting language is
{ref}/modules-scripting-painless.html[Painless].
NOTE: Starting with 5.0, Elasticsearch is shipped with the new
{ref}/modules-scripting-painless.html[Painless] scripting language.
Painless was created and designed specifically for use in Elasticsearch.
Beyond providing an extensive feature set, its biggest trait is that it's
properly sandboxed and safe to use anywhere in the system (including in
{watcher}) without the need to enable dynamic scripting.
Scripts can reference any of the values in the watch execution context or values
explicitly passed through script parameters.
For example, if the watch metadata contains a `color` field
(e.g. `"metadata" : {"color": "red"}`), you can access its value with the via the
`ctx.metadata.color` variable. If you pass in a `color` parameter as part of the
condition or transform definition (e.g. `"params" : {"color": "red"}`), you can
access its value via the `color` variable.
[float]
[[templates]]
==== Using Templates
You use templates to define dynamic content for a watch. At execution time,
templates pull in data from the watch execution context. For example, you can use
a template to populate the `subject` field for an `email` action with data stored
in the watch payload. Templates can also access values explicitly passed through
template parameters.
You specify templates using the https://mustache.github.io[Mustache] scripting
language.
For example, the following snippet shows how templates enable dynamic subjects
in sent emails:
[source,js]
----------------------------------------------------------------------
{
"actions" : {
"email_notification" : {
"email" : {
"subject" : "{{ctx.metadata.color}} alert"
}
}
}
}
----------------------------------------------------------------------
[float]
[[inline-templates-scripts]]
===== Inline Templates and Scripts
To define an inline template or script, you simply specify it directly in the
value of a field. For example, the following snippet configures the subject of
the `email` action using an inline template that references the `color` value in
the context metadata.
[source,js]
----------------------------------------------------------------------
"actions" : {
"email_notification" : {
"email" : {
"subject" : "{{ctx.metadata.color}} alert"
}
}
}
}
----------------------------------------------------------------------
For a script, you simply specify the inline script as the value of the `script`
field. For example:
[source,js]
----------------------------------------------------------------------
"condition" : {
"script" : "return true"
}
----------------------------------------------------------------------
You can also explicitly specify the inline type by using a formal object
definition as the field value. For example:
[source,js]
----------------------------------------------------------------------
"actions" : {
"email_notification" : {
"email" : {
"subject" : {
"inline" : "{{ctx.metadata.color}} alert"
}
}
}
}
----------------------------------------------------------------------
The formal object definition for a script would be:
[source,js]
----------------------------------------------------------------------
"condition" : {
"script" : {
"inline": "return true"
}
}
----------------------------------------------------------------------
[float]
[[stored-templates-scripts]]
===== Stored Templates and Scripts
If you {ref}/modules-scripting-using.html#modules-scripting-stored-scripts[store]
your templates and scripts, you can reference them by id.
To reference a stored script or template, you use the formal object definition
and specify its id in the `id` field. For example, the following snippet
references the `email_notification_subject` template:
[source,js]
----------------------------------------------------------------------
{
...
"actions" : {
"email_notification" : {
"email" : {
"subject" : {
"id" : "email_notification_subject",
"params" : {
"color" : "red"
}
}
}
}
}
}
----------------------------------------------------------------------
[float]
[[file-templates-scripts]]
===== File-based Templates and Scripts
If you store templates or scripts in the `$ES_HOME/config/scripts` directory, you
can reference them by name. Template files must be saved with the extension
`.mustache`. Script files must be saved with the appropriate file extension, such
as `.painless`.
NOTE: The `config/scripts` directory is scanned periodically for changes. New
and changed templates and scripts are reloaded and deleted templates and
scripts are removed from the preloaded scripts cache. For more information,
see {ref}/modules-scripting-using.html#reload-scripts[Automatic Script
Reloading] in the Elasticsearch Reference.
To reference a file-based stored or script, you use the formal object definition
and specify its name in the `file` field. For example, the following snippet
references the script file `threshold_hits.painless`:
[source,js]
--------------------------------------------------
"condition" : {
"script" : {
"file" : "threshold_hits",
"params" : {
"threshold" : 0
}
}
}
--------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

View File

@ -0,0 +1,87 @@
[[xpack-alerting]]
= Alerting on Cluster and Index Events
:imagesdir: images/watcher
[partintro]
--
You can watch for changes or anomalies in your data and perform the necessary
actions in response. For example, you might want to:
* Monitor social media as another way to detect failures in user-facing
automated systems like ATMs or ticketing systems. When the number of tweets
and posts in an area exceeds a threshold of significance, notify a service
technician.
* Monitor your infrastructure, tracking disk usage over time. Open a helpdesk
ticket when any servers are likely to run out of free space in the next few
days.
* Track network activity to detect malicious activity, and proactively change
firewall configuration to reject the malicious user.
* Monitor Elasticsearch, and send immediate notification to the system
administrator if nodes leave the cluster or query throughput exceeds an
expected range.
* Track application response times and if page-load time exceeds SLAs for more
than 5 minutes, open a helpdesk ticket. If SLAs are exceeded for an hour,
page the administrator on duty.
All of these use-cases share a few key properties:
* The relevant data or changes in data can be identified with a periodic
Elasticsearch query.
* The results of the query can be checked against a condition.
* One or more actions are taken if the condition is true -- an email is sent, a
3rd party system is notified, or the query results are stored.
[float]
=== How Watches Work
{xpack} provides an API for creating, managing and testing _watches_. A watch
describes a single alert and can contain multiple notification actions.
A watch is constructed from four simple building blocks:
Schedule:: A schedule for running a query and checking the condition.
Query:: The query to run as input to the condition. Watches
support the full Elasticsearch query language, including
aggregations.
Condition:: A condition that determines whether or not to execute the actions.
You can use simple conditions (always true), or use scripting for
more sophisticated scenarios.
Actions:: One or more actions, such as sending email, pushing data to
3rd party systems through a webhook, or indexing the results of
the query.
A full history of all watches is maintained in an Elasticsearch index. This
history keeps track of each time a watch is triggered and records the results
from the query, whether the condition was met, and what actions were taken.
--
include::getting-started.asciidoc[]
include::how-watcher-works.asciidoc[]
include::input.asciidoc[]
include::trigger.asciidoc[]
include::condition.asciidoc[]
include::actions.asciidoc[]
include::transform.asciidoc[]
include::java.asciidoc[]
include::managing-watches.asciidoc[]
include::example-watches.asciidoc[]

View File

@ -0,0 +1,28 @@
[[input]]
== Inputs
When a watch is triggered, its _input_ loads data into the execution
context. This payload is accessible during the subsequent watch execution
phases. For example, you can base a watch's condition on the data loaded by its
input.
{watcher} supports four input types:
* <<input-simple, `simple`>>: load static data into the execution context.
* <<input-search, `search`>>: load the results of a search into the execution
context.
* <<input-http, `http`>>: load the results of an HTTP request into the execution
context.
* <<input-chain, `chain`>>: use a series of inputs to load data into the
execution context.
NOTE: If you don't define an input for a watch, an empty payload is loaded
into the execution context.
include::input/simple.asciidoc[]
include::input/search.asciidoc[]
include::input/http.asciidoc[]
include::input/chain.asciidoc[]

View File

@ -0,0 +1,49 @@
[[input-chain]]
=== Chain Input
Use the `chain` input to load data from multiple sources into the watch
execution context when the watch is triggered. The inputs in a chain
are processed in order and the data loaded by an input can be accessed by the
subsequent inputs in the chain.
The `chain` input enables you perform actions based on data from multiple
sources. You can also use the data collected by one input to load data
from another source.
For example, the following chain input loads data from an HTTP server using the
path set by a `simple` input:
[source,js]
--------------------------------------------------
"input" : {
"chain" : {
"inputs" : [ <1>
{
"first" : {
"simple" : { "path" : "/_search" }
}
},
{
"second" : {
"http" : {
"request" : {
"host" : "localhost",
"port" : 9200,
"path" : "{{ctx.payload.first.path}}" <2>
}
}
}
}
]
}
}
--------------------------------------------------
<1> The inputs in a chain are specified as an array to guarantee the order in
which the inputs are processed. (JSON does not guarantee the order of
arbitrary objects.)
<2> Loads the `path` set by the `first` input.
==== Accessing Chained Input Data
To reference data loaded by a particular input, you use the input's name,
`ctx.payload.<input-name>.<value>`.

View File

@ -0,0 +1,247 @@
[[input-http]]
=== HTTP Input
Use the `http` input to submit a request to an HTTP endpoint and load the
response into the watch execution context when the watch is triggered. See
<<http-input-attributes, Input Attributes>> for all of the supported attributes.
With the `http` input, you can:
* Query external Elasticsearch clusters. The `http` input provides a way
to submit search requests to clusters other than the one {watcher} is running
on. This is useful when you're running a dedicated {watcher} cluster or if you
need to search clusters that are running different Elasticsearch versions.
* Query Elasticsearch APIs other than the search API. For example, you might want
to load data from the {ref}/cluster-nodes-stats.html[Nodes Stats],
{ref}/cluster-health.html[Cluster Health] or {ref}/cluster-state.html[Cluster
State] APIs.
* Query external web services. The `http` input enables you to load data from
any service that exposes an HTTP endpoint. This provides a bridge
between Elasticsearch clusters and other systems.
==== Querying External Elasticsearch Clusters
To query an external Elasticsearch cluster, you specify the cluster's
`host` and `port` attributes and the index's search endpoint as the `path`.
If you omit the search body, the request returns all documents in the specified
index:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"host" : "example.com",
"port" : 9200,
"path" : "/idx/_search"
}
}
}
--------------------------------------------------
You can use the full Elasticsearch {ref}/query-dsl.html[Query DSL] to perform
more sophisticated searches. For example, the following `http` input retrieves
all documents that contain `event` in the `category` field:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"host" : "host.domain",
"port" : 9200,
"path" : "/idx/_search",
"body" : "{\"query\" : { \"match\" : { \"category\" : \"event\"}}}"
}
}
}
--------------------------------------------------
==== Calling Elasticsearch APIs
To load the data from other Elasticsearch APIs, specify the API
endpoint as the `path` attribute. Use the `params` attribute to specify
query string parameters. For example, the following `http` input
calls the {ref}/cluster-stats.html[Cluster
Stats] API and enables the `human` attribute:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"host" : "host.domain",
"port" : "9200",
"path" : "/_cluster/stats",
"params" : {
"human" : "true" <1>
}
}
}
}
--------------------------------------------------
<1> Enabling this attribute returns the `bytes` values in the response in human
readable format.
[[input-http-auth-basic-example]]
==== Calling External Web Services
You can use `http` input to get data from any external web service. The `http`
input supports basic authentication. For example, the following input provides
a username and password to access `myservice`:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"host" : "host.domain",
"port" : "9200",
"path" : "/myservice",
"auth" : {
"basic" : {
"username" : "user",
"password" : "pass"
}
}
}
}
}
--------------------------------------------------
You can also pass in service-specific API keys and other information
through the `params` attribute. For example, the following `http`
input loads the current weather forecast for Amsterdam from the
http://openweathermap.org/appid[OpenWeatherMap] service:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"url" : "http://api.openweathermap.org/data/2.5/weather",
"params" : {
"lat" : "52.374031",
"lon" : "4.88969",
"appid" : "<your openweathermap appid>"
}
}
}
}
--------------------------------------------------
==== Using Templates
The `http` input supports templating. You can use <<templates, templates>> when
specifying the `path`, `body`, header values, and parameter values.
For example, the following snippet uses templates to specify what index to query
and restrict the results to documents added within the last five minutes:
[source,js]
--------------------------------------------------
"input" : {
"http" : {
"request" : {
"host" : "host.domain",
"port" : 9200,
"path" : "/{{ctx.watch_id}}/_search",
"body" : "{\"query\" : {\"range\": {\"@timestamp\" : {\"from\": \"{{ctx.trigger.triggered_time}}||-5m\",\"to\": \"{{ctx.trigger.triggered_time}}\"}}}}"
}
}
}
--------------------------------------------------
==== Accessing the HTTP Response
If the response body is formatted in JSON or YAML, it is parsed and loaded into
the execution context. If the response body is not formatted in JSON or YAML, it
is loaded into the payload's `_value` field.
Conditions, transforms, and actions access the response data through the
execution context. For example, if the response contains a `message`
object, you can use `ctx.payload.message` to access the message data.
In addition all the headers from the response can be accessed using the
`ctx.payload._headers` field as well as the HTTP status code of the response using
`ctx.payload._status_code`.
[[http-input-attributes]]
==== HTTP Input Attributes
[cols=",^,^,", options="header"]
|======
| Name | Required | Default | Description
| `request.scheme` | no | http | Url scheme. Valid values are: `http` or `https`.
| `request.host` | yes | - | The host to connect to.
| `request.port` | yes | - | The port the http service is listening on.
| `request.path` | no | - | The URL path. The path can be static text or contain `mustache`
<<templates, templates>>. URL query string parameters must be
specified via the `request.params` attribute.
| `request.method` | no | get | The HTTP method. Supported values are: `head`, `get`, `post`,
`put` and `delete`.
| `request.headers` | no | - | The HTTP request headers. The header values can be static text
or include `mustache` <<templates, templates>>.
| `request.params` | no | - | The URL query string parameters. The parameter values can be
static text or contain `mustache` <<templates, templates>>.
| `request.url` | no | - | Allows you to set `request.scheme`, `request.host`, `request.port`
and `request.params` add once by specifying a real URL, like
`https://www.example.org:1234/mypath?foo=bar`. May not be combined
with on of those four parameters. As those parameters are set,
specifying them individually might overwrite them.
| `request.auth` | no | - | Authentication related HTTP headers. Currently, only basic
authentication is supported.
| `request.proxy.host` | no | - | The proxy host to use when connecting to the host.
| `request.proxy.port` | no | - | The proxy port to use when connecting to the host.
| `request.connection_timeout` | no | 10s | The timeout for setting up the http connection. If the connection
could not be set up within this time, the input will timeout and
fail.
| `request.read_timeout` | no | 10s | The timeout for reading data from http connection. If no response
was received within this time, the input will timeout and fail.
| `request.body` | no | - | The HTTP request body. The body can be static text or include
`mustache` <<templates, templates>>.
| `extract` | no | - | A array of JSON keys to extract from the input response and
use as payload. In cases when an input generates a large
response this can be used to filter the relevant piece of
the response to be used as payload.
| `response_content_type` | no | json | The expected content type the response body will contain.
Supported values are `json`, `yaml` and `text`. If the
format is `text` the `extract` attribute cannot exist.
Note that this overrides the header that is returned in the
HTTP response. If this is set to `text` the body of the
response will be assigned and accessible to/via the `_value`
variable of the payload.
|======
You can reference the following variables in the execution context when
specifying the `path`, `params`, `headers` and `body` values:
[options="header"]
|======
| Name | Description
| `ctx.watch_id` | The id of the watch that is currently executing.
| `ctx.execution_time` | The time execution of this watch started.
| `ctx.trigger.triggered_time` | The time this watch was triggered.
| `ctx.trigger.scheduled_time` | The time this watch was supposed to be triggered.
| `ctx.metadata.*` | Any metadata associated with the watch.
|======

View File

@ -0,0 +1,203 @@
[[input-search]]
=== Search Input
Use the `search` input to load the results of an Elasticsearch search request
into the execution context when the watch is triggered. See
<<search-input-attributes, Search Input Attributes>> for all of the
supported attributes.
In the search input's `request` object, you specify:
* The indices you want to search
* The {ref}/search-request-search-type.html[search type]
* The search request body
The search request body supports the full Elasticsearch Query DSL--it's the
same as the body of an Elasticsearch `_search` request.
For example, the following input retrieves all `event`
documents from the `logs` index:
[source,js]
--------------------------------------------------
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"types" : [ "event" ],
"body" : {
"query" : { "match_all" : {}}
}
}
}
}
--------------------------------------------------
You can use date math and wildcards when specifying indices. For example,
the following input loads the latest VIXZ quote from today's daily quotes index:
[source,js]
--------------------------------------------------
{
"input" : {
"search" : {
"request" : {
"indices" : [ "<stock-quotes-{now/d}>" ],
"body" : {
"size" : 1,
"sort" : {
"timestamp" : { "order" : "desc"}
},
"query" : {
"term" : { "symbol" : "vix"}
}
}
}
}
}
}
--------------------------------------------------
==== Extracting Specific Fields
You can specify which fields in the search response you want to load into the
watch payload with the `extract` attribute. This is useful when a search
generates a large response and you are only interested in particular fields.
For example, the following input loads only the total number of hits into the
watch payload:
[source,js]
--------------------------------------------------
"input": {
"search": {
"request": {
"indices": [ ".watcher-history*" ]
},
"extract": [ "hits.total" ]
}
},
--------------------------------------------------
==== Using Templates
The `search` input supports {ref}/search-template.html[search templates]. For
example, the following snippet references the indexed template called
`my_template` and passes a value of 23 to fill in the template's `value`
parameter:
[source,js]
--------------------------------------------------
{
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"template" : {
"id" : "my_template",
"params" : {
"value" : 23
}
}
}
}
}
...
}
--------------------------------------------------
==== Applying Conditions
The `search` input is often used in conjunction with the <<condition-script,
`script`>> condition. For example, the following snippet adds a condition to
check if the search returned more than five hits:
[source,js]
--------------------------------------------------
{
"input" : {
"search" : {
"request" : {
"indices" : [ "logs" ],
"body" : {
"query" : { "match_all" : {} }
}
}
}
},
"condition" : {
"compare" : { "ctx.payload.hits.total" : { "gt" : 5 }}
}
...
}
--------------------------------------------------
==== Accessing the Search Results
Conditions, transforms, and actions can access the search results through the
watch execution context. For example:
* To load all of the search hits into an email body, use `ctx.payload.hits`.
* To reference the total number of hits, use `ctx.payload.hits.total`.
* To access a particular hit, use its zero-based array index. For example, to
get the third hit, use `ctx.payload.hits.hits.2`.
* To get a field value from a particular hit, use
`ctx.payload.hits.hits.<index>.fields.<fieldname>`. For example, to get the
message field from the first hit, use `ctx.payload.hits.hits.0.fields.message`.
[[search-input-attributes]]
==== Search Input Attributes
[cols=",^,,", options="header"]
|======
| Name |Required | Default | Description
| `request.search_type` | no | `query_then_fetch` | The {ref}/search-request-search-type.html#search-request-search-type[type]
of search request to perform. Valid values are: `dfs_query_and_fetch`,
`dfs_query_then_fetch`, `query_and_fetch`, and `query_then_fetch`. The
Elasticsearch default is `query_then_fetch`.
| `request.indices` | no | - | The indices to search. If omitted, all indices are searched, which is the
default behaviour in Elasticsearch.
| `request.types` | no | - | The document types to search for. If omitted, all document types are are
searched, which is the default behaviour in Elasticsearch.
| `request.body` | no | - | The body of the request. The {ref}/search-request-body.html[request body]
follows the same structure you normally send in the body of a REST `_search`
request. The body can be static text or include `mustache` <<templates, templates>>.
| `request.template` | no | - | The body of the search template. See <<templates, configure templates>>
for more information.
| `request.indices_options.expand_wildcards` | no | `open` | How to expand wildcards. Valid values are: `all`, `open`, `closed`, and `none`
See {ref}/multi-index.html#multi-index[`expand_wildcards`] for more information.
| `request.indices_options.ignore_unavailable` | no | `true` | Whether the search should ignore unavailable indices. See
{ref}/multi-index.html#multi-index[`ignore_unavailable`] for more information.
| `request.indices_options.allow_no_indices` | no | `true` | Whether to allow a search where a wildcard indices expression results in no
concrete indices. See {ref}/multi-index.html#multi-index[allow_no_indices]
for more information.
| `extract` | no | - | A array of JSON keys to extract from the search response and load as the payload.
When a search generates a large response, you can use `extract` to select the
relevant fields instead of loading the entire response.
| `timeout` | no | 30s | The timeout for waiting for the search api call to return. If no response is
returned within this time, the search input times out and fails. This setting
overrides the default search operations timeouts.
|======
You can reference the following variables in the execution context when
specifying the request `body`:
[options="header"]
|======
| Name | Description
| `ctx.watch_id` | The id of the watch that is currently executing.
| `ctx.execution_time` | The time execution of this watch started.
| `ctx.trigger.triggered_time` | The time this watch was triggered.
| `ctx.trigger.scheduled_time` | The time this watch was supposed to be triggered.
| `ctx.metadata.*` | Any metadata associated with the watch.
|======

View File

@ -0,0 +1,50 @@
[[input-simple]]
=== Simple Input
Use the `simple` input to load static data into the execution
context when the watch is triggered. This enables you to store the data
centrally and reference it with templates.
You can define the static data as a string (`str`), numeric value (`num`), or
an object (`obj`):
[source,js]
--------------------------------------------------
"input" : {
"simple" : {
"str" : "val1",
"num" : 23,
"obj" : {
"str" : "val2"
}
}
}
--------------------------------------------------
For example, the following watch uses the `simple` input to set the recipient
name for a daily reminder email:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"daily" : { "at" : "noon" }
}
},
"input" : {
"simple" : {
"name" : "John"
}
},
"actions" : {
"reminder_email" : {
"email" : {
"to" : "to@host.domain",
"subject" : "Reminder",
"body" : "Dear {{ctx.payload.name}}, by the time you read these lines, I'll be gone"
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,118 @@
[[api-java]]
== Java API
{xpack} 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`.
[float]
=== Installing XPackClient
You first need to make sure the +x-pack-transport-{version}+ JAR file is in the classpath.
You can extract this jar from the downloaded {xpack} bundle.
If you use Maven to manage dependencies, add the following to the `pom.xml`:
["source","xml",subs="attributes,callouts"]
--------------------------------------------------
<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>{version}</version>
</dependency>
...
</dependencies>
...
</project>
--------------------------------------------------
If you use Gradle, add the dependencies to `build.gradle`:
["source","groovy",subs="attributes,callouts"]
--------------------------------------------------------------
repositories {
/* ... Any other repositories ... */
// Add the Elasticsearch Maven Repository
maven {
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:{version}"
/* ... */
}
--------------------------------------------------------------
You can also download the https://artifacts.elastic.co/maven/org/elasticsearch/client/x-pack-transport/{version}/x-pack-transport-{version}.jar[X-Pack Transport JAR]
manually, directly from our Maven repository.
[float]
=== 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`:
[source,java]
--------------------------------------------------
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;
import org.elasticsearch.xpack.XPackClient;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.watcher.client.WatcherClient;
...
TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
.put("cluster.name", "myClusterName")
...
.build())
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
XPackClient xpackClient = new XPackClient(client);
WatcherClient watcherClient = xpackClient.watcher();
--------------------------------------------------
include::java/put-watch.asciidoc[]
include::java/get-watch.asciidoc[]
include::java/delete-watch.asciidoc[]
include::java/execute-watch.asciidoc[]
include::java/ack-watch.asciidoc[]
include::java/activate-watch.asciidoc[]
include::java/deactivate-watch.asciidoc[]
include::java/stats.asciidoc[]
include::java/service.asciidoc[]

View File

@ -0,0 +1,60 @@
[float]
[[api-java-ack-watch]]
=== Ack Watch API
<<actions-ack-throttle, 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 <<api-java-get-watch, Get Watch API>> response:
[source,java]
--------------------------------------------------
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`:
[source,java]
--------------------------------------------------
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:
[source,java]
--------------------------------------------------
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:
[source,java]
--------------------------------------------------
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch")
.setActionIds("action1", "action2")
.get();
--------------------------------------------------
To acknowledge all actions of a watch, specify only the watch ID:
[source,java]
--------------------------------------------------
AckWatchResponse ackResponse = watcherClient.prepareAckWatch("my-watch").get();
--------------------------------------------------

View File

@ -0,0 +1,25 @@
[float]
[[api-java-activate-watch]]
=== Activate Watch API
A watch can be either <<watch-active-state, 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 <<api-java-get-watch, Get Watch API>>:
[source,java]
--------------------------------------------------
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get();
boolean active = getWatchResponse.getStatus().state().isActive();
--------------------------------------------------
The following snippet shows how you can activate a watch:
[source,java]
--------------------------------------------------
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.

View File

@ -0,0 +1,25 @@
[float]
[[api-java-deactivate-watch]]
=== Deactivate Watch API
A watch can be either <<watch-active-state, 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 <<api-java-get-watch, Get Watch API>>:
[source,java]
--------------------------------------------------
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get();
boolean active = getWatchResponse.getStatus().state().isActive();
--------------------------------------------------
The following snippet shows how you can deactivate a watch:
[source,java]
--------------------------------------------------
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.

View File

@ -0,0 +1,22 @@
[float]
[[api-java-delete-watch]]
=== 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.
IMPORTANT: 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. I {security} is 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:
[source,java]
--------------------------------------------------
DeleteWatchResponse deleteWatchResponse = watcherClient.prepareDeleteWatch("my-watch").get();
--------------------------------------------------

View File

@ -0,0 +1,52 @@
[float]
[[api-java-execute-watch]]
=== 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`
[source,java]
--------------------------------------------------
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:
TIP: The `XContentSource` class provides convenient methods to explore the
source
[source,java]
--------------------------------------------------
XContentSource source = executeWatchResponse.getRecordSource();
String actionId = source.getValue("result.actions.0.id");
--------------------------------------------------

View File

@ -0,0 +1,33 @@
[float]
[[api-java-get-watch]]
=== Get Watch API
This API retrieves a watch by its id.
The following example gets a watch with `my-watch` id:
[source,java]
--------------------------------------------------
GetWatchResponse getWatchResponse = watcherClient.prepareGetWatch("my-watch").get();
--------------------------------------------------
You can access the watch definition by accessing the source of the response:
[source,java]
--------------------------------------------------
XContentSource source = getWatchResponse.getSource();
--------------------------------------------------
The `XContentSource` provides you methods to explore the source:
[source,java]
--------------------------------------------------
Map<String, Object> map = source.getAsMap();
--------------------------------------------------
Or get a specific value associated with a known key:
[source,java]
--------------------------------------------------
String host = source.getValue("input.http.request.host");
--------------------------------------------------

View File

@ -0,0 +1,91 @@
[float]
[[api-java-put-watch]]
=== 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).
IMPORTANT: 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 {security} is 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.
[source,java]
--------------------------------------------------
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 > 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:
[source,java]
--------------------------------------------------
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", CompareCondition.Op.GT, 1L))
.addAction("email_someone", emailAction(EmailTemplate.builder()
.to("someone@domain.host.com")
.subject("404 recently encountered"))))
.get();
--------------------------------------------------
* Use `TriggerBuilders` and `Schedules` 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

View File

@ -0,0 +1,25 @@
[float]
[[api-java-service]]
=== Service API
The {watcher} `service` API allows the control the lifecycle of the {watcher}
service. The following example starts the watcher service:
[source,java]
--------------------------------------------------
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().start().get();
--------------------------------------------------
The following example stops the watcher service:
[source,java]
--------------------------------------------------
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().stop().get();
--------------------------------------------------
The following example restarts the watcher service:
[source,java]
--------------------------------------------------
WatcherServiceResponse watcherServiceResponse = watcherClient.prepareWatchService().restart().get();
--------------------------------------------------

View File

@ -0,0 +1,32 @@
[float]
[[api-java-stats]]
=== 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 :
[source,java]
--------------------------------------------------
WatcherStatsResponse watcherStatsResponse = watcherClient.prepareWatcherStats().get();
--------------------------------------------------
A successful call returns a response structure that can be accessed as shown:
[source,java]
--------------------------------------------------
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();
--------------------------------------------------

View File

@ -0,0 +1,11 @@
[[watcher-limitations]]
== Watcher Limitations
[float]
=== Watches Are Not Updated When File Based Scripts Change
When you refer to a file script in a watch, the watch itself is not updated
if you change the script on the filesystem.
Currently, the only way to reload a file script in a watch is to delete
the watch and recreate it.

View File

@ -0,0 +1,36 @@
[[managing-watches]]
== Managing Watches
{watcher} provides as set of APIs you can use to manage your watches:
* Use the <<watcher-api-put-watch>> to add or update watches
* Use the <<watcher-api-get-watch>> to retrieve watches
* Use the <<watcher-api-delete-watch>> to delete watches
* Use the <<watcher-api-activate-watch>> to activate watches
* Use the <<watcher-api-deactivate-watch>> to deactivate watches
* Use the <<watcher-api-ack-watch>> to acknowledge watches
[float]
[[listing-watches]]
=== Listing Watches
Currently there is not dedicated API for listing the stored watches. However,
since {watcher} stores its watches in the `.watches` index, you can list them
by executing a search on this index.
IMPORTANT: You can only perform read actions on the `.watches` index. You must
use the {watcher} APIs to create, update, and delete watches. If
{security} is enabled, we recommend you only grant users `read`
privileges on the `.watches` index.
For example, the following returns the first 100 watches:
[source,js]
--------------------------------------------------
GET .watches/_search
{
"size" : 100
}
--------------------------------------------------
// CONSOLE
// TEST[setup:my_active_watch]

View File

@ -0,0 +1,312 @@
[[watcher-release-notes]]
== Watcher Release Notes (Pre-5.0)
[float]
[[watcher-change-list]]
=== Change List
[float]
==== 2.4.2
November 22, 2016
.Bug Fixes
* Deleting a watch now is independent from its current execution state in
order to prevent failed deletions with watches having small intervals
* Chain input: Parsing now throws an exception if a data structure is added, that cannot keep its order
[float]
==== 2.4.1
September 28, 2016
.Bug Fixes
* Fixed a serialization error that resulted in the watch history not being
written when a proxy is specified in a watch.
* Triggered watches are now correctly deleted from the `.triggered-watches`
index if they are rejected due to a full thread pool.
* Deleting or closing the `.watches` index now correctly cleans up the
in-memory watch store so the watches are no longer executed.
* If the HTTP request for an attachment fails, the error message is included
in the watch history.
* Fixed a possible exception when chained inputs don't execute successfully.
.Enhancements
* Hostname verification can be disabled for Watcher
HTTP actions.
* Running watches can be updated and deleted.
[float]
==== 2.4.0
August 31, 2016
.Enhancements
* The HTTP headers of a response are now part of the payload and can be accessed via `ctx.payload._headers`
[float]
==== 2.3.5
August 3, 2016
.Bug Fixes
* The watch history was not written, if one of the chained inputs resulted in a failure as well as an input containing a field name with dots
* Status of an acked watch, whose condition evaluates to false again is now properly persisted and not lost in case of a master node switch
* Fixed the watch history template so payloads and request bodies are handled
correctly. To update an existing installation, delete the existing watch history
template by running `DELETE /_template/watch_history` and the correct template
will be autocreated. To verify the template is recreated, call `GET
/_template/watch_history`. Note that this just updates the template, so you
need to wait one day for this update to take effect when a new history index is
created.
* The `watcher.http.proxy.port` setting for global proxy configuration was not applied correctly.
[float]
==== 2.3.4
July 7, 2016
.Bug Fixes
* Putting a new watch with state `active=false` now stores that state correctly
on a multi node cluster.
* Fixed the watch history template so nested request bodies are handled
correctly. To update an existing installation, delete the existing watch history
template by running `DELETE /_template/watch_history` and the correct template
will be autocreated. To verify the template is recreated, call `GET
/_template/watch_history`. Note that this just updates the template, so you
need to wait one day for this update to take effect when a new history index is
created.
* The HTML sanitizer now supports border and cellpadding attributes on table
elements and the colspan and rowspan attributes on <td> and <tr> elements.
* Fixed the Watcher/Marvel examples in the documentation.
[float]
==== 2.3.3
May 18, 2016
.Enhancements
* Adds support for Elasticsearch 2.3.3
[float]
==== 2.3.2
April 26, 2016
.Bug Fixes
* All SMTP connection timeouts are now set to two minutes by default to prevent
a watch from getting stuck.
* HTTP headers from responses that contained dots led to exceptions when the
HTTP response was stored in the watch history. All dots in any header names
are now replaced with underscores. For example, a header called `foo.bar`
becomes `foo_bar`
* Hipchat action: Fall back to the default Hipchat color and format if they
are not specified at the account level or within the action itself, instead
of failing.
[float]
==== 2.3.1
April 4, 2016
.Enhancements
* Adds support for Elasticsearch 2.3.1
[float]
==== 2.3.0
March 30, 2016
.Bug fixes
* The http client does not do any URL escaping by itself anymore, preventing
potential wrong double escapes.
.Enhancement
* Support `url` in http requests as a shortcut for `path`, `scheme`, `port`, `params`
* Support `ignore_condition` and `record_execution` as parameters in the
<<watcher-api-execute-watch, Execute Watch API>>
.New Features
* Added <<actions-pagerduty, PagerDuty action>>
* Added support for adding <<configuring-email-attachments, attachments to emails>>
via HTTP requests and superceding and deprecating the usage of `attach_data`
in order to use this feature
[float]
==== 2.2.1
March 10, 2016
.Bug Fixes
* The `croneval` CLI tool sets the correct environment to run
[float]
==== 2.2.0
February 2, 2016
.Enhancements
* Adds support for Elasticsearch 2.2.0.
[float]
==== 2.1.2
February 2, 2016
.Enhancements
* Adds support for Elasticssearch 2.1.2
[float]
==== 2.1.1
December 17, 2015
.Bug Fixes
* Fixed an issue that prevented sending of emails
[float]
==== 2.1.0
November 24, 2015
.New Features
* Adds support for <<input-chain, chaining several inputs>>
.Enhancements
* Adds support for Elasticsearch 2.1.0.
* Adds support for configuring a proxy in the webhook action, http input and
configuring a default proxy (which is also used by the slack action), using the
`watcher.http.proxy.host` and `watcher.http.proxy.port` settings.
.Bug Fixes
* Fixed an issue where the scheduler may get stuck during Watcher startup. This
caused no watches to ever fire.
* Fixed an issue where under specific conditions Watcher would not start if there
are not finished watch executions from the previous time that watcher was
running and those watch execution are unable the execute during the current
start process.
[float]
==== 2.0.1
November 24, 2015
.Enhancement
* Adds support for Elasticsearch 2.0.1.
.Bug fixes
* Fixed an issue where under specific conditions Watcher would not start if
there are not finished watch executions from the previous time that watcher
was running and those watch execution are unable the execute during the current
start process.
[float]
==== 2.0.0
October 28, 2015
.Breaking Changes
* The dynamic index names support has been removed and Elasticsearch's date math
index names support should be used instead. The only difference between Watcher's
dynamic index names support and Elasticsearch's date math index names support is
how timezones are expressed. In Watcher this is done via node settings, in
Elasticsearch the timezone is part of the date math index names support. Only
if you're using dynamic index names with timezones in Watcher then you need to
upgrade your watches after the upgrade, otherwise your watches will work as
they did before the upgrade. For example if `watcher.dynamic_indices.time_zone`
setting was set to `+01:00` and a watch has the following index name
`<logstash-{now/d}>` then after the upgrade you need to update this watch to
use the following index name `<logstash-{now/d{YYYY.MM.dd|+01:00}}>`.
.New Features
* Added new <<actions-hipchat, HipChat Action>>
* Added new <<actions-slack, Slack Action>>
* Watches now have an <<watch-active-state, active state>>. In addition, a new
API was added to <<watcher-api-activate-watch, activate>>/<<watcher-api-deactivate-watch, deactivate>>
registered watches.
* Added new <<condition-array-compare, array_compare>>, that can compare an array
of values in the <<watch-execution-context, Watch Execution Context Model>>
to a given value.
.Enhancements
* Watcher continuously checks if the index templates for `.watches`,
`.triggered_watches` and `.watch_history-*` exist. Whereas before the existence
of these index templates was only checked at Watcher startup time. The absence
of these index templates leads to watcher data being indexed incorrectly, which
then can cause Watcher to behave incorrectly.
* If Watcher was stopped via the stop Watcher api and after that a master
election took place then Watcher would then unexpectedly start.
* During Watcher start up only wait for the shards of the `.watches` and
`.triggered_watches` indices to be available. Before Watcher also waited for
the shards of the `.watch_history-*` indices, which wasn't needed. This
improved time it takes for Watcher to startup.
* If `action.auto_create_index` setting has been configured then Watcher will
check if the setting is too restrictive. If the `action.auto_create_index` is
too restrictive then Watcher will fail during startup with a descriptive error
message.
.Bug Fixes
* If Watcher was installed with Security then the Watcher index templates couldn't
be stored and could lead to Watcher behaving incorrectly. This was caused by
Watcher not detecting correctly if Security was installed.
* Update `croneval` command line utility to properly handle whitespaces in the
elasticsearch home path.
* Fixed an issue where the scheduler may get stuck during Watcher startup. This
caused no watches to ever fire.
* Fixed url encoding issue in http input and webhook output. The url params were
url encoded twice.
[float]
==== 1.0.1
July 29, 2015
.Enhancements
* Dynamic index names now support specifying a time zone to be used when
computing the names of the indices. The default is UTC. Previously, the
computation was fixed to always use UTC when computing the names of the
indices.
.Bug Fixes
* Fixed a compatibility issue with Elasticsearch 1.6.1 and 1.7.2, which were
released earlier today.
[float]
==== 1.0.0
June 25, 2015
.Enhancements
* Added execution time aware dynamic index names support to `index`
action, `search` input, and `search` transform.
* You must now explicitly specify the unit when configuring any time value.
(Numeric-only values are no longer supported.)
* Cleaned up the <<watcher-api-get-watch, Get Watch API>> response.
* Cleaned up the <<watcher-api-stats, Stats API>> response.
[float]
==== 1.0.0-rc1
June 19, 2015
.New Features
* Added <<watcher-api-execute-inline-watch, inline watch>> support to the Execute API
.Enhancements
* Added execution context <<watch-execution-context, variables>> support.
* Email html body sanitization is now <<email-html-sanitization, configurable>>.
* It is now possible to configure timeouts for http requests in
<<http-input-attributes, HTTP input>> and <<webhook-action-attributes, webhook actions>>.
[float]
==== 1.0.0-Beta2
June 10, 2015
.New Features
* <<actions-ack-throttle, Acking and Throttling>> are now applied at the action
level rather than the watch level.
* Added support for <<anatomy-actions-index-multi-doc-support, multi-doc>>
indexing to the index action.
* Added a queued watches metric that's accessible via the <<watcher-api-stats, Stats API>>.
* Added a currently-executing watches metric that's accessible via the
<<watcher-api-stats, Stats API>>.
.Enhancements
* The <<condition-compare, compare condition>> result now includes the value of
each field that was referenced in the comparison.
* The <<watcher-api-execute-watch, Execute API>> now supports a default trigger
event (**breaking change**).
* The `watch_record` document structure in the `.watch_history-*` indices has
changed significantly (**breaking change**).
* A new internal index was introduced - `.triggered_watches`
* Added support for headers in the <<actions-webhook, Webhook Action>> result
and the <<input-http, HTTP Input>> result.
* Add plain text response body support for the <<input-http, HTTP Input>>.
.Bug Fixes
* Disallow negative time value settings for <<actions-ack-throttle, `throttle_period`>>
* Added support for separate keystore and truststore in <<actions-webhook, Webhook Action>>
and <<input-http, HTTP Input>>.

View File

@ -0,0 +1,62 @@
[[transform]]
== Transforms
A _Transform_ processes and changes the payload in the watch execution context
to prepare it for the watch actions. {watcher} supports three types of
transforms: <<transform-search, `search`>>,
<<transform-script, `script`>> and <<transform-chain, `chain`>>.
NOTE: Transforms are optional. When none are defined, the actions have access to
the payload as loaded by the watch input.
You can define transforms in two places:
* As a top level construct in the watch definition. In this case, the payload is
transformed before any of the watch actions are executed.
* As part of the definition of an action. In this case, the payload is
transformed before that action is executed. The transformation is only applied
to the payload for that specific action.
If all actions require the same view of the payload, define a transform as part
of the watch definition. If each action requires a different view of the payload,
define different transforms as part of the action definitions so each action has
the payload prepared by its own dedicated transform.
The following example defines two transforms, one at the watch level and one as
part of the definition of the `my_webhook` action.
[source,js]
--------------------------------------------------
{
"trigger" : { ...}
"input" : { ... },
"condition" : { ... },
"transform" : { <1>
"search" : {
"body" : { "query" : { "match_all" : {} } }
}
},
"actions" : {
"my_webhook": {
"transform" : { <2>
"script" : "return ctx.payload.hits"
},
"webhook" : {
"host" : "host.domain",
"port" : 8089,
"path" : "/notify/{{ctx.watch_id}}"
}
}
]
}
--------------------------------------------------
<1> A watch level `transform`
<2> An action level `transform`
include::transform/search.asciidoc[]
include::transform/script.asciidoc[]
include::transform/chain.asciidoc[]

View File

@ -0,0 +1,45 @@
[[transform-chain]]
=== Chain Transform
A <<transform, Transform>> that executes an ordered list of configured transforms
in a chain, where the output of one transform serves as the input of the next
transform in the chain. The payload that is accepted by this transform serves as
the input of the first transform in the chain and the output of the last transform
in the chain is the output of the `chain` transform as a whole.
You can use chain transforms to build more complex transforms out of the other
available transforms. For example, you can combine a <<transform-search, `search`>>
transform and a <<transform-script, `script`>> transform, as shown in the
following snippet:
[source,js]
--------------------------------------------------
"transform" : {
"chain" : [ <1>
{
"search" : { <2>
"indices" : [ "logstash-*" ],
"body" : {
"size" : 0,
"query" : {
"match" : { "priority" : "error" }
}
}
}
},
{
"script" : "return [ error_count : ctx.payload.hits.total ]" <3>
}
]
}
--------------------------------------------------
<1> The `chain` transform definition
<2> The first transform in the chain (in this case, a `search` transform)
<3> The second and final transform in the chain (in this case, a `script`
transform)
This example executes a `count` search on the cluster to look for `error` events.
The search results are then passed to the second `script` transform. The `script`
transform extracts the total hit count and assigns it to the `error_count` field
in a newly-generated payload. This new payload is the output of the `chain`
transform and replaces the payload in the watch execution context.

View File

@ -0,0 +1,68 @@
[[transform-script]]
=== Script Transform
A <<transform, Transform>> that executes a script on the current payload in the
watch execution context and replaces it with a newly generated one. The following
snippet shows how a simple script transform can be defined on the watch level:
TIP: The `script` transform is often useful when used in combination with the
<<transform-search, `search`>> transform, where the script can extract only
the significant data from a search result, and by that, keep the payload
minimal. This can be achieved with the <<transform-chain, `chain`>>
transform.
[source,js]
--------------------------------------------------
{
"transform" : {
"script" : "return [ 'time' : ctx.trigger.scheduled_time ]" <1>
}
}
--------------------------------------------------
<1> A simple `painless` script that creates a new payload with a single `time`
field holding the scheduled time.
NOTE: The executed script may either return a valid model that is the equivalent
of a Java(TM) Map or a JSON object (you will need to consult the
documentation of the specific scripting language to find out what this
construct is). Any other value that is returned will be assigned and
accessible to/via the `_value` variable.
The `script` attribute may hold a string value in which case it will be treated
as an inline script and the default elasticsearch script languages will be assumed
(as described in {ref}/modules-scripting.html#modules-scripting[here]). You can
use the other scripting languages supported by Elasticsearch. For this, you need
to set the `script` field to an object describing the script and its language.
The following table lists the possible settings that can be configured:
[[transform-script-settings]]
.Script Transform Settings
[options="header,footer"]
|======
| Name |Required | Default | Description
| `inline` | yes* | - | When using an inline script, this field holds
the script itself.
| `file` | yes* | - | When referring to a script file, this field
holds the name of the file.
| `id` | yes* | - | When referring to a stored script, this
field holds the id of the script.
| `lang` | no | `painless` | The script language
| `params` | no | - | Additional parameters/variables that are
accessible by the script
4+d| * When using the object notation, only one of `inline`, `file` or `id`
fields must be defined
|======
When using the object notation of the script, one (and only one) of `inline`,
`file` or `id` fields must be defined
NOTE: In addition to the provided `params`, the scripts also have access to the
<<watch-execution-context, Standard Watch Execution Context Parameters>>.

View File

@ -0,0 +1,175 @@
[[transform-search]]
=== Search Transform
A <<transform, Transform>> that executes a search on the cluster and replaces
the current payload in the watch execution context with the returned search
response. The following snippet shows how a simple search transform can be
defined on the watch level:
[source,js]
--------------------------------------------------
{
"transform" : {
"search" : {
"request" : {
"body" : { "query" : { "match_all" : {} }}
}
}
}
}
--------------------------------------------------
Like every other search based construct, one can make use of the full search
API supported by Elasticsearch. For example, the following search transform
execute a search over all events indices, matching events with `error` priority:
[source,js]
--------------------------------------------------
{
"transform" : {
"search" : {
"request" : {
"indices" : [ "events-*" ],
"body" : {
"size" : 0,
"query" : {
"match" : { "priority" : "error"}
}
}
}
}
}
}
--------------------------------------------------
The following table lists all available settings for the search transform:
[[transform-search-settings]]
.Search Transform Settings
[cols=",^,,", options="header"]
|======
| Name |Required | Default | Description
| `request.search_type` | no | query_then_fetch | The search {ref}/search-request-search-type.html[type].
| `request.indices` | no | all indices | One or more indices to search on.
| `request.types` | no | all types | One or more document types to search on (may be a
comma-delimited string or an array of document types
names)
| `request.body` | no | `match_all` query | The body of the request. The
{ref}/search-request-body.html[request body] follows
the same structure you normally send in the body of
a REST `_search` request. The body can be static text
or include `mustache` <<templates, templates>>.
| `request.indices_options.expand_wildcards` | no | `open` | Determines how to expand indices wildcards. Can be one
of `open`, `closed`, `none` or `all`
(see {ref}/multi-index.html[multi-index support])
| `request.indices_options.ignore_unavailable` | no | `true` | A boolean value that determines whether the search
should leniently ignore unavailable indices
(see {ref}/multi-index.html[multi-index support])
| `request.indices_options.allow_no_indices` | no | `true` | A boolean value that determines whether the search
should leniently return no results when no indices
are resolved (see {ref}/multi-index.html[multi-index support])
| `request.template` | no | - | The body of the search template. See
<<templates, configure templates>> for more information.
| `timeout` | no | 30s | The timeout for waiting for the search api call to
return. If no response is returned within this time,
the search transform times out and fails. This setting
overrides the default timeouts.
|======
[[transform-search-template]]
==== Template Support
The search transform support mustache <<templates, templates>>. This can either
be as part of the body definition, or alternatively, point to an existing
template (either defined in a file or {ref}/search-template.html#pre-registered-templates[registered]
as a script in Elasticsearch).
For example, the following snippet shows a search that refers to the scheduled
time of the watch:
[source,js]
--------------------------------------------------
{
"transform" : {
"search" : {
"request" : {
"indices" : [ "logstash-*" ],
"types" : [ "event" ],
"body" : {
"size" : 0,
"query" : {
"bool" : {
"must" : {
"match" : { "priority" : "error"}
},
"filter" : [
{
"range" : {
"@timestamp" : {
"from" : "{{ctx.trigger.scheduled_time}}||-30s",
"to" : "{{ctx.trigger.triggered_time}}"
}
}
}
]
}
}
}
}
}
}
}
--------------------------------------------------
The model of the template is a union between the provided `template.params`
settings and the <<watch-execution-context, standard watch execution context model>>.
The following is an example of using templates that refer to provided parameters:
[source,js]
--------------------------------------------------
{
"transform" : {
"search" : {
"request" : {
"indices" : [ "logstash-*" ],
"types" : [ "event" ],
"template" : {
"inline" : {
"size" : 0,
"query" : {
"bool" : {
"must" : {
"match" : { "priority" : "{{priority}}"}
},
"filter" : [
{
"range" : {
"@timestamp" : {
"from" : "{{ctx.trigger.scheduled_time}}||-30s",
"to" : "{{ctx.trigger.triggered_time}}"
}
}
}
]
}
},
"params" : {
"priority" : "error"
}
}
}
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,12 @@
[[trigger]]
== Triggers
Every watch must have a `trigger` that defines when the watch execution process
should start. When you create a watch, its trigger is registered with the
appropriate _Trigger Engine_. The trigger engine is responsible for evaluating
the trigger and triggering the watch when needed.
{watcher} is designed to support different types of triggers, but only time-based
<<trigger-schedule, `schedule`>> triggers are currently available.
include::trigger/schedule.asciidoc[]

View File

@ -0,0 +1,41 @@
[[trigger-schedule]]
=== Schedule Trigger
Schedule <<trigger, triggers>> define when the watch execution should start based
on date and time. All times are specified in UTC time.
{watcher} uses the system clock to determine the current time. To ensure schedules
are triggered when expected, you should synchronize the clocks of all nodes in the
cluster using a time service such as http://www.ntp.org/[NTP].
Keep in mind that the throttle period can affect when a watch is actually executed.
The default throttle period is five seconds (5000 ms). If you configure a schedule
that's more frequent than the throttle period, the throttle period overrides the
schedule. For example, if you set the throttle period to one minute (60000 ms)
and set the schedule to every 10 seconds, the watch is executed no more than
once per minute. For more information about throttling, see
<<actions-ack-throttle, Acknowledgement and Throttling>>.
{watcher} provides several types of schedule triggers:
* <<schedule-hourly, `hourly`>>
* <<schedule-daily, `daily`>>
* <<schedule-weekly, `weekly`>>
* <<schedule-monthly, `monthly`>>
* <<schedule-yearly, `yearly`>>
* <<schedule-cron, `cron`>>
* <<schedule-interval, `interval`>>
include::schedule/hourly.asciidoc[]
include::schedule/daily.asciidoc[]
include::schedule/weekly.asciidoc[]
include::schedule/monthly.asciidoc[]
include::schedule/yearly.asciidoc[]
include::schedule/cron.asciidoc[]
include::schedule/interval.asciidoc[]

View File

@ -0,0 +1,234 @@
[[schedule-cron]]
==== `cron` Schedule
A <<trigger-schedule, `schedule`>> trigger that enables you to use a
https://en.wikipedia.org/wiki/Cron[cron] style expression to specify when you
want the scheduler to start the watch execution. {watcher} uses the cron parser
from the http://www.quartz-scheduler.org[Quartz Job Scheduler]. For more
information about writing Quartz cron expressions, see the
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-06.html[Quartz CronTrigger Tutorial].
WARNING: While `cron` triggers are super powerful, we recommend using one of
the other schedule types if you can, as they are much more
straightforward to configure. If you use `cron`, construct your `cron`
expressions with care to be sure you are actually setting the schedule
you want. You can use the <<croneval, `croneval`>> tool to validate
your cron expressions and see what the resulting trigger times will be.
===== Cron Expressions
A cron expression is a string of the following form:
[source,txt]
------------------------------
<seconds> <minutes> <hours> <day_of_month> <month> <day_of_week> [year]
------------------------------
All elements are required except for `year`. <<schedule-cron-elements>> shows
the valid values for each element in a cron expression.
[[schedule-cron-elements]]
.Cron Expression Elements
[cols=",^,,", options="header"]
|======
| Name | Required | Valid Values | Valid Special Characters
| `seconds` | yes | `0`-`59` | `,` `-` `*` `/`
| `minutes` | yes | `0`-`59` | `,` `-` `*` `/`
| `hours` | yes | `0`-`23` | `,` `-` `*` `/`
| `day_of_month` | yes | `1`-`31` | `,` `-` `*` `/` `?` `L` `W`
| `month` | yes | `1`-`12` or `JAN`-`DEC` | `,` `-` `*` `/`
| `day_of_week` | yes | `1`-`7` or `SUN`-`SAT` | `,` `-` `*` `/` `?` `L` `#`
| `year` | no | empty or `1970`-`2099 | `,` `-` `*` `/`
|======
The special characters you can use in a cron expression are described in
<<schedule-cron-special-characters>>. The names of months and days of the week
are not case sensitive. For example, `MON` and `mon` are equivalent.
NOTE: Currently, you must specify `?` for either the `day_of_week` or
`day_of_month`. Explicitly specifying both values is not supported.
[[schedule-cron-special-characters]]
.Cron Special Characters
[options="header"]
|======
| Special Character | Description
| * | All values. Selects every possible value for a field. For
example, `*` in the `hours` field means "every hour".
| ? | No specific value. Use when you don't care what the value
is. For example, if you want the schedule to trigger on a
particular day of the month, but don't care what day of
the week that happens to be, you can specify `?` in the
`day_of_week` field.
| - | A range of values (inclusive). Use to separate a minimum
and maximum value. For example, if you want the schedule
to trigger every hour between 9:00 AM and 5:00 PM, you
could specify `9-17` in the `hours` field.
| , | Multiple values. Use to separate multiple values for a
field. For example, if you want the schedule to trigger
every Tuesday and Thursday, you could specify `TUE,THU`
in the `day_of_week` field.
| / | Increment. Use to separate values when specifying a time
increment. The first value represents the starting point,
and the second value represents the interval. For example,
if you want the schedule to trigger every 20 minutes
starting at the top of the hour, you could specify `0/20`
in the `minutes` field. Similarly, specifying `1/5` in
`day_of_month` field will trigger every 5 days starting on
the first day of the month.
| L | Last. Use in the `day_of_month` field to mean the last day
of the month--day 31 for January, day 28 for February in
non-leap years, day 30 for April, and so on. Use alone in
the `day_of_week` field in place of `7` or `SAT`, or after
a particular day of the week to select the last day of that
type in the month. For example `6L` means the last Friday
of the month. You can specify `LW` in the `day_of_month`
field to specify the last weekday of the month. Avoid using
the `L` option when specifying lists or ranges of values,
as the results likely won't be what you expect.
| W | Weekday. Use to specify the weekday (Monday-Friday) nearest
the given day. As an example, if you specify `15W` in the
`day_of_month` field and the 15th is a Saturday, the
schedule will trigger on the 14th. If the 15th is a Sunday,
the schedule will trigger on Monday the 16th. If the 15th
is a Tuesday, the schedule will trigger on Tuesday the 15th.
However if you specify `1W` as the value for `day_of_month`,
and the 1st is a Saturday, the schedule will trigger on
Monday the 3rd--it won't jump over the month boundary. You
can specify `LW` in the `day_of_month` field to specify the
last weekday of the month. You can only use the `W` option
when the `day_of_month` is a single day--it is not valid
when specifying a range or list of days.
| # | Nth XXX day in a month. Use in the `day_of_week` field to
specify the nth XXX day of the month. For example, if you
specify `6#1`, the schedule will trigger on the first
Friday of the month. Note that if you specify `3#5` and
there are not 5 Tuesdays in a particular month, the
schedule won't trigger that month.
|======
.Setting Daily Triggers
[options="header"]
|======
| Cron Expression | Description
| `0 5 9 * * ?` | Trigger at 9:05 AM every day.
| `0 5 9 * * ? 2015` | Trigger at 9:05 AM every day during the year 2015.
|======
.Restricting Triggers to a Range of Days or Times
[options="header"]
|======
| Cron Expression | Description
| `0 5 9 ? * MON-FRI` | Trigger at 9:05 AM Monday through Friday.
| `0 0-5 9 * * ?` | Trigger every minute starting at 9:00 AM and ending
at 9:05 AM every day.
|======
.Setting Interval Triggers
[options="header"]
|======
| Cron Expression | Description
| `0 0/15 9 * * ?` | Trigger every 15 minutes starting at 9:00 AM and ending
at 9:45 AM every day.
| `0 5 9 1/3 * ?` | Trigger at 9:05 AM every 3 days every month, starting
on the first day of the month.
|======
.Setting Schedules that Trigger on a Particular Day
[options="header"]
|======
| Cron Expression | Description
| `0 1 4 1 4 ?` | Trigger every April 1st at 4:01 AM.
| `0 0,30 9 ? 4 WED` | Trigger at 9:00 AM and at 9:30 AM every Wednesday in
the month of April.
| `0 5 9 15 * ?` | Trigger at 9:05 AM on the 15th day of every month.
| `0 5 9 15W * ?` | Trigger at 9:05 AM on the nearest weekday to the 15th
of every month.
| `0 5 9 ? * 6#1` | Trigger at 9:05 AM on the first Friday of every month.
|======
.Setting Triggers Using Last
[options="header"]
|======
| Cron Expression | Description
| `0 5 9 L * ?` | Trigger at 9:05 AM on the last day of every month.
| `0 5 9 ? * 2L` | Trigger at 9:05 AM on the last Monday of every month
| `0 5 9 LW * ?` | Trigger at 9:05 AM on the last weekday of every month.
|======
===== Configuring a Cron Schedule
To configure a `cron` schedule, you simply specify the cron expression as a
string value. For example, the following snippet configures a `cron` schedule
that triggers every day at noon:
[source,js]
--------------------------------------------------
{
...
"trigger" : {
"schedule" : {
"cron" : "0 0 12 * * ?"
}
}
...
}
--------------------------------------------------
===== Configuring a Multiple Times Cron Schedule
To configure a `cron` schedule that triggers multiple times, you can
specify an array of cron expressions. For example, the following `cron`
schedule triggers every even minute during weekdays and every uneven
minute during the weekend:
[source,js]
--------------------------------------------------
{
...
"trigger" : {
"schedule" : {
"cron" : [
"0 0/2 * ? * MON-FRI"",
"0 1-59/2 * ? * SAT-SUN"
]
}
}
...
}
--------------------------------------------------
[[croneval]]
===== Verifying Cron Expressions
{xpack} ships with a `croneval` command line tool that you can use to verify that
your cron expressions are valid and produce the expected results. This tool is
provided in the `$ES_HOME/bin/x-pack` directory.
To verify a cron expression, simply pass it in as a parameter to `croneval`:
[source,bash]
--------------------------------------------------
bin/x-pack/croneval "0 0/1 * * * ?"
--------------------------------------------------
If the cron expression is valid, `croneval` displays the next 10 times that the
schedule will be triggered.
You can specify the `-c` option to control how many future trigger times are
displayed. For example, the following command displays the next 20 trigger times:
[source,bash]
--------------------------------------------------
bin/x-pack/croneval "0 0/1 * * * ?" -c 20
--------------------------------------------------

View File

@ -0,0 +1,91 @@
[[schedule-daily]]
==== Daily Schedule
A <<trigger-schedule, `schedule`>> that triggers at a particular time
every day. To use the `daily` schedule, you specify the time of day (or times)
when you want the scheduler to start the watch execution with the `at` attribute.
Times are specified in the form `HH:mm` on a 24-hour clock. You can also use the
reserved values `midnight` and `noon` for `00:00` and `12:00`, and
<<specifying-times-using-objects, specify times using objects>>.
NOTE: If you don't specify the `at` attribute for a `daily` schedule, it defaults
to firing once daily at midnight, `00:00`.
===== Configuring a Daily Schedule
To configure a once a day schedule, you specify a single time with the `at`
attribute. For example, the following `daily` schedule triggers once every
day at 5:00 PM:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"daily" : { "at" : "17:00" }
}
}
}
--------------------------------------------------
===== Configuring a Multiple Times Daily Schedule
To configure a `daily` schedule that triggers at multiple times during the day,
you specify an array of times. For example, the following `daily` schedule
triggers at `00:00`, `12:00`, and `17:00` every day.
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"daily" : { "at" : [ "midnight", "noon", "17:00" ] }
}
}
}
--------------------------------------------------
[[specifying-times-using-objects]]
===== Specifying Times Using Objects
In addition to using the `HH:mm` string syntax to specify times, you can specify
a time as an object that has `hour` and `minute` attributes.
For example, the following `daily` schedule triggers once every day at 5:00 PM:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"daily" : {
"at" {
"hour" : 17,
"minute" : 0
}
}
}
}
}
--------------------------------------------------
To specify multiple times using the object notation, you specify multiple hours
or minutes as an array. For example, following `daily` schedule triggers at
`00:00`, `00:30`, `12:00`, `12:30`, `17:00` and `17:30` every day:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"daily" : {
"at" {
"hour" : [ 0, 12, 17 ],
"minute" : [0, 30]
}
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,48 @@
[[schedule-hourly]]
==== Hourly Schedule
A <<trigger-schedule, `schedule`>> that triggers at a particular minute every
hour of the day. To use the `hourly` schedule, you specify the minute (or minutes)
when you want the scheduler to start the watch execution with the `minute`
attribute.
NOTE: If you don't specify the `minute` attribute for an `hourly` schedule, it
defaults to `0` and the schedule triggers on the hour every hour--`12:00`,
`13:00`, `14:00`, and so on.
===== Configuring a Once an Hour Schedule
To configure a once an hour schedule, you specify a single time with the `minute`
attribute.
For example, the following `hourly` schedule triggers at minute 30 every hour--
`12:30`, `13:30`, `14:30`, ...:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"hourly" : { "minute" : 30 }
}
}
}
--------------------------------------------------
===== Configuring a Multiple Times Hourly Schedule
To configure an `hourly` schedule that triggers at multiple times during the
hour, you specify an array of minutes. For example, the following schedule
triggers every 15 minutes every hour--`12:00`, `12:15`, `12:30`, `12:45`,
`1:00`, `1:15`, ...:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"hourly" : { "minute" : [ 0, 15, 30, 45 ] }
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,36 @@
[[schedule-interval]]
==== Interval Schedule
A <<trigger-schedule, `schedule`>> that triggers at a fixed time interval. The
interval can be set in seconds, minutes, hours, days, or weeks:
* `"Xs"` - trigger every `X` seconds. For example, `"30s"` means every 30 seconds.
* `"Xm"` - trigger every `X` minutes. For example, `"5m"` means every 5 minutes.
* `"Xh"` - trigger every `X` hours. For example, `"12h"` means every 12 hours.
* `"Xd"` - trigger every `X` days. For example, `"3d"` means every 3 days.
* `"Xw"` - trigger every `X` weeks. For example, `"2w"` means every 2 weeks.
If you don't specify a time unit, it defaults to seconds.
NOTE: The interval value differs from the standard _time value_ used in
Elasticsearch. You cannot configure intervals in milliseconds or
nanoseconds.
===== Configuring an Interval Schedule
To configure an `interval` schedule, you specify a string value that represents
the interval. If you omit the unit of time (`s`,`m`, `h`, `d`, or `w`), it
defaults to seconds.
For example, the following `interval` schedule triggers every five minutes:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"interval" : "5m"
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,70 @@
[[schedule-monthly]]
==== Monthly Schedule
A <<trigger-schedule, `schedule`>> that triggers at a specific day and time
every month. To use the `monthly` schedule, you specify the day of the month and
time (or days and times) when you want the scheduler to start the watch execution
with the `on` and `at` attributes.
You specify the day of month as a numeric value between `1` and `31` (inclusive).
Times are specified in the form `HH:mm` on a 24-hour clock. You can also use the
reserved values `midnight` and `noon` for `00:00` and `12:00`.
===== Configuring a Monthly Schedule
To configure a once a month schedule, you specify a single day and time with the
`on` and `at` attributes. For example, the following `monthly` schedule triggers
on the 10th of each month at noon:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"monthly" : { "on" : 10, "at" : "noon" }
}
}
}
--------------------------------------------------
NOTE: You can also specify the day and time with the `day` and `time` attributes,
they are interchangeable with `on` and `at`.
===== Configuring a Multiple Times Monthly Schedule
To configure a `monthly` schedule that triggers multiple times a month, you can
specify an array of day and time values. For example, the following `monthly`
schedule triggers at 12:00 PM on the 10th of each month and at 5:00 PM on the
20th of each month:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"monthly" : [
{ "on" : 10, "at" : "noon" },
{ "on" : 20, "at" : "17:00" }
]
}
}
}
--------------------------------------------------
Alternatively, you can specify days and times in an object that has `on` and `at`
attributes that contain an array of values. For example, the following `monthly`
schedule triggers at 12:00 AM and 12:00 PM on the 10th and 20th of each month.
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"monthly" : {
"on" : [ 10, 20 ],
"at" : [ "midnight", "noon" ]
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,75 @@
[[schedule-weekly]]
==== Weekly Schedule
A <<trigger-schedule, `schedule`>> that triggers at a specific day and time
every week. To use the `weekly` schedule, you specify the day and time (or days
and times) when you want the scheduler to start the watch execution with the `on`
and `at` attributes.
You can specify the day of the week by name, abbreviation, or number (with Sunday
being the first day of the week):
* `sunday`, `monday`, `tuesday`, `wednesday`, `thursday`, `friday` and `saturday`
* `sun`, `mon`, `tue`, `wed`, `thu`, `fri` and `sat`
* `1`, `2`, `3`, `4`, `5`, `6` and `7`
Times are specified in the form `HH:mm` on a 24-hour clock. You can also use the
reserved values `midnight` and `noon` for `00:00` and `12:00`.
===== Configuring a Weekly Schedule
To configure a once a week schedule, you specify the day with the `on` attribute
and the time with the `at` attribute. For example, the following `weekly` schedule
triggers once a week on Friday at 5:00 PM:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"weekly" : { "on" : "friday", "at" : "17:00" }
}
}
}
--------------------------------------------------
NOTE: You can also specify the day and time with the `day` and `time` attributes,
they are interchangeable with `on` and `at`.
===== Configuring a Multiple Times Weekly Schedule
To configure a `weekly` schedule that triggers multiple times a week, you can
specify an array of day and time values. For example, the following `weekly`
schedule triggers every Tuesday at 12:00 PM and every Friday at 5:00 PM:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"weekly" : [
{ "on" : "tuesday", "at" : "noon" },
{ "on" : "friday", "at" : "17:00" }
]
}
}
}
--------------------------------------------------
Alternatively, you can specify days and times in an object that has `on` and
`minute` attributes that contain an array of values. For example, the following
`weekly` schedule triggers every Tuesday and Friday at 12:00 PM and 17:00 PM:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"weekly" : {
"on" : [ "tuesday", "friday" ],
"at" : [ "noon", "17:00" ]
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,83 @@
[[schedule-yearly]]
==== Yearly Schedule
A <<trigger-schedule, `schedule`>> that triggers at a specific day and time
every year. To use the `yearly` schedule, you specify the month, day, and time
(or months, days, and times) when you want the scheduler to start the watch
execution with the `in`, `on`, and `at` attributes.
You can specify the month by name, abbreviation, or number:
* `january`, `february`, `march`, `april`, `may`, `june`, `july`,
`august`, `september`, `october`, `november` and `december`
* `jan`, `feb`, `mar`, `apr`, `may`, `jun`, `jul`, `aug`,
`sep`, `oct`, `nov` and `dec`
* `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11` and `12`
You specify the day of month as a numeric value between `1` and `31` (inclusive).
The Times are specified in the form `HH:mm` on a 24-hour clock. You can also use
the reserved values `midnight` and `noon` for `00:00` and `12:00`.
===== Configuring a Yearly Schedule
To configure a once a year schedule, you specify the month with the `in` attribute,
the day with the `on` attribute, and the time with the `at` attribute. For
example, the following `yearly` schedule triggers once a year at noon on January
10th:
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"yearly" : { "in" : "january", "on" : 10, "at" : "noon" }
}
}
}
--------------------------------------------------
NOTE: You can also specify the month, day, and time with the `month`, `day`, and
`time` attributes, they are interchangeable with `in`, `on`, and `at`.
===== Configuring a Multiple Times Yearly Schedule
To configure a `yearly` schedule that triggers multiple times a year, you can
specify an array of month, day, and time values. For example, the following
`yearly` schedule triggers twice a year: at noon on January 10th, and at 5:00 PM
on July 20th.
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"yearly" : [
{ "in" : "january", "on" : 10, "at" : "noon" },
{ "in" : "july", "on" : 20, "at" : "17:00" }
]
}
}
}
--------------------------------------------------
Alternatively, you can specify the months, days, and times in an object that has
`in`, `on`, and `minute` attributes that contain an array of values. For example,
the following `yearly` schedule triggers at 12:00 AM and 12:00 PM on January 10th,
January 20th, December 10th, and December 20th.
[source,js]
--------------------------------------------------
{
"trigger" : {
"schedule" : {
"yearly" : {
"in" : [ "jan", "dec" ],
"on" : [ 10, 20 ],
"at" : [ "midnight", "noon" ]
}
}
}
}
--------------------------------------------------

View File

@ -0,0 +1,58 @@
[[watcher-troubleshooting]]
== {watcher} Troubleshooting
[float]
=== Dynamic Mapping Error When Trying to Add a Watch
If you get the _Dynamic Mapping is Disabled_ error when you try to add a watch,
verify that the index mappings for the `.watches` index are available. You can
do that by submitting the following request:
[source,js]
--------------------------------------------------
GET .watches/_mapping
--------------------------------------------------
// CONSOLE
// TEST[setup:my_active_watch]
If the index mappings are missing, follow these steps to restore the correct
mappings:
. Stop the Elasticsearch node.
. Add `xpack.watcher.index.rest.direct_access : true` to `elasticsearch.yml`.
. Restart the Elasticsearch node.
. Delete the `.watches` index:
+
[source,js]
--------------------------------------------------
DELETE .watches
--------------------------------------------------
+
. Disable direct access to the `.watches` index:
.. Stop the Elasticsearch node.
.. Remove `xpack.watcher.index.rest.direct_access : true` from `elasticsearch.yml`.
.. Restart the Elasticsearch node.
[float]
=== Unable to Send Email
If you get an authentication error indicating that you need to continue the
sign-in process from a web browser when Watcher attempts to send email, you need
to configure Gmail to
https://support.google.com/accounts/answer/6010255?hl=en[Allow Less Secure Apps to access your account].
If you have two-step verification enabled for your email account, you must
generate and use an App Specific password to send email from {watcher}. For more
information, see:
- Gmail: https://support.google.com/accounts/answer/185833?hl=en[Sign in using App Passwords]
- Outlook.com: http://windows.microsoft.com/en-us/windows/app-passwords-two-step-verification[App passwords and two-step verification]
[float]
=== {watcher} Not Responsive
Keep in mind that there's no built-in validation of scripts that you add to a
watch. Buggy or deliberately malicious scripts can negatively impact {watcher}
performance. For example, if you add multiple watches with buggy script
conditions in a short period of time, {watcher} might be temporarily unable to
process watches until the bad watches time out.