# ============================================================================= # DESIGN-REFERENCE RULE SET — NOT LOADED BY ANY ALERTMANAGER TODAY. # ============================================================================= # This file is reference/design config. It is NOT wired into any running # alerting pipeline: # - vmalert (pilot/dev) loads ONLY ops/vmalert/rules/*.yaml # - prod CRDs live ONLY in infra/k8s/prom/prometheus-rules/*.yaml # Nothing mounts or imports tidal/docs/ops/prometheus-alerts.yaml. # Do not read these as live pager rules. # # Provenance: every metric referenced below (tidaldb_health_ok, # tidaldb_checkpoint_age_seconds, tidaldb_checkpoint_failures_total, # tidaldb_wal_lag_bytes, tidaldb_signal_hot_entries, tidaldb_degradation_level, # tidaldb_active_sessions, tidaldb_rate_limited_total, # tidaldb_tantivy_segment_count, tidaldb_retrieve_latency_us_bucket, # tidaldb_search_latency_us_bucket) IS really emitted today by # tidal/src/db/metrics/mod.rs. So these rules are promotable — they # are not orphaned against phantom metrics. # # Promotion path (the right long-term fix — do it deliberately, do NOT # hand-copy these as live pager rules without the steps below): # 1. Add a vmalert rule file: ops/vmalert/rules/tidaldb.yaml, translating # each rule and stamping the canonical labels every routed rule carries — # severity + capability + surface (+ optional component). Map per the # canonical severity taxonomy in ops/alerting.md: # labels {severity: critical} = pager class (TidalDBDown only here), # {severity: warning} = non-paging / business-hours, # {severity: info} = pure-FYI. # Add capability: tidaldb and a surface label per rule, and a # runbook_url annotation: # https://github.com/orchard9/tidaldb/blob/main/tidal/docs/runbooks//.md # 2. Add the prod CRD twin: infra/k8s/prom/prometheus-rules/tidaldb.yaml, # kept byte-aligned in expr/threshold with the vmalert file. # 3. Verify the alerts fire against real metrics (scrape tidaldb, force a # degraded state) before declaring them on-call-ready. # Until steps 1–3 land, this file stays a design reference only. # ============================================================================= groups: - name: tidaldb interval: 30s rules: - alert: TidalDBDown expr: tidaldb_health_ok == 0 for: 1m labels: { severity: critical } annotations: summary: "tidalDB is unhealthy" description: "tidaldb_health_ok is 0 — database is unhealthy or shut down." - alert: TidalDBCheckpointStale expr: tidaldb_checkpoint_age_seconds > 300 for: 2m labels: { severity: warning } annotations: summary: "Signal checkpoint not running" description: "{{ $value }}s since last checkpoint (threshold: 300s). Signal durability at risk." - alert: TidalDBCheckpointFailures expr: increase(tidaldb_checkpoint_failures_total[5m]) > 0 labels: { severity: warning } annotations: summary: "Signal checkpoint failures detected" description: "Checkpoint failures in last 5m. Check disk space and storage errors." - alert: TidalDBWALDiskPressure expr: tidaldb_wal_lag_bytes > 1000000000 for: 5m labels: { severity: warning } annotations: summary: "WAL disk usage exceeds 1GB" description: "{{ $value | humanize1024 }}B of WAL uncompacted. Compaction may be stuck." - alert: TidalDBSignalBacklog expr: tidaldb_signal_hot_entries > 4000000 for: 5m labels: { severity: warning } annotations: summary: "Signal ledger over 80% of capacity" description: "{{ $value }} hot entries (threshold: 4M / 80% of 5M budget)." - alert: TidalDBDegradedRanking expr: tidaldb_degradation_level > 0 for: 2m labels: { severity: warning } annotations: summary: "Ranking quality degraded" description: "Degradation level {{ $value }} active. Scale up or reduce load." - alert: TidalDBSessionLeak # tidaldb_active_sessions is a GAUGE, so rate()/increase() are invalid # (those operators only count counter resets). deriv() fits a least-squares # slope over the window and is the gauge-correct way to detect sustained # growth: > 0.03 sessions/sec is ~> 9 new sessions over a 5m window. expr: deriv(tidaldb_active_sessions[5m]) > 0.03 and tidaldb_active_sessions > 100 for: 5m labels: { severity: warning } annotations: summary: "Active session count growing steadily" description: "{{ $value }} active sessions and trending up (deriv > 0.03/s). Agents may not be closing sessions." - alert: TidalDBHighRateLimiting expr: rate(tidaldb_rate_limited_total[5m]) > 100 for: 5m labels: { severity: info } annotations: summary: "Sustained rate limiting" description: "{{ $value }}/s rate-limited writes. Review agent rate limit config." - alert: TidalDBTantivySegmentBloat expr: tidaldb_tantivy_segment_count > 30 for: 10m labels: { severity: warning } annotations: summary: "Tantivy segment count elevated" description: "{{ $value }} segments (threshold: 30). Text syncer may be stalled." - alert: TidalDBSlowRetrieve expr: histogram_quantile(0.95, rate(tidaldb_retrieve_latency_us_bucket[5m])) > 500000 for: 5m labels: { severity: warning } annotations: summary: "Retrieve p95 latency exceeds 500ms" description: "p95 retrieve latency is {{ $value | humanizeDuration }}. Check signal ledger load and degradation level." - alert: TidalDBSlowSearch expr: histogram_quantile(0.95, rate(tidaldb_search_latency_us_bucket[5m])) > 1000000 for: 5m labels: { severity: warning } annotations: summary: "Search p95 latency exceeds 1s" description: "p95 search latency is {{ $value | humanizeDuration }}. Check Tantivy segment count and ANN index health."