nd_300/diagnostics/
traffic_counters.rs1use serde::Serialize;
2use sysinfo::Networks;
3
4use super::shared_cache::SharedCache;
5
6#[derive(Debug, Clone, Serialize)]
7pub struct TrafficCounter {
8 pub interface: String,
9 pub rx_bytes: u64,
10 pub tx_bytes: u64,
11 pub rx_formatted: String,
12 pub tx_formatted: String,
13 pub total_formatted: String,
14}
15
16pub async fn collect_with_cache(cache: &SharedCache) -> Option<Vec<TrafficCounter>> {
17 if let Some(ref networks) = cache.sysinfo_networks {
18 return collect_from_networks(networks);
19 }
20 collect().await
21}
22
23fn collect_from_networks(networks: &Networks) -> Option<Vec<TrafficCounter>> {
24 let mut counters = Vec::new();
25
26 for (name, data) in networks {
27 let rx = data.total_received();
28 let tx = data.total_transmitted();
29
30 if rx == 0 && tx == 0 {
31 continue;
32 }
33
34 counters.push(TrafficCounter {
35 interface: name.clone(),
36 rx_bytes: rx,
37 tx_bytes: tx,
38 rx_formatted: format_bytes(rx),
39 tx_formatted: format_bytes(tx),
40 total_formatted: format_bytes(rx + tx),
41 });
42 }
43
44 if counters.is_empty() {
45 None
46 } else {
47 Some(counters)
48 }
49}
50
51pub async fn collect() -> Option<Vec<TrafficCounter>> {
52 let networks = Networks::new_with_refreshed_list();
53 let mut counters = Vec::new();
54
55 for (name, data) in &networks {
56 let rx = data.total_received();
57 let tx = data.total_transmitted();
58
59 if rx == 0 && tx == 0 {
60 continue;
61 }
62
63 counters.push(TrafficCounter {
64 interface: name.clone(),
65 rx_bytes: rx,
66 tx_bytes: tx,
67 rx_formatted: format_bytes(rx),
68 tx_formatted: format_bytes(tx),
69 total_formatted: format_bytes(rx + tx),
70 });
71 }
72
73 if counters.is_empty() {
74 None
75 } else {
76 Some(counters)
77 }
78}
79
80fn format_bytes(bytes: u64) -> String {
81 const KB: u64 = 1024;
82 const MB: u64 = 1024 * KB;
83 const GB: u64 = 1024 * MB;
84 const TB: u64 = 1024 * GB;
85
86 if bytes >= TB {
87 format!("{:.2} TB", bytes as f64 / TB as f64)
88 } else if bytes >= GB {
89 format!("{:.2} GB", bytes as f64 / GB as f64)
90 } else if bytes >= MB {
91 format!("{:.1} MB", bytes as f64 / MB as f64)
92 } else if bytes >= KB {
93 format!("{:.1} KB", bytes as f64 / KB as f64)
94 } else {
95 format!("{} B", bytes)
96 }
97}