hashiverse_server_lib/server/stats/
system_stats.rs1use sysinfo::{Disks, LoadAvg, System};
2
3pub fn system_stats_subtree() -> serde_json::Value {
13 let (memory_total_bytes, memory_free_bytes) = match System::new() {
14 Ok(mut system) => {
15 system.refresh_memory();
16 (system.total_memory(), system.available_memory())
17 }
18 Err(_) => (0, 0),
19 };
20
21 let mut disk_total_bytes: u64 = 0;
22 let mut disk_free_bytes: u64 = 0;
23 if let Ok(disks) = Disks::new_with_refreshed_list() {
24 for disk in &disks {
25 disk_total_bytes = disk_total_bytes.saturating_add(disk.total_space());
26 disk_free_bytes = disk_free_bytes.saturating_add(disk.available_space());
27 }
28 }
29
30 let load = System::load_average().unwrap_or(LoadAvg { one: 0.0, five: 0.0, fifteen: 0.0 });
31
32 serde_json::json!({
33 "memory_total_bytes": memory_total_bytes,
34 "memory_free_bytes": memory_free_bytes,
35 "disk_total_bytes": disk_total_bytes,
36 "disk_free_bytes": disk_free_bytes,
37 "load_1m": load.one,
38 "load_5m": load.five,
39 "load_15m": load.fifteen,
40 })
41}
42
43#[cfg(test)]
44mod tests {
45 use super::system_stats_subtree;
46
47 #[test]
48 fn system_stats_subtree_has_all_numeric_fields() {
49 let system_stats = system_stats_subtree();
50 for field in ["memory_total_bytes", "memory_free_bytes", "disk_total_bytes", "disk_free_bytes", "load_1m", "load_5m", "load_15m"] {
51 assert!(system_stats[field].is_number(), "field {} missing or not numeric: {}", field, system_stats);
52 }
53 assert!(system_stats["memory_free_bytes"].as_u64().unwrap() <= system_stats["memory_total_bytes"].as_u64().unwrap(), "free memory exceeds total: {}", system_stats);
56 assert!(system_stats["disk_free_bytes"].as_u64().unwrap() <= system_stats["disk_total_bytes"].as_u64().unwrap(), "free disk exceeds total: {}", system_stats);
57 }
58}