use super::{ErrorBudget, Slo, TimeWindow};
use chrono::Duration;
pub struct AvailabilitySlo;
impl AvailabilitySlo {
pub fn three_nines() -> Slo {
Slo {
name: "availability_99.9".to_string(),
description: "99.9% availability over 30 days".to_string(),
target: 99.9,
sli_query: "sum(rate(http_requests_total{status!~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))".to_string(),
time_window: TimeWindow::Rolling(Duration::days(30)),
error_budget: ErrorBudget::from_target(99.9),
}
}
pub fn four_nines() -> Slo {
Slo {
name: "availability_99.99".to_string(),
description: "99.99% availability over 30 days".to_string(),
target: 99.99,
sli_query: "sum(rate(http_requests_total{status!~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))".to_string(),
time_window: TimeWindow::Rolling(Duration::days(30)),
error_budget: ErrorBudget::from_target(99.99),
}
}
}
pub struct LatencySlo;
impl LatencySlo {
pub fn p95_100ms() -> Slo {
Slo {
name: "latency_p95_100ms".to_string(),
description: "95% of requests complete within 100ms".to_string(),
target: 95.0,
sli_query:
"histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) < 0.1"
.to_string(),
time_window: TimeWindow::Rolling(Duration::days(7)),
error_budget: ErrorBudget::from_target(95.0),
}
}
pub fn p99_500ms() -> Slo {
Slo {
name: "latency_p99_500ms".to_string(),
description: "99% of requests complete within 500ms".to_string(),
target: 99.0,
sli_query:
"histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) < 0.5"
.to_string(),
time_window: TimeWindow::Rolling(Duration::days(7)),
error_budget: ErrorBudget::from_target(99.0),
}
}
}
pub struct ThroughputSlo;
impl ThroughputSlo {
pub fn min_rps(rps: f64) -> Slo {
Slo {
name: format!("throughput_min_{}rps", rps),
description: format!("Minimum {} requests per second", rps),
target: 99.0,
sli_query: format!("rate(http_requests_total[1m]) >= {}", rps),
time_window: TimeWindow::Rolling(Duration::hours(24)),
error_budget: ErrorBudget::from_target(99.0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_availability_slos() {
let slo = AvailabilitySlo::three_nines();
assert_eq!(slo.target, 99.9);
let slo = AvailabilitySlo::four_nines();
assert_eq!(slo.target, 99.99);
}
#[test]
fn test_latency_slos() {
let slo = LatencySlo::p95_100ms();
assert_eq!(slo.target, 95.0);
let slo = LatencySlo::p99_500ms();
assert_eq!(slo.target, 99.0);
}
}