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<RwLock<System>> for thread- safe refreshing. Network I/O left at 0.0 (requires sustained sampling). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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<RwLock<sysinfo::System>>,
|
||||
/// Disk info handle (refreshed on each status query)
|
||||
disks: Arc<RwLock<sysinfo::Disks>>,
|
||||
}
|
||||
|
||||
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<RwLock<sysinfo::System>>,
|
||||
disks: &Arc<RwLock<sysinfo::Disks>>,
|
||||
) -> 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,
|
||||
|
||||
Reference in New Issue
Block a user