AlertRule Spec
The full AlertRule file format, the apply manifest, and the alert evaluation states.
An AlertRule is a resource with three top-level keys. Everr validates it on everr apply; reads return the spec exactly as it was stored at apply time, with no re-validation. The spec holds a ClickHouse query, a threshold condition, and the notification text to send when instances start and stop firing. The query always returns its useful data; the condition decides which rows fire.
kind: AlertRule
metadata:
name: <slug>
spec:
{ ... }| Key | Type | Notes |
|---|---|---|
kind | "AlertRule" | Selects the reconciler. Required. |
metadata.name | string | The rule's slug. Required. 1 to 128 characters from [A-Za-z0-9_.-]; cannot be exactly . or ... |
metadata.project | string | Groups the rule with other resources. Optional, defaults to default. Lowercase letters, digits, and hyphens only; cannot start or end with a hyphen. Together with metadata.name it forms the rule's canonical identity, <project>/<slug>. |
metadata.labels | map (string to string) | Optional, descriptive metadata. Stored as everr.label.<key> annotations on the rule. Silence matchers cannot match on them; instance labels come from the query's result columns. |
spec | object | The rule contents, below. |
spec
| Field | Type | Required | Notes |
|---|---|---|---|
evaluationInterval | string | yes | How often the query runs. <int><s|m|h|d>, minimum 1m. |
for | string | no | How long the condition must hold continuously before firing. <int><s|m|h|d>; default 0s (fire on the first matching evaluation). While waiting, the instance is pending and sends nothing. |
resolveAfter | int | no | Consecutive evaluations where a firing instance is absent or no longer matches before it resolves. Default 1; raise it (for example 3) to tolerate gaps in the data. Must be ≥ 1. |
severity | string | no | One of info, warning, critical. Default info. Stamped as the severity label on every dispatched event; a severity-split default destination delivers by it. See set up notifications. |
query | string | yes | ClickHouse SQL. Must return a numeric column named value. No ${...} templating. |
condition | object | yes | A numeric threshold applied to each row's value: { operator, threshold }. Supported operators: gt, gte, lt, lte, eq, neq. A matching row is a firing instance. |
notifications | object | no | The rule's own notification destination. When present, its channels receive this alert and the Organization's default destination is skipped. Silences still apply. |
notifications.channels | [string] | yes, within notifications | One or more unique Organization channel names. A name that does not match an existing channel is an apply warning, not an error: the reference links up when the channel is created. |
notificationMessage | object | yes | The notification text. See below. |
notificationMessage.title | string | yes | Supports ${column} (any query result column) and ${value}. Non-empty. |
notificationMessage.description | string | no | Supports ${column} and ${value}. |
instanceLabels | [string] | no | The columns that form instance identity. Each must be a column the query returns. Without it, apply infers the identity from every string-typed result column, so each distinct combination is its own instance; a query with no string columns yields a single instance. Set it to [] to say so explicitly: the whole result is one instance, whatever columns the query returns. Apply resolves the identity once and stores it, so the rule evaluates on the columns you see when you export it. |
maxInterval | string | no | Duration string (<int><s|m|h|d>), the ceiling for adaptive retry backoff. Evaluation health becomes degraded on the first failed attempt and returns to healthy after the next successful evaluation. When both durations parse, maxInterval must be greater than or equal to evaluationInterval. Omit it to use the default cap. |
annotations | map (string to string) | no | Free-form key/value pairs stored with the alert rule alongside Everr's own generated annotations. Keys starting with everr., and the exact keys summary, description, link.alert, and link.runbook, are reserved for Everr's generated sugar and rejected here. |
display | object | no | name and/or description, both optional. Human-facing labels. |
runbook | string | no | A linked runbook: bare slug (resolved against the alert's own project) or project/slug. Must resolve at apply time, either to a runbook in the same apply or to one owned by another repo. Generates the link.runbook notification annotation. |
Ownership is keyed by the rule's canonical name (<project>/<slug>) and its first-class Repoid. A rule under another Repoid with a name your config declares is an ownership conflict at apply time: everr apply fails fast unless run with --adopt, which transfers the rule in place. A rule owned by your Repoid is part of that config: apply updates it when the spec drifts and prunes it if no YAML file declares it.
Notification destination
By default, an alert delivers to the Organization's default destination (see set up notifications). Set notifications.channels when a rule has its own destination that should override it:
spec:
notifications:
channels: [team-slack, primary-on-call]The channel names reference existing Organization channels. Configuration and secrets stay with the channels and are not copied into the alert definition. Direct notifications use the same fixed grouping: instances batch by rule and severity. Omitting notifications restores the default destination. Preview alerts remain suppressed even when they declare their own destination.
Message templating
notificationMessage.title and notificationMessage.description support ${...} placeholders, substituted per firing instance when the notification is rendered:
${<column>}expands to that instance's value for any column the query returns: aninstanceLabelscolumn resolves from the instance's labels, and every other column resolves from the event's evidence (the source row's remaining columns).${value}expands to the matching row's required numericvaluecolumn.
Referencing a column the query does not return is an apply-time error. A missing, null, empty, or non-numeric value does not match the condition.
Evidence is capped: an event carries at most 16 non-label columns, and only while their compact JSON stays under 4096 bytes; past the caps, refs to non-label columns may render empty (apply warns when a message depends on columns beyond the 16-column cap). The query SQL itself does not support templating, placeholders work only in the notification message fields.
Manifest
The apply identity (the repoid) is inferred automatically from the repository's origin git remote, normalized to the slug host/owner/repo: scheme, credentials, port, a trailing .git, and trailing slashes are stripped and the result is lowercased. For example, git@github.com:Acme/API.git becomes github.com/acme/api. Equivalent ssh, https, and scp clone URLs collapse to the same identity, so one repo means one boundary.
No manifest file is needed when the repo has an origin remote. An optional everr.yaml (or everr.yml) at the apply root overrides the inferred identity. It accepts exactly one key:
# everr/everr.yaml
repoid: "my-explicit-id"| Field | Type | Notes |
|---|---|---|
repoid | string | Explicit identity override. When present it always wins over the inferred slug. Use it for local-only repositories, non-git directories, or when you need to pin an explicit name. The manifest rejects any other key. |
If there is neither an origin remote nor an everr.yaml manifest, apply errors and tells you to add a remote or create everr.yaml.
Declarations sit flat in everr/, named by kind: *.alert.yaml, *.dashboard.yaml, and *.runbook.yaml (the legacy *.notebook.yaml suffix is still recognized). everr apply ./everr discovers every kind: Dashboard, kind: AlertRule, and kind: Runbook document under the directory and makes the live resources for that repoid exactly match the tree: new documents are created, changed ones updated, and removed ones deleted. The kind suffix is a naming convention only; apply routes by the kind: field. Use --preview to stage the changes for review without touching the live state (preview rules evaluate but never notify). See the everr apply reference.
Constraints and errors
evaluationIntervalmust be ≥1m.formust be a valid duration (0sis allowed).resolveAftermust be an integer ≥ 1.severity, when set, must beinfo,warning, orcritical.notificationMessage.titleis required and non-empty.notifications.channelsmust contain unique, non-empty names. A named channel that does not exist produces an apply warning.${...}in messages must reference a column thequeryreturns or be${value}.querymust return a numeric column namedvalue.condition.operatormust begt,gte,lt,lte,eq, orneq;condition.thresholdmust be a finite number.instanceLabelsentries must each be a column thequeryreturns. An empty list is valid and means the whole result is one instance.queryrejects${...}.maxInterval, when set, must be a valid duration and, whenevaluationIntervalalso parses, greater than or equal to it.annotationskeys starting witheverr., and the exact keyssummary,description,link.alert, andlink.runbook, are rejected: those are reserved for Everr's own generated annotations.- Supported document kinds for apply are
Dashboard,AlertRule, andRunbook.