Implementing Alerting and Watcher
1. Understanding Watcher
Watcher is a component of the ELK Stack (Elasticsearch, Logstash, Kibana) that enables users to define and automate alerting rules based on data in Elasticsearch. It allows for the creation of "watch" configurations that can monitor indices, execute queries, and trigger actions when specific conditions are met.
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the watch | "my-watch" |
| trigger | Defines when the watch should be executed | { "schedule": { "interval": "5m" } } |
| input | Defines the data source for the watch | { "search": { "request": { "indices": ["logs-*"], "body": { "query": { "match": { "status": "error" } } } } } } |
| condition | Defines the condition under which the watch should execute actions | { "compare": { "ctx.payload.hits.total": { "gt": 0 } } } |
| actions | Defines what actions to take when the condition is met | { "email": { "to": "admin@example.com", "subject": "Error Alert" } } |
Example: Basic Watch Configuration
{
"id": "error-alert",
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"match": {
"status": "error"
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 0
}
}
},
"actions": {
"email": {
"to": "admin@example.com",
"subject": "Error Alert"
}
}
}
Note: Watcher requires a valid Elasticsearch cluster and Kibana instance to function. The watch configuration must be stored in the
.watcher-history index or via Kibana's UI.
Key Features of Watcher
- Triggering Mechanisms: Supports scheduled, manual, and continuous triggers.
- Input Types: Can pull data from Elasticsearch, HTTP endpoints, or other sources.
- Condition Logic: Allows complex condition checks using scripting or built-in comparisons.
- Action Types: Supports email, webhook, Slack, and more via action templates.
2. Creating Watches
| Property | Description | Example |
|---|---|---|
| id | Unique identifier for the watch | "my-watch" |
| trigger | Defines when the watch should run | |
| input | Defines the data source for the watch | |
| condition | Condition to determine if the watch should execute actions | |
| actions | Defines what to do when the watch triggers | |
Example: Creating a Watch
{
"id": "error-alert",
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"match": {
"level": "ERROR"
}
},
"size": 0,
"aggs": {
"error_count": {
"value_count": {
"field": "message"
}
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.aggregations.error_count.value": {
"gt": 10
}
}
},
"actions": {
"email": {
"to": ["admin@example.com"],
"subject": "High error count detected",
"body": "Detected {{ctx.payload.aggregations.error_count.value}} errors in the last 5 minutes."
}
}
}
3. Using Schedule Triggers
| Property | Description | Values | Notes |
|---|---|---|---|
| schedule | Defines when the watch runs | interval, cron |
Required field |
| interval | Time interval between executions | 1m, 5h, 1d |
Used with schedule |
| cron | Cron expression for scheduling | 0 0 * * * |
Used with schedule |
4. Configuring Input Sources
Example: Using a Search Input
{
"input": {
"search": {
"request": {
"body": {
"query": {
"match": {
"status": "error"
}
}
}
}
}
}
}
| Input Type | Description | Configuration | Notes |
|---|---|---|---|
| search | Queries data from Elasticsearch | request.body, indices |
Most common input type for alerts |
| http | Fetches data from an HTTP endpoint | url, method |
Useful for external data sources |
| simple | Static input without dynamic data | payload |
Good for testing or fixed values |
Note: The
search input is the most commonly used input type in Watcher, enabling real-time monitoring of Elasticsearch indices.
5. Defining Conditions
| Condition Type | Description | Example |
|---|---|---|
| compare | Compares a field value to a threshold using operators like >, <, == | |
| exists | Checks if a field exists in the document | |
| range | Checks if a field value is within a specified range | |
| script | Runs a custom script to evaluate the condition | |
Example: Using Compare Condition
{
"condition": {
"compare": {
"ctx.payload.aggregations.avg_response_time.value": {
"gt": 500
}
}
},
"transform": {
"script": {
"source": "return 'High response time detected: ' + ctx.payload.aggregations.avg_response_time.value"
}
}
}
6. Setting Up Actions
| Action Type | Description | Configuration Example | Notes |
|---|---|---|---|
| Sends an email notification | |
Requires email server configuration in Elasticsearch | |
| webhook | Posts alert data to a webhook URL | |
Supports custom headers and body formatting |
| slack | Sends alert to Slack channel | |
Requires Slack incoming webhook setup |
| index | Creates a new document in an index | |
Useful for storing alert history |
Example: Email Action Configuration
{
"actions": {
"send_email": {
"email": {
"to": ["ops@example.com"],
"subject": "Elasticsearch Alert: {{ctx.watch_id}}",
"body": "The following condition was met:\n{{ctx.payload.hits.total}} hits found"
}
}
}
}
Example: Slack Webhook Action
{
"actions": {
"send_to_slack": {
"webhook": {
"url": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
"method": "POST",
"body": "{\n \"text\": \"Alert triggered: {{ctx.watch_id}}\"\n}"
}
}
}
}
7. Using Transform
Example: Basic Transform Configuration
{
"id": "transform-example",
"source": {
"index": "logs-*"
},
"dest": {
"index": "transformed-logs"
},
"transform": {
"script": {
"source": "ctx.response = ctx._source.response_time"
}
}
}
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the transform | string |
| source.index | Source index pattern to transform | string |
| dest.index | Destination index to store transformed data | string |
| transform.script.source | Script to transform the data | string |
Note: Transforms are executed asynchronously and can be scheduled to run at regular intervals.
Warning: Ensure that the destination index has appropriate mappings to handle transformed data.
8. Testing Watches
Example: Simple Watch Test
{
"trigger": {
"schedule": {
"interval": "1m"
}
},
"input": {
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"match": {
"status": "error"
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 0
}
}
},
"actions": {
"log-error": {
"logging": {
"text": "Found {{ctx.payload.hits.total}} error logs"
}
}
}
}
| Property | Description | Values |
|---|---|---|
| trigger.schedule.interval | Schedule interval for watch execution | 1m, 5m, 1h |
| input.search.request.indices | Indices to search in | logs-*, app-logs-2024* |
| condition.compare.ctx.payload.hits.total | Condition to compare against | gt 0, eq 10 |
Note: Use
ctx.payload.hits.total to access the result count from search input.
Testing Workflow
- Create a watch with a simple condition
- Use the
elasticsearch:watcherAPI to execute it manually - Check logs for action execution
- Adjust conditions or actions based on output
Watch vs Trigger
- Watch: Complete alerting unit with input, condition, and actions
- Trigger: Schedule or event that causes a watch to run
9. Managing Watch History
| Field | Description | Values |
|---|---|---|
| watch_id | Unique identifier for the watch | string |
| execution_time | Time when the watch was executed | datetime |
| status | Execution status of the watch | success, failure, error |
| triggered | Whether the watch was triggered | true, false |
| result | Result of the watch execution | object |
Example: Retrieve Watch History
const history = await client.watcher.getHistory({
watch_id: 'my-watch'
});
console.log(history);
Note: Watch history is stored in Elasticsearch and can be queried using the
_watcher/history endpoint.
Warning: Watch history is limited by default to 100 entries. Configure
watcher.history settings to increase this limit.
10. Acknowledging Alerts
| Field | Description | Values |
|---|---|---|
| alert_id | Unique identifier for the alert | string |
| acknowledged_by | User who acknowledged the alert | string |
| acknowledged_at | Timestamp of acknowledgment | datetime |
Example: Acknowledge Alert via API
PUT /_watcher/acknowledge_alert/<alert_id>
{
"acknowledged_by": "john.doe",
"acknowledged_at": "2026-04-05T10:00:00Z"
}
Note: Acknowledging an alert does not close it; it only marks that the alert has been reviewed.
11. Using Chained Inputs
| Input Type | Description | Usage Example |
|---|---|---|
| chain | Allows chaining multiple inputs together in a sequence | |
| search | Executes a search query to fetch data from Elasticsearch | |
| http | Fetches data from an HTTP endpoint | |
Example: Chained Search Inputs
{
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"chain": [
{
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"match": {
"level": "error"
}
},
"size": 10
}
}
}
},
{
"search": {
"request": {
"indices": ["logs-*"],
"body": {
"query": {
"range": {
"@timestamp": {
"gte": "now-1h"
}
}
},
"size": 5
}
}
}
}
]
},
"condition": {
"compare": {
"ctx.payload.hits.total.value": {
"gt": 0
}
}
},
"actions": {
"log-alert": {
"logging": {
"text": "Found {{ctx.payload.hits.total.value}} errors in the last hour"
}
}
}
}
12. Debugging Watch Failures
| Issue | Description | Solution |
|---|---|---|
| Watcher not triggering | Watch fails to execute despite conditions being met | Check Watcher logs in Elasticsearch for errors or warnings. Ensure the watch's condition is correctly defined and that the input query returns results. |
| Incorrect alerting thresholds | Alerts fire when they shouldn't or don't fire when they should | Review the watch's condition logic and thresholds. Use debug to inspect values during execution. |
| Timeout errors | Watcher times out during execution | Increase watcher.execution.timeout setting in Elasticsearch config or optimize the watch's query and actions. |
| Action failures | Alerts are triggered but actions (e.g., email, webhook) fail | Check action configuration and logs. Ensure the action URL or email settings are valid. |
Note: Use
debug in the watch definition to inspect variables and conditions during execution.
Warning: Avoid complex queries or actions in watches that may cause timeouts or resource exhaustion.