From 55b4ece54caeaf846cf222c3da4d1ef838d01127 Mon Sep 17 00:00:00 2001 From: dev-dami Date: Mon, 2 Feb 2026 04:24:28 +0100 Subject: [PATCH 1/4] feat(modules): add network interface traffic collector NetworkCollector uses sysinfo's Networks::new_with_refreshed_list() to enumerate all network interfaces and sum total bytes received and transmitted. Reports per-interface breakdown as a List metric with human-readable byte formatting. Useful for spotting which interface is handling traffic and rough bandwidth consumption. --- src/modules/network.rs | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/modules/network.rs diff --git a/src/modules/network.rs b/src/modules/network.rs new file mode 100644 index 0000000..caa23c2 --- /dev/null +++ b/src/modules/network.rs @@ -0,0 +1,60 @@ +use crate::core::{MetricCollector, MetricData, MetricValue}; +use sysinfo::Networks; +use std::collections::HashMap; + +pub struct NetworkCollector; + +impl NetworkCollector { + pub fn new() -> Self { + NetworkCollector + } +} + +impl MetricCollector for NetworkCollector { + fn collect(&self) -> Result> { + let networks = Networks::new_with_refreshed_list(); + + let mut total_rx: u64 = 0; + let mut total_tx: u64 = 0; + let mut iface_count: i64 = 0; + let mut iface_details: Vec = Vec::new(); + + for (name, data) in networks.iter() { + let rx = data.total_received(); + let tx = data.total_transmitted(); + total_rx += rx; + total_tx += tx; + iface_count += 1; + iface_details.push(MetricValue::String( + format!("{}: rx={} tx={}", name, format_bytes(rx), format_bytes(tx)), + )); + } + + let mut metrics = HashMap::new(); + metrics.insert("total_received_bytes".to_string(), MetricValue::Integer(total_rx as i64)); + metrics.insert("total_transmitted_bytes".to_string(), MetricValue::Integer(total_tx as i64)); + metrics.insert("interface_count".to_string(), MetricValue::Integer(iface_count)); + metrics.insert("interfaces".to_string(), MetricValue::List(iface_details)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "network" + } +} + +fn format_bytes(bytes: u64) -> String { + if bytes >= 1_073_741_824 { + format!("{:.2}GB", bytes as f64 / 1_073_741_824.0) + } else if bytes >= 1_048_576 { + format!("{:.2}MB", bytes as f64 / 1_048_576.0) + } else if bytes >= 1024 { + format!("{:.2}KB", bytes as f64 / 1024.0) + } else { + format!("{}B", bytes) + } +} From 29f21de0210e3f34696cf3c2225dab5d51805ba2 Mon Sep 17 00:00:00 2001 From: dev-dami Date: Mon, 2 Feb 2026 04:24:38 +0100 Subject: [PATCH 2/4] feat(modules): add process collector with top-5 by memory and CPU ProcessCollector snapshots all running processes and reports total count, top 5 by memory consumption (name, pid, MB), and top 5 by CPU usage (name, pid, percentage). Gives a quick htop-style summary without needing a separate tool. --- src/modules/process.rs | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/modules/process.rs diff --git a/src/modules/process.rs b/src/modules/process.rs new file mode 100644 index 0000000..f3adce6 --- /dev/null +++ b/src/modules/process.rs @@ -0,0 +1,68 @@ +use crate::core::{MetricCollector, MetricData, MetricValue}; +use sysinfo::{System, RefreshKind, ProcessRefreshKind}; +use std::collections::HashMap; + +pub struct ProcessCollector; + +impl ProcessCollector { + pub fn new() -> Self { + ProcessCollector + } +} + +impl MetricCollector for ProcessCollector { + fn collect(&self) -> Result> { + let sys = System::new_with_specifics( + RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()), + ); + + let processes = sys.processes(); + let total = processes.len() as i64; + + let mut by_memory: Vec<_> = processes.values().collect(); + by_memory.sort_by(|a, b| b.memory().cmp(&a.memory())); + + let top_mem: Vec = by_memory + .iter() + .take(5) + .map(|p| { + MetricValue::String(format!( + "{} (pid {}) — {:.1}MB", + p.name().to_string_lossy(), + p.pid(), + p.memory() as f64 / 1_048_576.0, + )) + }) + .collect(); + + let mut by_cpu: Vec<_> = processes.values().collect(); + by_cpu.sort_by(|a, b| b.cpu_usage().partial_cmp(&a.cpu_usage()).unwrap_or(std::cmp::Ordering::Equal)); + + let top_cpu: Vec = by_cpu + .iter() + .take(5) + .map(|p| { + MetricValue::String(format!( + "{} (pid {}) — {:.1}%", + p.name().to_string_lossy(), + p.pid(), + p.cpu_usage(), + )) + }) + .collect(); + + let mut metrics = HashMap::new(); + metrics.insert("total_processes".to_string(), MetricValue::Integer(total)); + metrics.insert("top_by_memory".to_string(), MetricValue::List(top_mem)); + metrics.insert("top_by_cpu".to_string(), MetricValue::List(top_cpu)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "process" + } +} From 4749550118e19f77bf760cb8a5ba0ebadd1b293c Mon Sep 17 00:00:00 2001 From: dev-dami Date: Mon, 2 Feb 2026 04:24:52 +0100 Subject: [PATCH 3/4] feat(modules): add system info collector with OS, uptime, and load SystemCollector reports OS name, version, kernel version, hostname, CPU architecture, uptime in seconds and human-readable format (Xd Yh Zm), and 1/5/15 minute load averages. Uses sysinfo static methods so it does not need a System instance refresh. Load averages return zeros on Windows which is expected behavior. --- src/modules/system.rs | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/modules/system.rs diff --git a/src/modules/system.rs b/src/modules/system.rs new file mode 100644 index 0000000..d1fd40b --- /dev/null +++ b/src/modules/system.rs @@ -0,0 +1,65 @@ +use crate::core::{MetricCollector, MetricData, MetricValue}; +use sysinfo::System; +use std::collections::HashMap; + +pub struct SystemCollector; + +impl SystemCollector { + pub fn new() -> Self { + SystemCollector + } +} + +impl MetricCollector for SystemCollector { + fn collect(&self) -> Result> { + let mut metrics = HashMap::new(); + + if let Some(name) = System::name() { + metrics.insert("os_name".to_string(), MetricValue::String(name)); + } + if let Some(version) = System::os_version() { + metrics.insert("os_version".to_string(), MetricValue::String(version)); + } + if let Some(kernel) = System::kernel_version() { + metrics.insert("kernel_version".to_string(), MetricValue::String(kernel)); + } + if let Some(host) = System::host_name() { + metrics.insert("hostname".to_string(), MetricValue::String(host)); + } + if let Some(arch) = System::cpu_arch() { + metrics.insert("arch".to_string(), MetricValue::String(arch)); + } + + let uptime_secs = System::uptime(); + metrics.insert("uptime_seconds".to_string(), MetricValue::Integer(uptime_secs as i64)); + metrics.insert("uptime_human".to_string(), MetricValue::String(format_uptime(uptime_secs))); + + let load = System::load_average(); + metrics.insert("load_1m".to_string(), MetricValue::Float(load.one)); + metrics.insert("load_5m".to_string(), MetricValue::Float(load.five)); + metrics.insert("load_15m".to_string(), MetricValue::Float(load.fifteen)); + + Ok(MetricData { + timestamp: std::time::SystemTime::now(), + metrics, + }) + } + + fn name(&self) -> &'static str { + "system" + } +} + +fn format_uptime(secs: u64) -> String { + let days = secs / 86400; + let hours = (secs % 86400) / 3600; + let minutes = (secs % 3600) / 60; + + if days > 0 { + format!("{}d {}h {}m", days, hours, minutes) + } else if hours > 0 { + format!("{}h {}m", hours, minutes) + } else { + format!("{}m", minutes) + } +} From 3c8d2b158d3d7e6198980413463e41a8587e6eee Mon Sep 17 00:00:00 2001 From: dev-dami Date: Mon, 2 Feb 2026 04:25:02 +0100 Subject: [PATCH 4/4] feat(modules): register network, process, and system in mod.rs Exports the three new modules so they can be imported by the engine. --- src/modules/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/mod.rs b/src/modules/mod.rs index dbfd332..c1785ac 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -1,3 +1,6 @@ pub mod cpu; -pub mod memory; pub mod disk; +pub mod memory; +pub mod network; +pub mod process; +pub mod system;