use super::DriftBudgetStateProvider;
use crate::handlers::structural_incidents::StructuralIncidents;
use axum::{
extract::{Query, State},
http::StatusCode,
response::Json,
};
use mockforge_foundation::incidents_types::{IncidentQuery, IncidentType};
use serde::Deserialize;
use std::collections::HashMap;
#[derive(Debug, Deserialize)]
pub struct GetMetricsQuery {
pub endpoint: Option<String>,
pub method: Option<String>,
pub workspace_id: Option<String>,
pub days: Option<u32>,
}
pub async fn get_drift_metrics<S: DriftBudgetStateProvider>(
State(state): State<S>,
Query(params): Query<GetMetricsQuery>,
) -> Result<Json<serde_json::Value>, StatusCode> {
let mut query = IncidentQuery {
endpoint: params.endpoint,
method: params.method,
workspace_id: params.workspace_id,
..IncidentQuery::default()
};
if let Some(days) = params.days {
let start_date = chrono::Utc::now()
.checked_sub_signed(chrono::Duration::days(days as i64))
.map(|dt| dt.timestamp())
.unwrap_or(0);
query.start_date = Some(start_date);
}
let incidents = state.incident_manager().query_incidents(query).await;
let total_incidents = incidents.len();
let breaking_changes = incidents
.iter()
.filter(|i| matches!(i.incident_type, IncidentType::BreakingChange))
.count();
let threshold_exceeded = total_incidents - breaking_changes;
let by_severity: HashMap<String, usize> =
incidents.iter().fold(HashMap::new(), |mut acc, inc| {
let key = format!("{:?}", inc.severity).to_lowercase();
*acc.entry(key).or_insert(0) += 1;
acc
});
Ok(Json(serde_json::json!({
"total_incidents": total_incidents,
"breaking_changes": breaking_changes,
"threshold_exceeded": threshold_exceeded,
"by_severity": by_severity,
"incidents": incidents.iter().take(100).collect::<Vec<_>>(), })))
}