All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Raw _msg piped into email_body_html renders unescaped in email clients.
The example config switched body: "" in v1.2.0 (#26 fix), and operators may reasonably mirror that in email_body_html. The email notifier marks body as safe (pre-escaped HTML) before injection into the email envelope, so a log line containing raw HTML or <script> tags would render unescaped in the recipient’s mail client.
This is pre-existing behaviour from v1.x, not a regression introduced in v2.0.0, but the surface is wider now that the example actively uses _msg.
Mitigation: if your VictoriaLogs ingests untrusted content (web request bodies, user-controlled fields), wrap the offending field with | escape, or render via plain body (not email_body_html) for email destinations until the email path is hardened in a follow-up.
victorialogs is now a map of named sources. A single valerter instance can tail multiple VL backends and route alerts per source. The v1.x single-URL shape (victorialogs.url: ... at the top level) is rejected at load with an actionable migration error.
Migrate from:
victorialogs:
url: "http://victorialogs:9428"
basic_auth:
username: "u"
password: "p"
To:
victorialogs:
default:
url: "http://victorialogs:9428"
basic_auth:
username: "u"
password: "p"
Then optionally target sources per rule via vl_sources: [name, ...], or omit the field to fan out across every configured source. Credentials, TLS, and headers are per-source, self-contained in each VlSourceConfig.
Default throttle key is now {rule}-{source}:global (was {rule}:global in v1.x). Multi-source deployments get isolated throttle buckets per source with no extra config. Users who want cross-source dedup must override throttle.key explicitly (e.g. key: "").
Source names are restricted to ^[a-zA-Z0-9_]+$. No dashes, colons, dots, or spaces allowed. Validated at load. The constraint avoids ambiguity in the default throttle key format above.
Notifier output formats extended with vl_source. The Mattermost footer now reads valerter | <rule> | <source> | <timestamp> instead of valerter | <rule> | <timestamp>. The default webhook payload exposes vl_source as a top-level JSON field. Downstream parsers / dashboards that match exact strings in either output need to update.
All per-rule Prometheus metrics now also carry a vl_source label. Affected counters: valerter_alerts_sent_total, valerter_alerts_throttled_total, valerter_alerts_passed_total, valerter_alerts_failed_total, valerter_email_recipient_errors_total, valerter_lines_discarded_total, valerter_logs_matched_total, valerter_notify_errors_total, valerter_parse_errors_total, valerter_reconnections_total, valerter_rule_panics_total, valerter_rule_errors_total. Affected gauge/histogram: valerter_last_query_timestamp, valerter_query_duration_seconds. Dashboards and alerts that grouped by rule_name alone keep working but get an extra vl_source dimension; PromQL using sum by (rule_name) (...) still rolls up correctly. valerter_queue_size stays unlabeled (the queue is shared, not per-source).
valerter_victorialogs_up{rule_name} removed and replaced by valerter_vl_source_up{vl_source}. The new gauge is per-source (one value per configured source, regardless of how many rules tail it) since reachability is a property of the source, not the rule. Alerts and panels need to migrate from per-rule to per-source semantics. Examples:
# v1.x (per-rule): valerter_victorialogs_up{rule_name="nginx-5xx"} == 0
# v2.0.0 (per-source): valerter_vl_source_up{vl_source="prod"} == 0
# v1.x (any rule down): min(valerter_victorialogs_up) == 0
# v2.0.0 (any source): min(valerter_vl_source_up) == 0
The label key is now vl_source (not rule_name), and the cardinality drops from |rules| to |sources|.
defaults.max_streams cap introduced (default 50). Total VictoriaLogs streams = sum of (rule, source) pairs spawned for enabled rules. Breaching the cap fails the config at load with both the actual count and the cap value. Configurable via defaults.max_streams: <usize>. Disabled rules do not contribute. Prevents accidental fan-out from DoSing a backend.
(rule, source) pair with per-source cancellation and reconnect isolation, so a single unhealthy source does not stop alerts on the others.template variable** available everywhere is: layer 1 templates (title, body, email_body_html), throttle.key, and notifier-level layer 2 contexts (subject_template, body_template). Always non-empty, owned String, equal to the source name currently processing the event. Synthetic value wins over any event field literally named vl_source (matches the rule_name collision policy).AlertPayload.vl_source propagated end-to-end so notifiers can render the source name. See Breaking changes above for the related output format updates on Mattermost and webhook destinations.valerter_vl_source_up{vl_source} per-source reachability gauge. Initialized to 0 for every configured source at startup; engine flips to 1 on tail connect success and back to 0 on permanent failure or stream error. Replaces the v1.x per-rule valerter_victorialogs_up.±10% uniform jitter on reconnect backoff (per (rule, source) task). Sources behind a flapping load balancer no longer reconnect in lock-step, breaking the thundering-herd alignment over a few cycles. Hardcoded jitter range; not configurable in this release.tests/metrics_snapshot.rs integration test. Spins up a 2-source 1-rule engine, scrapes /metrics, and asserts the set of metric names + label keys (not values) against an inline expected string. Catches accidental relabel/rename in future PRs.examples/multi-source/config.yaml reference and top-level MIGRATION.md for v1.x upgraders.available in top-level templates and throttle key** (issue #31). `rule_name` is now injected into the render context of `templates.<name>.title`, `body`, and `email_body_html`, and also into the `throttle.key` template, not just the notifier-level `subject_template` / `body_template`. Configs that referenced in a top-level template previously rendered an empty string; they now render the rule name. If an event field happens to be literally named rule_name, the synthetic rule name wins, matching the collision policy of the existing notifier-level contexts.throttle.key. The unflatten step introduced in v1.2.0 for template rendering (issue #25) now also applies to the throttle key template, so throttle.key: "-" works consistently with title / body.body_html renamed to email_body_html to reflect that
only the email notifier consumes it (Telegram, Mattermost, and webhook always
ignored it). Migration: in every template, replace body_html: with
email_body_html:. This applies to templates defined inline in config.yaml
and to any split files under templates.d/. Configs using the old name are
rejected at load time with a clear error that lists email_body_html among
the expected fields, so valerter --validate will point out every template
that needs updating on the first run.server.hostname or http.request.method can now be referenced directly in
Jinja templates using dotted notation, matching the shape users see in log
payloads.body_html (now email_body_html) is email-only so users do not
accidentally leave body empty.type: telegram notifier using the
Bot API sendMessage endpoint. Supports multi-chat delivery (one sequential
HTTP call per chat_id), HTML parse_mode by default, 429 Retry-After
handling, automatic codepoint-safe truncation at Telegram’s 4096 character
limit, and a new valerter_alerts_truncated_total Prometheus counter.body field that is shared across all notifiers. If
you write a Markdown-flavored body (e.g. **bold**, triple-backtick fences)
for Mattermost, Telegram will render those markers literally because it is
configured with parse_mode: HTML. Workaround: override body_template on
the Telegram notifier with HTML-friendly Jinja, for example
body_template: "<b></b>\n<pre></pre>". A proper
render-pipeline-per-notifier abstraction is planned for 1.2.Promote 1.0.0-rc.5 to stable. No functional changes.
cargo update to pick up patched versions:
aws-lc-sys 0.35.0 → 0.39.1 (GHSA advisories on AWS-LC crypto/x509)quinn-proto 0.11.13 → 0.11.14 (QUIC transport parameter DoS)rustls-webpki 0.103.8 → 0.103.11 (CRL scope check)bytes 1.11.0 → 1.11.1 (BytesMut::reserve integer overflow)Final RC - Hardening and observability improvements before 1.0.0 stable.
valerter_lines_discarded_total{reason=oversized} metric to prevent OOM from malformed inputdeny_unknown_fields rejects typos, URL format validation for VictoriaLogs and webhook endpointsinstrument() for async-safe span propagation in all notifier functions (engine, queue, mattermost, webhook, email)rule_name label from alerts_dropped_total (global metric, not per-rule)valerter_email_recipient_errors_total and valerter_notifier_config_errors_total, added performance reportFeature freeze - From this release, only bug fixes until 1.0.0 stable. No new features or refactoring.
.d/ directories (rules.d/, templates.d/, notifiers.d/)mattermost_channel is set but no Mattermost notifier in destinationsnotify.template required - Each rule must now specify its template explicitly (no more defaults.notify.template fallback)notify.destinations required - Each rule must specify at least one destinationdefaults.notify removed - The entire defaults.notify section has been removednotifiers section required - At least one notifier must be configuredtemplates section required - At least one template must be definedMATTERMOST_WEBHOOK env var removed - Use notifiers section insteadnotify.channel renamed - Now notify.mattermost_channel for claritynotify section now cause parsing errors.d/ directories on installtimestamp_timezone setting for formatted timestamps (default: UTC)examples/cisco-switches/proxy_buffering off)/select/logsql/tail endpointvalerter_victorialogs_up now correctly documented as connection statusconfig.rs into focused submodulesnotify.rs into focused submodulesbody_html fieldtemplates/default-email.html.j2body_htmldocs/ folder with detailed guides (getting-started, configuration, notifiers, metrics, architecture)color → accent_color - Template field renamed for clarityicon removed - Template field no longer supportedvalerter_build_info metric - Exposes version label for Prometheus dashboards.md, images)valerter_alerts_passed_total - alerts that passed throttlingvalerter_rule_panics_total - rule task panics (auto-restarted)valerter_rule_errors_total - fatal rule errorsvalerter_last_query_timestamp - timestamp of last successful queryvalerter_victorialogs_up - VictoriaLogs connection statusvalerter_query_duration_seconds - query latency histogramvalerter_latest_amd64.deb now available via /releases/latest/download//tail API/metrics)