diff --git a/agent/Cargo.lock b/agent/Cargo.lock index 4ce8518..6b2b585 100644 --- a/agent/Cargo.lock +++ b/agent/Cargo.lock @@ -250,6 +250,7 @@ dependencies = [ name = "nanometrics-agent" version = "0.1.0" dependencies = [ + "libc", "rumqttc", "serde", "serde_json", diff --git a/agent/Cargo.toml b/agent/Cargo.toml index 67d25e7..75a34e4 100644 --- a/agent/Cargo.toml +++ b/agent/Cargo.toml @@ -19,6 +19,7 @@ codegen-units = 1 [dependencies] sysinfo = { version = "0.30", default-features = false } +libc = "0.2" serde = { version = "1", features = ["derive"] } serde_json = "1" toml = "0.8" diff --git a/agent/src/main.rs b/agent/src/main.rs index aaa641c..8f4bbb3 100644 --- a/agent/src/main.rs +++ b/agent/src/main.rs @@ -1,5 +1,5 @@ use nanometrics_agent::{config, metrics, payload, transport}; -use sysinfo::{Components, Disks, Networks, System}; +use sysinfo::{Components, Networks, System}; use std::time::{Duration, Instant}; use std::sync::mpsc; @@ -34,7 +34,6 @@ fn main() { let mut sys = System::new(); let mut networks = Networks::new_with_refreshed_list(); - let mut disks = Disks::new_with_refreshed_list(); let mut components = Components::new_with_refreshed_list(); let udp_sender = if cfg.protocols.udp.enabled { @@ -102,9 +101,8 @@ fn main() { } if first_slow || now.duration_since(last_slow).as_secs() >= 60 { - disks.refresh(); if cfg.metrics.disk.udp || cfg.metrics.disk.mqtt { - let (used, free, total) = metrics::disk::get(&disks); + let (used, free, total) = metrics::disk::get(); m.hdd_used = Some(used); m.hdd_free = Some(free); m.hdd_total = Some(total); diff --git a/agent/src/metrics/disk.rs b/agent/src/metrics/disk.rs index 2e5292f..8bc9dd3 100644 --- a/agent/src/metrics/disk.rs +++ b/agent/src/metrics/disk.rs @@ -1,34 +1,36 @@ -use sysinfo::Disks; +use std::mem::MaybeUninit; -pub fn get(disks: &Disks) -> (u64, u64, u64) { - for disk in disks.list() { - let mount = disk.mount_point().to_string_lossy(); - if mount == "/" { - let total = disk.total_space(); - let free = disk.available_space(); - let used = total.saturating_sub(free); - return (used, free, total); - } +/// Retourne (used, free, total) en octets pour le système de fichiers racine "/". +/// Utilise statvfs() directement pour correspondre exactement aux chiffres de `df` : +/// - total = f_blocks × f_frsize +/// - used = (f_blocks − f_bfree) × f_frsize (blocs effectivement écrits) +/// - free = f_bavail × f_frsize (disponible pour utilisateurs non-root) +pub fn get() -> (u64, u64, u64) { + let path = b"/\0"; + let mut stat = MaybeUninit::::uninit(); + let ret = unsafe { libc::statvfs(path.as_ptr() as *const libc::c_char, stat.as_mut_ptr()) }; + if ret != 0 { + return (0, 0, 0); } - if let Some(disk) = disks.list().first() { - let total = disk.total_space(); - let free = disk.available_space(); - return (total.saturating_sub(free), free, total); - } - (0, 0, 0) + let stat = unsafe { stat.assume_init() }; + let bsize = stat.f_frsize as u64; + let total = stat.f_blocks.saturating_mul(bsize); + let used = stat.f_blocks.saturating_sub(stat.f_bfree).saturating_mul(bsize); + let free = stat.f_bavail.saturating_mul(bsize); + (used, free, total) } #[cfg(test)] mod tests { use super::*; - use sysinfo::Disks; #[test] fn test_disk_coherent() { - let disks = Disks::new_with_refreshed_list(); - let (used, free, total) = get(&disks); + let (used, free, total) = get(); + eprintln!("résultat statvfs : used={used} free={free} total={total}"); if total > 0 { - assert!(used + free <= total + 1024, "used + free > total"); + assert!(used + free <= total + 1024 * 1024, "used + free > total"); + assert!(total > 0, "total doit être > 0"); } } }