Keywords & Triggers
There are two types of triggers: keywords and container_events.
Keyword Types
The keywords list accepts three types, which can be mixed freely:
keywords:
- error # simple keyword
- keyword: failed login # another way to set a simple keywordkeywords:
- regex: 'download.*failed'
- regex: 'process (?P<pid>\d+) crashed' # named capture group → available in templates# these only trigger when all members of the all_of group match in the same log entry
keywords:
- all_of:
- error
- timeout
- keyword: database
- all_of:
- keyword: authentication
- regex: 'failed.*attempt'INFO
- keywords are case-insensitive
- regexes are case-sensitive by default (controlled by
regex_case_sensitiveindefaults:) - named capturing groups (
(?P<name>...)) can be used to extract values that become available as template variables intitle_templateandmessage_template. See Customize Noticications and Extract from Regex.
Container Events
Monitor Docker container lifecycle events instead of (or in addition to) log content.
containers:
rules:
- container_name: my-app
container_events:
- event: crash
- event: oomSupported Events
| Event | Triggered when... |
|---|---|
start | Container is started |
stop | Container is stopped via a stop request (not on crashes or forced exits) |
die | Container exits, regardless of reason (stop, crash, or kill) |
crash | Container exits with a non-zero exit code |
destroy | Container is removed |
healthy | Container health status changes to healthy |
unhealthy | Container health status changes to unhealthy |
starting | Container health status changes to starting |
oom | Container is killed by the OOM killer |
kill | Container is killed by a signal |
create | Container is created |
restart | Container is restarted |
How triggers are merged across levels
Keywords and container events can be configured at the following levels:
- Global level (
global.keywords): applied to every matched target across all sources. - Source level (
containers.keywords,containers.container_events): applied to every target of that source (containersorswarm) that is matched by any rule. - Rule level (
rules[*].keywords,rules[*].container_events): applied only to containers matched by that specific rule.
Triggers from all levels are combined. Source-level triggers come first, followed by rule-level triggers.
If the same container event type appears at multiple levels, the most specific level's settings are used.
INFO
There will most likely be more log sources in the future. This is why there is no global.container_events section since that is specific to containers and swarm.
Example
global:
keywords:
- "critical" # applied to every matched target across all sources (containers and swarm)
containers:
keywords:
- keyword: "panic" # applied to every container matched by any rule
container_events:
- event: crash # applied to every container matched by any rule
rules:
- container_name: my-app
keywords:
- keyword: "error" # applied only to containers matched by this rule
container_events:
- event: start # applied only to containers matched by this rule
swarm:
rules:
- service_name: my-service
keywords:
- keyword: "timeout" # applied only to services matched by this ruleThreshold-Based Triggering with trigger_on
Instead of triggering on every match, trigger_on delays a trigger until the keyword has matched a minimum number of times within a sliding time window. This is useful for noisy signals where a single occurrence is not actionable, but repeated occurrences indicate a real problem.
trigger_on works on keyword:, regex:, and all_of: items, as well as on container_events items.
keywords:
- keyword: "connection timeout"
trigger_on:
count: 5
timeframe: 60
title_template: "{{ container_name }}: {{ trigger_on_count }} timeouts in {{ trigger_on_timeframe }}s"container_events:
- event: crash
trigger_on:
count: 5
timeframe: 60
title_template: "{{ container_name }} crashed {{ trigger_on_count }} times in {{ trigger_on_timeframe }}s"Behavior:
- Each match is recorded in an in-memory sliding window.
- When the match count reaches
countwithintimeframeseconds, the trigger fires and the counter resets to zero. trigger_cooldownstill applies as a gate before a match is evaluated againsttrigger_on.countmust be≥ 2.timeframemust be≥ 1second.
Template variables available when trigger_on is set:
{{ trigger_on_count }}: the configured count threshold{{ trigger_on_timeframe }}: the configured timeframe in seconds
Actions
You can configure container_action and olivetin_actions on keywords and container events.
See Actions for more details.
Per-Keyword defaults Settings
Any field from global.defaults: can be set on an individual trigger (keyword or container event). These override the inherited value for that specific trigger only.
Per Trigger Settings Example
global:
defaults:
ntfy_priority: 1
attach_logfile: false
containers:
rules:
- container_name: my-app
keywords:
- keyword: error
ntfy_priority: 5 # override priority for this keyword only
attach_logfile: true
trigger_cooldown: 60
title_template: "Error in my-app"
- regex: 'panic.*goroutine'
ntfy_topic: "critical-alerts"
container_action: restart # see Actions guide
container_events:
- event: crash
ntfy_priority: 5
attach_logfile: true
title_template: "Container {{ container_name }} crashed"Additional explanation on some of the settings from global.defaults:
merge_matches
Controls what happens when multiple keywords match in the same log line.
merge_matches: false(default): each matching keyword fires its own independent notification with its own configuration. One log line can produce multiple notifications.merge_matches: true: all keywords matching the same log line that havemerge_matches: trueset (whether inherited or set on the keyword itself) are merged into one notification. Keywords that havemerge_matches: falsefire their own independent notification.
defaults:
merge_matches: true
containers:
rules:
- container_name: my-app
keywords:
- keyword: "error"
merge_matches: false # this keyword will not be merged with other keywordsmerge_matches can be set at defaults:, source-level defaults:, rule level, or per-keyword. Setting it on individual keywords makes those keywords opt-in or opt-out of merging while others remain independent.
ignore_keywords
Keywords or regex patterns that suppress a trigger when found in the same log line.
Can be set at multiple levels
defaults:
ignore_keywords:
- regex: "debug.*message"
containers:
rules:
- container_name: my-app
ignore_keywords:
- keyword: "ignoreforthisrule"
keywords:
- keyword: "error"
ignore_keywords:
- regex: "ignoreforthiskeyword"ignore_keywords are merged across all levels.
disable_trigger_notifications
Suppresses the notification when a trigger fires, while still executing any configured actions (container actions, OliveTin actions). Useful when you only want to trigger automation without notification noise.
keywords:
- keyword: "unhealthy"
disable_trigger_notifications: true
container_action: restart