This commit is contained in:
2026-05-16 17:57:54 +02:00
parent 1a2ec26f27
commit b2cefb7d66
55 changed files with 1654 additions and 334 deletions
+26 -12
View File
@@ -27,6 +27,8 @@ use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use crate::metrics::{Metrics, MetricsSnapshot};
// ── Compteurs ────────────────────────────────────────────────────────────────
/// Compteurs atomiques du serveur UDP.
@@ -94,6 +96,7 @@ impl UdpMetrics {
/// Prend un instantané cohérent de tous les compteurs.
pub fn snapshot(&self) -> UdpMetricsSnapshot {
UdpMetricsSnapshot {
taken_at: Instant::now(),
packets_received: self.packets_received.load(Ordering::Relaxed),
bytes_received: self.bytes_received.load(Ordering::Relaxed),
packets_sent: self.packets_sent.load(Ordering::Relaxed),
@@ -105,14 +108,23 @@ impl UdpMetrics {
}
}
impl Metrics for UdpMetrics {
type Snapshot = UdpMetricsSnapshot;
fn snapshot(&self) -> UdpMetricsSnapshot {
self.snapshot()
}
}
// ── Snapshot ─────────────────────────────────────────────────────────────────
/// Lecture cohérente de l'ensemble des compteurs à un instant T.
///
/// Permet de calculer des deltas et des taux entre deux points dans le temps
/// sans bloquer la boucle de routage.
#[derive(Debug, Clone, Copy, Default)]
#[derive(Debug, Clone, Copy)]
pub struct UdpMetricsSnapshot {
pub taken_at: Instant,
pub packets_received: u64,
pub bytes_received: u64,
pub packets_sent: u64,
@@ -124,11 +136,12 @@ pub struct UdpMetricsSnapshot {
impl UdpMetricsSnapshot {
/// Calcule les taux moyens par seconde depuis un snapshot précédent.
///
/// `elapsed` est la durée réelle écoulée entre les deux snapshots.
pub fn rates_since(&self, previous: &Self, elapsed: Duration) -> UdpRates {
// On évite la division par zéro si l'interval est infinitésimal.
let secs = elapsed.as_secs_f64().max(f64::EPSILON);
pub fn rates_since(&self, previous: &Self) -> UdpRates {
let secs = self
.taken_at
.duration_since(previous.taken_at)
.as_secs_f64()
.max(f64::EPSILON);
UdpRates {
packets_received_per_sec: self
@@ -151,6 +164,12 @@ impl UdpMetricsSnapshot {
}
}
impl MetricsSnapshot for UdpMetricsSnapshot {
fn taken_at(&self) -> Instant {
self.taken_at
}
}
// ── Taux ─────────────────────────────────────────────────────────────────────
/// Taux moyens par seconde calculés entre deux [`UdpMetricsSnapshot`].
@@ -194,15 +213,12 @@ pub fn spawn_reporter(metrics: Arc<UdpMetrics>, interval: Duration) {
ticker.tick().await;
let mut prev_snapshot = metrics.snapshot();
let mut prev_instant = Instant::now();
loop {
ticker.tick().await;
let now = Instant::now();
let current = metrics.snapshot();
let elapsed = now.duration_since(prev_instant);
let rates = current.rates_since(&prev_snapshot, elapsed);
let rates = current.rates_since(&prev_snapshot);
tracing::info!(
// ── Cumulatifs ──
@@ -219,12 +235,10 @@ pub fn spawn_reporter(metrics: Arc<UdpMetrics>, interval: Duration) {
pkts_tx_s = format!("{:.1}", rates.packets_sent_per_sec),
bytes_tx_s = format!("{:.0}", rates.bytes_sent_per_sec),
pkts_dropped_s = format!("{:.1}", rates.packets_dropped_per_sec),
interval_ms = elapsed.as_millis(),
"UDP metrics"
);
prev_snapshot = current;
prev_instant = now;
}
});
}
+1 -2
View File
@@ -69,9 +69,8 @@ impl UdpServer {
///
/// Retourne le serveur et un [`broadcast::Sender`] pour déclencher le
/// shutdown gracieux.
pub fn new(network: &NetworkConfig) -> (Self, broadcast::Sender<()>) {
pub fn new(network: &NetworkConfig, metrics: Arc<UdpMetrics>) -> (Self, broadcast::Sender<()>) {
let bind_addr = SocketAddr::new(network.host.into(), network.udp_port);
let metrics = UdpMetrics::new();
let (shutdown_tx, shutdown_rx) = broadcast::channel(1);
(
Self {