Phase 13 build: logs, metrics, alerting and a deadman on a diag. host
Six containers, all loopback-published, reachable only through the gated diag. host: victorialogs 30d retention, -http.pathPrefix=/logs so Caddy passes the prefix through unchanged vector docker_logs + journald -> VictoriaLogs (elasticsearch bulk, the documented path) victoriametrics 90d, scrapes the four taps that were already live plus the new services vmalert-metrics 11 metric rules: disk, load, memory, RAID, restart loops, a core container gone vmalert-logs 5 LogsQL rules: sweep failures, publish-deny bursts, failed bot deploys, cert trouble alertmanager groups and inhibits, posts to Discord, webhook read from a 0600 file not the config The deadman (bin/vanguard-deadman.sh, host timer, 5 min) is the part that does not trust any of the above: curl only, it checks each component answers, that the always-firing Watchdog alert is still arriving through vmalert -> Alertmanager -> dumpd /heartbeat, and the disks. It reports on change and announces recovery once. Verified here: failures listed, silence when nothing changes, disk threshold, recovery fired once. Collection uses the Docker socket (Phase 13 option A, chosen explicitly). That is root-equivalent on this host and is recorded as such in vector.yaml with the two upgrade paths. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
33
observability/alerts-logs.yml
Normal file
33
observability/alerts-logs.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
# Rules vmalert evaluates against VictoriaLogs' /select/logsql/stats_query endpoints (LogsQL, not PromQL).
|
||||
groups:
|
||||
- name: logs
|
||||
interval: 2m
|
||||
type: vlogs
|
||||
rules:
|
||||
- alert: SweepFailing
|
||||
# normalize-sweep writes event=failed and leaves a .normalize-failed.log beside the file.
|
||||
expr: 'component:=sweep level:=error event:=failed | stats count() as hits'
|
||||
for: 1m
|
||||
labels: {severity: warning}
|
||||
annotations:
|
||||
summary: "the normalize sweep failed {{ $value }} time(s) in the last 2m"
|
||||
detail: "A recording or clip did not convert. Look for *.normalize-failed.log under /srv/media."
|
||||
- alert: PublishDenied
|
||||
# A few are normal (expired token, wrong prefix). A burst means a streamer is locked out.
|
||||
expr: 'component:=dumpd event:=publish_deny | stats count() as hits'
|
||||
for: 5m
|
||||
labels: {severity: warning}
|
||||
annotations: {summary: "{{ $value }} publish denials in 2m — a streamer may be unable to go live"}
|
||||
- alert: BotDeployFailed
|
||||
expr: 'component:=dumpd event:=bot_deploy_exit level:=error | stats count() as hits'
|
||||
labels: {severity: warning}
|
||||
annotations: {summary: "a Discord bot release failed to install"}
|
||||
- alert: ServiceErrors
|
||||
expr: 'level:=error | stats by (service) count() as hits'
|
||||
for: 5m
|
||||
labels: {severity: warning}
|
||||
annotations: {summary: "{{ $labels.service }} logged {{ $value }} errors in 2m"}
|
||||
- alert: CertificateTrouble
|
||||
expr: 'service:=caddy _msg:"obtain" _msg:"error" | stats count() as hits'
|
||||
labels: {severity: warning}
|
||||
annotations: {summary: "Caddy could not obtain or renew a certificate"}
|
||||
Reference in New Issue
Block a user