use std::time::Instant;
use sysinfo::{Networks, ProcessesToUpdate, System};
#[derive(Debug, Clone, Default)]
pub struct HostMetricsSnapshot {
pub disk_read_bytes_sec: u64,
pub disk_write_bytes_sec: u64,
pub net_tx_bytes_sec: u64,
pub net_rx_bytes_sec: u64,
}
pub struct MetricsCollector {
sys: System,
networks: Networks,
last_snapshot: HostMetricsSnapshot,
last_update: Instant,
}
impl Default for MetricsCollector {
fn default() -> Self {
Self::new()
}
}
impl MetricsCollector {
pub fn new() -> Self {
let mut sys = System::new_all();
let mut networks = Networks::new_with_refreshed_list();
sys.refresh_cpu_all();
sys.refresh_memory();
sys.refresh_processes(ProcessesToUpdate::All, true);
networks.refresh();
Self {
sys,
networks,
last_snapshot: HostMetricsSnapshot::default(),
last_update: Instant::now(),
}
}
pub fn refresh(&mut self) -> HostMetricsSnapshot {
let now = Instant::now();
let elapsed = now.duration_since(self.last_update).as_secs_f64();
if elapsed < 0.1 {
return self.last_snapshot.clone();
}
self.networks.refresh();
self.sys.refresh_processes(ProcessesToUpdate::All, true);
let mut total_rx = 0;
let mut total_tx = 0;
for (_interface_name, data) in &self.networks {
total_rx += data.received();
total_tx += data.transmitted();
}
let mut total_disk_read = 0;
let mut total_disk_write = 0;
for process in self.sys.processes().values() {
let disk_usage = process.disk_usage();
total_disk_read += disk_usage.read_bytes;
total_disk_write += disk_usage.written_bytes;
}
let rx_rate = (total_rx as f64 / elapsed) as u64;
let tx_rate = (total_tx as f64 / elapsed) as u64;
let disk_read_rate = (total_disk_read as f64 / elapsed) as u64;
let disk_write_rate = (total_disk_write as f64 / elapsed) as u64;
self.last_snapshot = HostMetricsSnapshot {
disk_read_bytes_sec: disk_read_rate,
disk_write_bytes_sec: disk_write_rate,
net_tx_bytes_sec: tx_rate,
net_rx_bytes_sec: rx_rate,
};
self.last_update = now;
self.last_snapshot.clone()
}
}