Error Budget and Burn Rate
Problem Statement
An SLO of 99.9% availability is really a budget: over the window you are allowed to fail 0.1% of requests. Spending that budget slowly is normal operation; spending it fast is an incident. Compute how much budget a service has left and how fast it is burning.
Background
For an availability SLO over one window:
budget_rate = 1 - slo_target # fraction you may fail
allowed_failures = budget_rate * total_requests
error_rate = failed_requests / total_requests
burn_rate = error_rate / budget_rate
budget_consumed_pct = 100 * failed_requests / allowed_failures
budget_remaining_pct= 100 - budget_consumed_pct
Burn rate is the number that pages someone. A burn rate of 1.0 means you will spend exactly the whole budget over exactly the window — sustainable. A burn rate of 10 means the month's budget is gone in three days, which is why fast-burn alerts fire on burn rate rather than on raw error rate.
Projecting forward at the current burn rate:
hours_to_exhaustion = (budget_remaining_pct / 100) * window_hours / burn_rate
Two clamps: once the budget is exhausted (budget_remaining_pct <= 0), report 0.0 for both the remaining percentage and the hours; and with a burn rate of 0 the budget never runs out, so report the full window_hours.
Your Task
Implement:
def error_budget(slo_target, total_requests, failed_requests, window_hours):
Return a dict with keys "allowed_failures", "burn_rate", "budget_consumed_pct", "budget_remaining_pct", "hours_to_exhaustion", in that order, each rounded to 2 decimal places.
Input Format
- slo_target: float in (0, 1), e.g. 0.999.
- total_requests, failed_requests: ints.
- window_hours: number of hours in the SLO window (720 for 30 days).
Output Format
- A dict of five values, each rounded to 2 decimals.
Sample
print(error_budget(0.999, 2000000, 1200, 720))
Output:
{'allowed_failures': 2000.0, 'burn_rate': 0.6, 'budget_consumed_pct': 60.0, 'budget_remaining_pct': 40.0, 'hours_to_exhaustion': 480.0}
A 99.9% SLO over 2M requests buys 2000 failures. 1200 are spent, so 40% of the budget is left and the service is burning at 0.6x — under 1.0, so it will finish the window inside budget.
Example
print(error_budget(0.999, 2000000, 1200, 720))
{'allowed_failures': 2000.0, 'burn_rate': 0.6, 'budget_consumed_pct': 60.0, 'budget_remaining_pct': 40.0, 'hours_to_exhaustion': 480.0}budget_rate = 1 - 0.999 = 0.001, so 0.001 * 2,000,000 = 2000 failures are allowed. The observed error rate is 1200 / 2,000,000 = 0.0006, giving burn_rate = 0.0006 / 0.001 = 0.6. 1200 of 2000 failures is 60% consumed, 40% left, and projecting 0.4 * 720 / 0.6 gives 480 hours before the budget is gone.
Constraints
- 0 < slo_target < 1
- 1 <= total_requests <= 10**9, 0 <= failed_requests <= total_requests
- window_hours > 0
- When the budget is exhausted, report
budget_remaining_pctandhours_to_exhaustionas 0.0 (never negative) - When burn_rate is 0,
hours_to_exhaustionis the fullwindow_hours - Round every returned value to 2 decimal places