use axum::{extract::State, http::header, response::IntoResponse}; use sqlx::SqlitePool; use crate::error::Result; /// Exposition des métriques au format Prometheus text (scraping Grafana/Prometheus). /// /// Endpoint : GET /metrics /// Compatible avec prometheus.yml : /// scrape_configs: /// - job_name: sentinelmesh /// static_configs: /// - targets: ['sentinelmesh:8080'] pub async fn metrics(State(db): State) -> Result { let rows = sqlx::query_as::<_, ( String, String, Option, Option, Option, Option, Option, Option, )>( "SELECT a.hostname, m.agent_id, m.cpu_percent, m.ram_percent, m.disk_percent, m.temperature_c, m.net_rx_bps, m.net_tx_bps FROM metrics m JOIN agents a ON a.id = m.agent_id", ) .fetch_all(&db) .await?; let mut out = String::with_capacity(2048); macro_rules! gauge { ($name:expr, $help:expr, $type:expr) => { out.push_str(&format!( "# HELP sentinelmesh_{} {}\n# TYPE sentinelmesh_{} {}\n", $name, $help, $name, $type )); }; } gauge!("cpu_percent", "Utilisation CPU en pourcentage", "gauge"); gauge!("ram_percent", "Utilisation RAM en pourcentage", "gauge"); gauge!("disk_percent", "Utilisation disque en pourcentage", "gauge"); gauge!("temperature_c", "Température CPU/système en Celsius", "gauge"); gauge!("net_rx_bps", "Débit réseau entrant en octets/s", "gauge"); gauge!("net_tx_bps", "Débit réseau sortant en octets/s", "gauge"); for (hostname, agent_id, cpu, ram, disk, temp, rx, tx) in &rows { let lbl = format!("agent=\"{agent_id}\",hostname=\"{hostname}\""); let push = |name: &str, val: f64| format!("sentinelmesh_{name}{{{lbl}}} {val:.2}\n"); if let Some(v) = cpu { out.push_str(&push("cpu_percent", *v)); } if let Some(v) = ram { out.push_str(&push("ram_percent", *v)); } if let Some(v) = disk { out.push_str(&push("disk_percent", *v)); } if let Some(v) = temp { out.push_str(&push("temperature_c", *v)); } if let Some(v) = rx { out.push_str(&push("net_rx_bps", *v as f64)); } if let Some(v) = tx { out.push_str(&push("net_tx_bps", *v as f64)); } } Ok(( [(header::CONTENT_TYPE, "text/plain; version=0.0.4; charset=utf-8")], out, )) }