use reqwest::Method;
use serde::Deserialize;
use crate::{client::Sendry, error::Error, Page, PaginationParams};
#[derive(Debug, Clone)]
pub struct Status {
client: Sendry,
}
impl Status {
pub(crate) fn new(client: Sendry) -> Self {
Self { client }
}
pub async fn get_current(&self) -> Result<SystemStatus, Error> {
self.client
.request(
self.client
.build::<()>(Method::GET, "/v1/status", &[], None),
)
.await
}
pub async fn get_history(&self, params: PaginationParams) -> Result<Page<Incident>, Error> {
let q = params.to_query();
self.client
.request(
self.client
.build::<()>(Method::GET, "/v1/status/history", &q, None),
)
.await
}
pub async fn get_latency(&self, params: GetLatencyParams) -> Result<LatencyStats, Error> {
let q = params.to_query();
self.client
.request(
self.client
.build::<()>(Method::GET, "/v1/status/latency", &q, None),
)
.await
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct IncidentUpdate {
pub id: String,
pub status: String,
pub message: String,
pub created_at: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AffectedComponent {
pub id: String,
pub name: String,
pub slug: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Incident {
pub id: String,
pub title: String,
pub status: String,
pub impact: String,
pub starts_at: Option<String>,
pub ends_at: Option<String>,
pub resolved_at: Option<String>,
pub created_at: String,
pub updated_at: String,
pub updates: Vec<IncidentUpdate>,
pub affected_components: Vec<AffectedComponent>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct StatusComponent {
pub id: String,
pub name: String,
pub description: Option<String>,
pub group: Option<String>,
pub slug: String,
pub status: String,
pub uptime_90d: f64,
pub sla_target: f64,
pub sla_met: bool,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SlaSummary {
pub target: f64,
pub current_uptime: f64,
pub sla_met: bool,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SystemStatus {
pub status: String,
pub components: Vec<StatusComponent>,
pub active_incidents: Vec<Incident>,
pub sla_summary: SlaSummary,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LatencyHourBucket {
pub hour: String,
pub p50_ms: Option<f64>,
pub p95_ms: Option<f64>,
pub p99_ms: Option<f64>,
pub sample_count: u64,
pub target_met_pct: f64,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LatencyStats {
pub component: String,
pub target_ms: f64,
pub current_p50_ms: Option<f64>,
pub target_met: bool,
pub hourly: Vec<LatencyHourBucket>,
}
#[derive(Debug, Clone, Default)]
pub struct GetLatencyParams {
pub component: Option<String>,
pub hours: Option<u32>,
}
impl GetLatencyParams {
fn to_query(&self) -> Vec<(&'static str, String)> {
let mut q = Vec::new();
if let Some(v) = &self.component {
q.push(("component", v.clone()));
}
if let Some(v) = self.hours {
q.push(("hours", v.to_string()));
}
q
}
}