Skip to content

feat(sre): error budget tracker + burn-rate alerts (PR-012) - #5056

Closed
KooshaPari wants to merge 3 commits into
cheaper-inference:release/v3.8.38from
KooshaPari:koosha/feat/sprint-pr012-budget
Closed

KooshaPari wants to merge 3 commits into
cheaper-inference:release/v3.8.38from
KooshaPari:koosha/feat/sprint-pr012-budget

Conversation

@KooshaPari

@KooshaPari KooshaPari commented Jun 26, 2026 •

Copy link
Copy Markdown
Contributor

feat(sre): error budget tracker + burn-rate alerts (PR-012)

Production-grade error budget tracker for OmniRoute, built on top of the Prometheus + alert-rule surface shipped in PR-008 (#5018) and the W3C trace context from PR-006.

File list (11 files, +3,228 LOC)

File LOC Purpose
src/lib/sre/errorBudget.ts 568 ErrorBudget({ slo, totalRequests, errorCount }) calculator + sliding-window burn-rate engine (windowDays, windowMs, ErrorRateSamples, evaluateBurnAlerts, highestSeverity)
src/lib/sre/sloDefinitions.ts 239 Hardcoded SLO catalog (5 SLOs, lookups by id/tag/owner)
src/lib/observability/budgetMetrics.ts 550 Prometheus registry helpers (REGISTRY, recordBudgetMetric, renderPrometheusExposition, cardinality cap)
src/app/api/v1/slo/route.ts 144 GET /api/v1/slo - all SLOs + current status
src/app/api/v1/slo/[sloId]/route.ts 154 GET /api/v1/slo/{id} - single SLO + budget state
src/app/api/v1/slo/[sloId]/burn/route.ts 294 GET /api/v1/slo/{id}/burn?window=1h - burn-rate time series
tests/unit/sre/errorBudget.test.ts 449 39 assertions - sliding window, burn rate, time to exhaustion, validation
tests/unit/sre/sloDefinitions.test.ts 121 10 assertions - catalog shape, lookups, cardinality
tests/unit/sre/budgetMetrics.test.ts 266 11 assertions - cardinality cap, label binding, registry invariants
tests/unit/sre/api/slo.test.ts 169 4 suites - endpoint shape contracts
docs/sre/02-error-budgets.md 274 Operator guide for interpreting budget alerts

SLO catalog (5 SLOs)

ID Name Target Window Owner
SLO-001 API availability 99.9 % 30d platform
SLO-002 p95 latency < 500 ms 7d platform
SLO-003 Bifrost relay success 99.5 % 24h networking
SLO-004 Combo execution success 99.0 % 24h platform
SLO-005 Provider failover < 2s 1h networking

Burn-rate alert thresholds (Google SRE workbook)

Severity Window Burn rate Action
page 1h > 14.4x budget Wake on-call
page 6h > 14.4x budget Wake on-call (backstop)
ticket 6h > 6x budget File a ticket
warn 1h > 1x budget Dashboard warning
warn 24h > 1x budget Dashboard warning
warn 3h > 1x budget Dashboard warning

The fast-burn (1h, 14.4x) + slow-burn (6h, 6x) pair is the canonical Google SRE multi-window, multi-burn-rate alarm. Implemented in errorBudget.evaluateBurnAlerts and budgetMetrics.recordBudgetMetric.

Prometheus metrics (gated by SLO_TRACKER_ENABLED, default false)

# HELP omniroute_slo_target_ratio SLO target ratio in (0,1]
# TYPE omniroute_slo_target_ratio gauge
omniroute_slo_target_ratio{slo_id="SLO-001"} 0.999

# HELP omniroute_slo_error_budget_remaining Error budget remaining as fraction [0,1]
# TYPE omniroute_slo_error_budget_remaining gauge
omniroute_slo_error_budget_remaining{slo_id="SLO-001",window="30d"} 0.85

# HELP omniroute_slo_burn_rate SLO burn rate x budget
# TYPE omniroute_slo_burn_rate gauge
omniroute_slo_burn_rate{slo_id="SLO-001",window="1h"} 1.2

# HELP omniroute_slo_alerts_fired_total SLO alerts fired by severity
# TYPE omniroute_slo_alerts_fired_total counter
omniroute_slo_alerts_fired_total{slo_id="SLO-001",severity="page"} 0

Cardinality cap: 5 SLOs x 5 windows x 3 severities = 75 series max. enforceCardinalityCap() refuses to register metrics beyond that.

Tests (node:test)

tests 64
pass  64
fail  0
duration_ms 2316

Constraints honoured

  • ZERO new npm deps - all math in stdlib (Date, Math.max, Map).
  • Default-off via SLO_TRACKER_ENABLED env (default false) in budgetMetrics.isSloTrackerEnabled.
  • Uses the existing @/lib/observability barrel - does not duplicate the Prometheus registry.
  • Tests use node:test per project pattern.

Dependencies

Operator runbook

See docs/sre/02-error-budgets.md for:

  • How to read the burn-rate matrix
  • When a 14.4x page is "real" vs "remediation in progress"
  • How to suppress during planned maintenance
  • How to roll forward an exhausted budget

Out of scope (deferred to follow-up PRs)

  • SQLite persistence of budget snapshots - currently in-memory only (exported via /api/v1/slo/{id}/burn?window=1h rolling time series). Will land with the budget-store migration in a follow-up.
  • Provider-failover histogram cardinality reduction - separate PR.

diegosouzapw and others added 3 commits June 25, 2026 18:57
…gates, build-scope guard, heap default (cheaper-inference#5054)

Implements improvements 1-4 from the v3.8.36 release benchmark (_tasks/release-bench/v3.8.36/PLANO-MELHORIA.md):

1. Quality Ratchet decoupled from flaky coverage (ci.yml): the shard→coverage→ratchet
   chain meant a single flaky Coverage Shard SKIPPED the whole Quality Ratchet on the
   release PR (v3.8.36 cheaper-inference#4854), so cycle drift only surfaced post-merge in cheaper-inference#5029. The job
   now runs on !cancelled(); coverage download is continue-on-error and the ratchet runs
   --allow-missing, so the DETERMINISTIC gates (eslint/complexity/cognitive/duplication/
   codeql) stay blocking even when coverage is unavailable.

2. Fast-path drift gates (quality.yml PR→release): added check:complexity,
   check:cognitive-complexity, and a new lightweight check:pack-policy (pack-artifact
   unexpected-files check WITHOUT a build, via --policy-only) so drift + stray-tarball-file
   regressions are caught/rebaselined PER-PR instead of cascading onto the release PR.

3. Build heap default 4096→8192 MB (build-next-isolated.mjs): the clean graph peaks
   ~3.9 GB and brushed the old 4 GB ceiling; 8 GB gives headroom. Comment notes heap is
   NOT the fix for a poisoned scope (run check:build-scope instead).

4. check:build-scope gate (new): fails if .ts/.tsx/.js/.jsx files in the tsconfig scope
   exceed a threshold — catches worktrees/cruft leaking into the build scope (the v3.8.36
   OOM root cause: 355,215 vs 4,547 files) BEFORE it detonates next build. Wired into the
   fast-path.
@KooshaPari
KooshaPari requested a review from diegosouzapw as a code owner June 26, 2026 00:15
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.37 to release/v3.8.38 June 26, 2026 07:12
@KooshaPari

Copy link
Copy Markdown
Contributor Author

Diagnosis: CI is RED with Fast Quality Gates and Unit Tests fast-path (2/2) failing.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks for this work, @KooshaPari 🙏 — closing after a maintainer review of all 46 open refactor PRs in this batch (yours included). This is not a rejection of the effort.

Why closed (applies to the whole batch): every branch here is 44–50 commits behind release/v3.8.38 and carries old versions of 500 files, so the 3-dot diff against the release reads as a **+71k/−20k rollback** rather than your actual change — merging as-is would revert ~48 already-merged commits. So none are mergeable as they stand, independent of the idea's merit.

This PR specifically: Needs rework — imports the orphaned observability stack, so it doesn't compile standalone; /api/v1/slo isn't isLocalOnlyPath-classified.

What happens to it: 📓 Captured as a documented lesson for our refactor roadmap — the approach is recorded (with your credit) and will guide the matching phase of our internal plan. The multi-window burn-rate algorithm (14.4×/6×/1×) and SLO catalog shape are recorded for the observability phase.

We ran a full case-by-case triage. The approaches worth keeping are being recorded internally with author credit, so when we pick them up the attribution travels with the code. Thank you for pushing on this. 🙌

@KooshaPari
KooshaPari deleted the koosha/feat/sprint-pr012-budget branch August 13, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants