use sysinfo::System;
use crate::metrics::types::SystemMetrics;
use chrono::Utc;
pub struct MetricsCollector {
sys: System,
}
impl MetricsCollector {
pub fn new() -> Self {
Self {
sys: System::new_all(),
}
}
pub fn collect(&mut self) -> SystemMetrics {
self.sys.refresh_all();
let mem_free_mb = self.sys.free_memory() as f64 / 1024.0 / 1024.0;
let mem_total_mb = self.sys.total_memory() as f64 / 1024.0 / 1024.0;
let swap_free_mb = self.sys.free_swap() as f64 / 1024.0 / 1024.0;
let swap_total_mb = self.sys.total_swap() as f64 / 1024.0 / 1024.0;
let load_avg = System::load_average();
let cpu_load_1 = load_avg.one;
let cpu_load_5 = load_avg.five;
let cpu_load_15 = load_avg.fifteen;
let (disk_free_gb, disk_total_gb) = Self::get_disk_space();
SystemMetrics {
timestamp: Utc::now().timestamp(),
mem_free_mb,
mem_total_mb,
swap_free_mb,
swap_total_mb,
cpu_load_1,
cpu_load_5,
cpu_load_15,
disk_free_gb,
disk_total_gb,
}
}
fn get_disk_space() -> (f64, f64) {
let output = std::process::Command::new("df")
.args(["-B1", "/"])
.output();
if let Ok(out) = output {
if let Ok(stdout) = String::from_utf8(out.stdout) {
let lines: Vec<&str> = stdout.lines().collect();
if lines.len() >= 2 {
let parts: Vec<&str> = lines[1].split_whitespace().collect();
if parts.len() >= 4 {
let total = parts[1].parse::<u64>().unwrap_or(0) as f64 / 1024.0 / 1024.0 / 1024.0;
let free = parts[3].parse::<u64>().unwrap_or(0) as f64 / 1024.0 / 1024.0 / 1024.0;
return (free, total);
}
}
}
}
(0.0, 0.0)
}
}