Skip to content

Commit 6941ad2

Browse files
authored
Merge pull request #6 from dev-dami/feat/new-modules
feat: add network, process, and system info collectors
2 parents 64d95af + 3c8d2b1 commit 6941ad2

4 files changed

Lines changed: 197 additions & 1 deletion

File tree

src/modules/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
pub mod cpu;
2-
pub mod memory;
32
pub mod disk;
3+
pub mod memory;
4+
pub mod network;
5+
pub mod process;
6+
pub mod system;

src/modules/network.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::core::{MetricCollector, MetricData, MetricValue};
2+
use sysinfo::Networks;
3+
use std::collections::HashMap;
4+
5+
pub struct NetworkCollector;
6+
7+
impl NetworkCollector {
8+
pub fn new() -> Self {
9+
NetworkCollector
10+
}
11+
}
12+
13+
impl MetricCollector for NetworkCollector {
14+
fn collect(&self) -> Result<MetricData, Box<dyn std::error::Error>> {
15+
let networks = Networks::new_with_refreshed_list();
16+
17+
let mut total_rx: u64 = 0;
18+
let mut total_tx: u64 = 0;
19+
let mut iface_count: i64 = 0;
20+
let mut iface_details: Vec<MetricValue> = Vec::new();
21+
22+
for (name, data) in networks.iter() {
23+
let rx = data.total_received();
24+
let tx = data.total_transmitted();
25+
total_rx += rx;
26+
total_tx += tx;
27+
iface_count += 1;
28+
iface_details.push(MetricValue::String(
29+
format!("{}: rx={} tx={}", name, format_bytes(rx), format_bytes(tx)),
30+
));
31+
}
32+
33+
let mut metrics = HashMap::new();
34+
metrics.insert("total_received_bytes".to_string(), MetricValue::Integer(total_rx as i64));
35+
metrics.insert("total_transmitted_bytes".to_string(), MetricValue::Integer(total_tx as i64));
36+
metrics.insert("interface_count".to_string(), MetricValue::Integer(iface_count));
37+
metrics.insert("interfaces".to_string(), MetricValue::List(iface_details));
38+
39+
Ok(MetricData {
40+
timestamp: std::time::SystemTime::now(),
41+
metrics,
42+
})
43+
}
44+
45+
fn name(&self) -> &'static str {
46+
"network"
47+
}
48+
}
49+
50+
fn format_bytes(bytes: u64) -> String {
51+
if bytes >= 1_073_741_824 {
52+
format!("{:.2}GB", bytes as f64 / 1_073_741_824.0)
53+
} else if bytes >= 1_048_576 {
54+
format!("{:.2}MB", bytes as f64 / 1_048_576.0)
55+
} else if bytes >= 1024 {
56+
format!("{:.2}KB", bytes as f64 / 1024.0)
57+
} else {
58+
format!("{}B", bytes)
59+
}
60+
}

src/modules/process.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use crate::core::{MetricCollector, MetricData, MetricValue};
2+
use sysinfo::{System, RefreshKind, ProcessRefreshKind};
3+
use std::collections::HashMap;
4+
5+
pub struct ProcessCollector;
6+
7+
impl ProcessCollector {
8+
pub fn new() -> Self {
9+
ProcessCollector
10+
}
11+
}
12+
13+
impl MetricCollector for ProcessCollector {
14+
fn collect(&self) -> Result<MetricData, Box<dyn std::error::Error>> {
15+
let sys = System::new_with_specifics(
16+
RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
17+
);
18+
19+
let processes = sys.processes();
20+
let total = processes.len() as i64;
21+
22+
let mut by_memory: Vec<_> = processes.values().collect();
23+
by_memory.sort_by(|a, b| b.memory().cmp(&a.memory()));
24+
25+
let top_mem: Vec<MetricValue> = by_memory
26+
.iter()
27+
.take(5)
28+
.map(|p| {
29+
MetricValue::String(format!(
30+
"{} (pid {}) — {:.1}MB",
31+
p.name().to_string_lossy(),
32+
p.pid(),
33+
p.memory() as f64 / 1_048_576.0,
34+
))
35+
})
36+
.collect();
37+
38+
let mut by_cpu: Vec<_> = processes.values().collect();
39+
by_cpu.sort_by(|a, b| b.cpu_usage().partial_cmp(&a.cpu_usage()).unwrap_or(std::cmp::Ordering::Equal));
40+
41+
let top_cpu: Vec<MetricValue> = by_cpu
42+
.iter()
43+
.take(5)
44+
.map(|p| {
45+
MetricValue::String(format!(
46+
"{} (pid {}) — {:.1}%",
47+
p.name().to_string_lossy(),
48+
p.pid(),
49+
p.cpu_usage(),
50+
))
51+
})
52+
.collect();
53+
54+
let mut metrics = HashMap::new();
55+
metrics.insert("total_processes".to_string(), MetricValue::Integer(total));
56+
metrics.insert("top_by_memory".to_string(), MetricValue::List(top_mem));
57+
metrics.insert("top_by_cpu".to_string(), MetricValue::List(top_cpu));
58+
59+
Ok(MetricData {
60+
timestamp: std::time::SystemTime::now(),
61+
metrics,
62+
})
63+
}
64+
65+
fn name(&self) -> &'static str {
66+
"process"
67+
}
68+
}

src/modules/system.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use crate::core::{MetricCollector, MetricData, MetricValue};
2+
use sysinfo::System;
3+
use std::collections::HashMap;
4+
5+
pub struct SystemCollector;
6+
7+
impl SystemCollector {
8+
pub fn new() -> Self {
9+
SystemCollector
10+
}
11+
}
12+
13+
impl MetricCollector for SystemCollector {
14+
fn collect(&self) -> Result<MetricData, Box<dyn std::error::Error>> {
15+
let mut metrics = HashMap::new();
16+
17+
if let Some(name) = System::name() {
18+
metrics.insert("os_name".to_string(), MetricValue::String(name));
19+
}
20+
if let Some(version) = System::os_version() {
21+
metrics.insert("os_version".to_string(), MetricValue::String(version));
22+
}
23+
if let Some(kernel) = System::kernel_version() {
24+
metrics.insert("kernel_version".to_string(), MetricValue::String(kernel));
25+
}
26+
if let Some(host) = System::host_name() {
27+
metrics.insert("hostname".to_string(), MetricValue::String(host));
28+
}
29+
if let Some(arch) = System::cpu_arch() {
30+
metrics.insert("arch".to_string(), MetricValue::String(arch));
31+
}
32+
33+
let uptime_secs = System::uptime();
34+
metrics.insert("uptime_seconds".to_string(), MetricValue::Integer(uptime_secs as i64));
35+
metrics.insert("uptime_human".to_string(), MetricValue::String(format_uptime(uptime_secs)));
36+
37+
let load = System::load_average();
38+
metrics.insert("load_1m".to_string(), MetricValue::Float(load.one));
39+
metrics.insert("load_5m".to_string(), MetricValue::Float(load.five));
40+
metrics.insert("load_15m".to_string(), MetricValue::Float(load.fifteen));
41+
42+
Ok(MetricData {
43+
timestamp: std::time::SystemTime::now(),
44+
metrics,
45+
})
46+
}
47+
48+
fn name(&self) -> &'static str {
49+
"system"
50+
}
51+
}
52+
53+
fn format_uptime(secs: u64) -> String {
54+
let days = secs / 86400;
55+
let hours = (secs % 86400) / 3600;
56+
let minutes = (secs % 3600) / 60;
57+
58+
if days > 0 {
59+
format!("{}d {}h {}m", days, hours, minutes)
60+
} else if hours > 0 {
61+
format!("{}h {}m", hours, minutes)
62+
} else {
63+
format!("{}m", minutes)
64+
}
65+
}

0 commit comments

Comments
 (0)