1#[cfg(target_os = "linux")]
7pub fn read_net_dev() -> Option<(u64, u64)> {
8 read_net_dev_from_path("/proc/net/dev")
9}
10
11#[cfg(target_os = "linux")]
14pub fn read_net_dev_for_pid(pid: i32) -> Option<(u64, u64)> {
15 read_net_dev_from_path(&format!("/proc/{}/net/dev", pid))
16}
17
18#[cfg(target_os = "linux")]
19fn read_net_dev_from_path(path: &str) -> Option<(u64, u64)> {
20 let raw = std::fs::read_to_string(path).ok()?;
21 let mut rx_total = 0u64;
22 let mut tx_total = 0u64;
23 for line in raw.lines().skip(2) {
24 let colon = line.find(':')?;
25 let rest = line[colon + 1..].trim_start();
26 let nums: Vec<u64> = rest
27 .split_whitespace()
28 .filter_map(|s| s.parse().ok())
29 .collect();
30 if nums.len() >= 9 {
31 rx_total += nums[0];
32 tx_total += nums[8];
33 }
34 }
35 Some((rx_total, tx_total))
36}
37
38#[cfg(target_os = "linux")]
47pub fn sample_network_rate(pid: i32) -> Option<(u64, u64)> {
48 let window_ms = std::env::var("PEEK_NET_SAMPLE_MS")
49 .ok()
50 .and_then(|s| s.parse::<u64>().ok())
51 .unwrap_or(1000);
52
53 if window_ms == 0 {
54 return None;
55 }
56
57 let window = std::time::Duration::from_millis(window_ms);
58
59 let (r1, t1) = read_net_dev_for_pid(pid)?;
60 std::thread::sleep(window);
61 let (r2, t2) = read_net_dev_for_pid(pid)?;
62 let elapsed_secs = window_ms as f64 / 1000.0;
63 let rx = (r2.saturating_sub(r1) as f64 / elapsed_secs) as u64;
64 let tx = (t2.saturating_sub(t1) as f64 / elapsed_secs) as u64;
65 Some((rx, tx))
66}
67
68#[cfg(not(target_os = "linux"))]
69pub fn read_net_dev() -> Option<(u64, u64)> {
70 None
71}
72
73#[cfg(not(target_os = "linux"))]
74pub fn read_net_dev_for_pid(_pid: i32) -> Option<(u64, u64)> {
75 None
76}
77
78#[cfg(not(target_os = "linux"))]
79pub fn sample_network_rate(_pid: i32) -> Option<(u64, u64)> {
80 None
81}