From 9b482b4db242e732f50a92d0f4f6b2e63f22c88d Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Sun, 22 Feb 2026 05:05:58 +0100 Subject: [PATCH] feat(monitoring): wire real CPU/memory/disk metrics via sysinfo Replace hardcoded 0.0 system metrics with live values from sysinfo crate (already in dependencies). Uses Arc> for thread- safe refreshing. Network I/O left at 0.0 (requires sustained sampling). Co-Authored-By: Claude Opus 4.6 --- .../src/services/monitoring.rs | 87 ++++++++++++++++++- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/services/trading_service/src/services/monitoring.rs b/services/trading_service/src/services/monitoring.rs index 39fce49a7..b698c4ae2 100644 --- a/services/trading_service/src/services/monitoring.rs +++ b/services/trading_service/src/services/monitoring.rs @@ -12,7 +12,9 @@ use crate::proto::monitoring::{ SystemStatusEvent, ThroughputMetric, }; use crate::state::{HealthStatus, TradingServiceState}; +use std::sync::Arc; use std::time::Instant; +use tokio::sync::RwLock; use tonic::{Request, Response, Status}; /// Monitoring service implementation @@ -21,18 +23,92 @@ pub struct MonitoringServiceImpl { state: TradingServiceState, /// Tracks when this service instance was started for real uptime reporting started_at: Instant, + /// System info handle for CPU/memory metrics (refreshed on each status query) + sys: Arc>, + /// Disk info handle (refreshed on each status query) + disks: Arc>, } impl MonitoringServiceImpl { /// Create new monitoring service pub fn new(state: TradingServiceState) -> Self { + // Construct with initial refresh so the first CPU reading has a baseline. + let mut sys = sysinfo::System::new(); + sys.refresh_cpu_all(); + sys.refresh_memory(); + Self { state, started_at: Instant::now(), + sys: Arc::new(RwLock::new(sys)), + disks: Arc::new(RwLock::new(sysinfo::Disks::new_with_refreshed_list())), } } } +/// Collected system-level metrics (CPU, memory, disk). +struct LiveSystemMetrics { + cpu_usage_percent: f64, + memory_usage_percent: f64, + disk_usage_percent: f64, + /// Network I/O requires sustained measurement; always 0.0 for now. + network_io_mbps: f64, +} + +/// Collect real system metrics from sysinfo handles. +/// +/// CPU usage is computed as the global average across all cores since the last +/// refresh. Memory and disk are point-in-time snapshots. The function is +/// non-blocking apart from acquiring the `RwLock`. +async fn collect_system_metrics( + sys: &Arc>, + disks: &Arc>, +) -> LiveSystemMetrics { + // --- CPU + Memory -------------------------------------------------- + let (cpu_usage, mem_pct) = { + let mut s = sys.write().await; + // Refresh CPU counters (delta since last refresh). + s.refresh_cpu_all(); + s.refresh_memory(); + + let cpu = s.global_cpu_usage() as f64; // 0-100 across all cores + + let total = s.total_memory(); + let used = s.used_memory(); + let mem = if total > 0 { + (used as f64 / total as f64) * 100.0 + } else { + 0.0 + }; + (cpu, mem) + }; + + // --- Disk ---------------------------------------------------------- + let disk_pct = { + let mut d = disks.write().await; + d.refresh(true); + + let (total_space, available_space) = + d.iter().fold((0u64, 0u64), |(ts, avail), disk| { + (ts + disk.total_space(), avail + disk.available_space()) + }); + if total_space > 0 { + let used_space = total_space.saturating_sub(available_space); + (used_space as f64 / total_space as f64) * 100.0 + } else { + 0.0 + } + }; + + LiveSystemMetrics { + cpu_usage_percent: cpu_usage, + memory_usage_percent: mem_pct, + disk_usage_percent: disk_pct, + // Network I/O measurement requires sustained sampling; leave as 0.0. + network_io_mbps: 0.0, + } +} + #[tonic::async_trait] impl MonitoringService for MonitoringServiceImpl { async fn get_health_check( @@ -152,6 +228,9 @@ impl MonitoringService for MonitoringServiceImpl { } } + // Collect real system metrics (CPU, memory, disk) from sysinfo. + let live = collect_system_metrics(&self.sys, &self.disks).await; + let system_status = SystemStatus { overall_health: overall_health as i32, healthy_services: 3, @@ -159,10 +238,10 @@ impl MonitoringService for MonitoringServiceImpl { critical_issues, system_uptime_seconds: uptime_seconds, system_metrics: Some(SystemMetrics { - cpu_usage_percent: 0.0, // TODO: wire to sysinfo crate - memory_usage_percent: 0.0, // TODO: wire to sysinfo crate - disk_usage_percent: 0.0, // TODO: wire to sysinfo crate - network_io_mbps: 0.0, // TODO: wire to sysinfo crate + cpu_usage_percent: live.cpu_usage_percent, + memory_usage_percent: live.memory_usage_percent, + disk_usage_percent: live.disk_usage_percent, + network_io_mbps: live.network_io_mbps, active_connections: 25, total_requests: 1000, avg_response_time_ms: 2.5,