1use sysinfo::{CpuExt, DiskExt, NetworkExt, NetworksExt, System, SystemExt};
2
3#[derive(Debug, Clone, PartialEq)]
5pub struct CpuInfo {
6 pub name: String,
7 pub usage: f32,
8}
9
10#[derive(Debug, Clone, PartialEq)]
12pub struct DiskInfo {
13 pub name: String,
14 pub total_space: u64,
15 pub available_space: u64,
16}
17
18#[derive(Debug, Clone, PartialEq)]
20pub struct NetworkInfo {
21 pub interface: String,
22 pub received: u64,
23 pub transmitted: u64,
24}
25
26#[derive(Debug, Clone, PartialEq)]
28pub struct SystemInfo {
29 pub uptime: u64,
30 pub total_memory: u64,
31 pub used_memory: u64,
32 pub cpus: Vec<CpuInfo>,
33 pub disks: Vec<DiskInfo>,
34 pub networks: Vec<NetworkInfo>,
35}
36
37pub fn gather() -> SystemInfo {
39 let mut sys = System::new_all();
40 sys.refresh_all();
41
42 let cpus = sys
43 .cpus()
44 .iter()
45 .map(|c| CpuInfo {
46 name: c.name().to_string(),
47 usage: c.cpu_usage(),
48 })
49 .collect();
50
51 let disks = sys
52 .disks()
53 .iter()
54 .map(|d| DiskInfo {
55 name: d.name().to_string_lossy().into_owned(),
56 total_space: d.total_space(),
57 available_space: d.available_space(),
58 })
59 .collect();
60
61 let networks = sys
62 .networks()
63 .iter()
64 .map(|(iface, data)| NetworkInfo {
65 interface: iface.to_string(),
66 received: data.received(),
67 transmitted: data.transmitted(),
68 })
69 .collect();
70
71 SystemInfo {
72 uptime: sys.uptime(),
73 total_memory: sys.total_memory(),
74 used_memory: sys.used_memory(),
75 cpus,
76 disks,
77 networks,
78 }
79}
80
81pub fn format_plain(info: &SystemInfo) -> String {
83 let mut out = String::new();
84 out.push_str(&format!("Uptime: {}s\n", info.uptime));
85 out.push_str(&format!(
86 "Memory: {}/{} KB\n",
87 info.used_memory, info.total_memory
88 ));
89
90 out.push_str("CPU usage:\n");
91 for cpu in &info.cpus {
92 out.push_str(&format!(" - {}: {:.1}%\n", cpu.name, cpu.usage));
93 }
94
95 out.push_str("Disks:\n");
96 for disk in &info.disks {
97 out.push_str(&format!(
98 " - {}: {} / {} bytes free\n",
99 disk.name, disk.available_space, disk.total_space
100 ));
101 }
102
103 out.push_str("Networks:\n");
104 for net in &info.networks {
105 out.push_str(&format!(
106 " - {}: rx {} bytes tx {} bytes\n",
107 net.interface, net.received, net.transmitted
108 ));
109 }
110
111 out
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_format_plain() {
120 let info = SystemInfo {
121 uptime: 10,
122 total_memory: 1000,
123 used_memory: 500,
124 cpus: vec![CpuInfo {
125 name: "cpu0".into(),
126 usage: 20.0,
127 }],
128 disks: vec![DiskInfo {
129 name: "disk".into(),
130 total_space: 2000,
131 available_space: 1000,
132 }],
133 networks: vec![NetworkInfo {
134 interface: "eth0".into(),
135 received: 100,
136 transmitted: 200,
137 }],
138 };
139 let out = format_plain(&info);
140 assert!(out.contains("Uptime: 10s"));
141 assert!(out.contains("Memory: 500/1000"));
142 assert!(out.contains("cpu0"));
143 assert!(out.contains("disk"));
144 assert!(out.contains("eth0"));
145 }
146}