use dashmap::DashMap;
use std::sync::Arc;
use std::time::Duration;
use crate::api::common::error::MediaTransportError;
use crate::api::common::stats::{MediaStats, QualityLevel};
use crate::api::server::transport::core::connection::ClientConnection;
#[derive(Debug, Default, Clone)]
pub struct ServerMetrics {
pub active_clients: usize,
pub total_bytes_received: u64,
pub total_bytes_sent: u64,
pub total_packets_received: u64,
pub total_packets_sent: u64,
pub average_jitter_ms: f32,
pub average_packet_loss: f32,
pub total_downstream_bandwidth_bps: u64,
pub total_upstream_bandwidth_bps: u64,
pub average_rtt_ms: Option<f32>,
pub overall_quality: QualityLevel,
pub total_rtcp_packets_received: u64,
pub total_rtcp_packets_sent: u64,
pub uptime: Duration,
}
pub async fn get_server_metrics(
clients: &Arc<DashMap<String, ClientConnection>>,
media_stats: &MediaStats,
server_start_time: Duration,
) -> Result<ServerMetrics, MediaTransportError> {
let mut metrics = ServerMetrics::default();
metrics.active_clients = clients.iter().filter(|e| e.value().connected).count();
let mut total_jitter = 0.0;
let mut total_packet_loss = 0.0;
let mut total_rtt = 0.0;
let mut rtt_count = 0;
for stream in media_stats.streams.values() {
metrics.total_bytes_received += stream.byte_count;
metrics.total_packets_received += stream.packet_count;
total_jitter += stream.jitter_ms;
total_packet_loss += stream.fraction_lost;
if let Some(rtt) = stream.rtt_ms {
total_rtt += rtt;
rtt_count += 1;
}
}
let stream_count = media_stats.streams.len();
if stream_count > 0 {
metrics.average_jitter_ms = total_jitter / stream_count as f32;
metrics.average_packet_loss = total_packet_loss / stream_count as f32 * 100.0;
}
if rtt_count > 0 {
metrics.average_rtt_ms = Some(total_rtt / rtt_count as f32);
}
metrics.total_downstream_bandwidth_bps = media_stats.downstream_bandwidth_bps as u64;
metrics.total_upstream_bandwidth_bps = media_stats.upstream_bandwidth_bps as u64;
metrics.overall_quality = media_stats.quality;
metrics.uptime = server_start_time;
Ok(metrics)
}