use crate::stats::Stats;
use axum::{
extract::State,
response::{Html, IntoResponse},
routing::get,
Json, Router,
};
use log::info;
#[derive(Clone)]
pub struct DashboardState {
pub stats: Stats,
}
pub fn create_dashboard_router(stats: Stats) -> Router {
let state = DashboardState { stats };
Router::new()
.route("/", get(serve_dashboard))
.route("/stats", get(get_stats))
.with_state(state)
}
async fn serve_dashboard(State(_state): State<DashboardState>) -> impl IntoResponse {
Html(include_str!("dashboard.html"))
}
async fn get_stats(State(state): State<DashboardState>) -> impl IntoResponse {
let snapshot = state.stats.snapshot().await;
Json(snapshot)
}
pub async fn run_dashboard(listen_addr: &str, stats: Stats) {
let app = create_dashboard_router(stats);
let listener = match tokio::net::TcpListener::bind(listen_addr).await {
Ok(l) => l,
Err(e) => {
log::error!("Failed to bind dashboard to {}: {}", listen_addr, e);
return;
}
};
info!("Dashboard listening on {}", listen_addr);
if let Err(e) = axum::serve(listener, app).await {
log::error!("Dashboard server error: {}", e);
}
}