Skip to content

Commit b2e66cc

Browse files
apollo_network_benchmark: added network usage metrics
1 parent 26772cb commit b2e66cc

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

crates/apollo_network_benchmark/src/bin/broadcast_network_stress_test_node/metrics.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ define_metrics!(
1717
MetricGauge { SYSTEM_PROCESS_CPU_USAGE_PERCENT, "system_process_cpu_usage_percent", "CPU usage percentage of the current process" },
1818
MetricGauge { SYSTEM_PROCESS_MEMORY_USAGE_BYTES, "system_process_memory_usage_bytes", "Memory usage in bytes of the current process" },
1919
MetricGauge { SYSTEM_PROCESS_VIRTUAL_MEMORY_USAGE_BYTES, "system_process_virtual_memory_usage_bytes", "Virtual memory usage in bytes of the current process" },
20+
21+
// system metrics for network usage
22+
MetricGauge { SYSTEM_NETWORK_BYTES_SENT_TOTAL, "system_network_bytes_sent_total", "Total bytes sent across all network interfaces since system start" },
23+
MetricGauge { SYSTEM_NETWORK_BYTES_RECEIVED_TOTAL, "system_network_bytes_received_total", "Total bytes received across all network interfaces since system start" },
24+
MetricGauge { SYSTEM_NETWORK_BYTES_SENT_CURRENT, "system_network_bytes_sent_current", "Bytes sent across all network interfaces since last measurement" },
25+
MetricGauge { SYSTEM_NETWORK_BYTES_RECEIVED_CURRENT, "system_network_bytes_received_current", "Bytes received across all network interfaces since last measurement" },
2026
},
2127
);
2228

crates/apollo_network_benchmark/src/bin/broadcast_network_stress_test_node/system_metrics.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use tracing::warn;
88
use crate::metrics::{
99
SYSTEM_AVAILABLE_MEMORY_BYTES,
1010
SYSTEM_CPU_COUNT,
11+
SYSTEM_NETWORK_BYTES_RECEIVED_CURRENT,
12+
SYSTEM_NETWORK_BYTES_RECEIVED_TOTAL,
13+
SYSTEM_NETWORK_BYTES_SENT_CURRENT,
14+
SYSTEM_NETWORK_BYTES_SENT_TOTAL,
1115
SYSTEM_PROCESS_CPU_USAGE_PERCENT,
1216
SYSTEM_PROCESS_MEMORY_USAGE_BYTES,
1317
SYSTEM_PROCESS_VIRTUAL_MEMORY_USAGE_BYTES,
@@ -126,11 +130,41 @@ fn get_process_memory() -> Option<(u64, u64)> {
126130
Some((rss_kb? * 1024, vsize_kb? * 1024))
127131
}
128132

133+
/// Reads per-interface network byte counters from /proc/net/dev.
134+
/// Returns a vec of (interface_name, rx_bytes, tx_bytes).
135+
fn get_network_stats() -> Option<Vec<(String, u64, u64)>> {
136+
let content = match fs::read_to_string("/proc/net/dev") {
137+
Ok(c) => c,
138+
Err(e) => {
139+
warn!("Failed to read /proc/net/dev: {}", e);
140+
return None;
141+
}
142+
};
143+
144+
let mut result = Vec::new();
145+
// Skip the first two header lines
146+
for line in content.lines().skip(2) {
147+
let (iface, rest) = line.split_once(':')?;
148+
let iface = iface.trim().to_string();
149+
let fields: Vec<&str> = rest.split_whitespace().collect();
150+
// Field 0 = rx_bytes, field 8 = tx_bytes
151+
let rx_bytes: u64 = fields.first()?.parse().ok()?;
152+
let tx_bytes: u64 = fields.get(8)?.parse().ok()?;
153+
result.push((iface, rx_bytes, tx_bytes));
154+
}
155+
Some(result)
156+
}
157+
129158
struct CpuState {
130159
prev_ticks: u64,
131160
prev_time: Instant,
132161
}
133162

163+
struct NetworkState {
164+
prev_bytes_sent: u64,
165+
prev_bytes_received: u64,
166+
}
167+
134168
/// Collects system-wide and process-specific metrics (CPU, memory) by reading /proc directly.
135169
fn collect_system_and_process_metrics(cpu_state: &mut Option<CpuState>) {
136170
if let Some((total, available)) = get_memory_info() {
@@ -166,14 +200,49 @@ fn collect_system_and_process_metrics(cpu_state: &mut Option<CpuState>) {
166200
}
167201
}
168202

203+
/// Collects network interface metrics (bytes sent/received) by reading /proc/net/dev.
204+
fn collect_network_metrics(network_state: &mut Option<NetworkState>) {
205+
let stats = match get_network_stats() {
206+
Some(s) => s,
207+
None => return,
208+
};
209+
210+
let mut total_bytes_sent: u64 = 0;
211+
let mut total_bytes_received: u64 = 0;
212+
213+
for (iface, rx, tx) in &stats {
214+
if iface == "lo" || iface.starts_with("ifb") {
215+
continue;
216+
}
217+
total_bytes_sent += tx;
218+
total_bytes_received += rx;
219+
}
220+
221+
SYSTEM_NETWORK_BYTES_SENT_TOTAL.set(total_bytes_sent.into_f64());
222+
SYSTEM_NETWORK_BYTES_RECEIVED_TOTAL.set(total_bytes_received.into_f64());
223+
224+
if let Some(prev) = network_state.as_ref() {
225+
let current_sent = total_bytes_sent.saturating_sub(prev.prev_bytes_sent);
226+
let current_received = total_bytes_received.saturating_sub(prev.prev_bytes_received);
227+
SYSTEM_NETWORK_BYTES_SENT_CURRENT.set(current_sent.into_f64());
228+
SYSTEM_NETWORK_BYTES_RECEIVED_CURRENT.set(current_received.into_f64());
229+
}
230+
231+
*network_state = Some(NetworkState {
232+
prev_bytes_sent: total_bytes_sent,
233+
prev_bytes_received: total_bytes_received,
234+
});
235+
}
236+
169237
pub async fn monitor_process_metrics(interval_seconds: u64) {
170238
let mut interval = interval(Duration::from_secs(interval_seconds));
171239

172240
struct State {
173241
cpu_state: Option<CpuState>,
242+
network_state: Option<NetworkState>,
174243
}
175244

176-
let mut state = Some(State { cpu_state: None });
245+
let mut state = Some(State { cpu_state: None, network_state: None });
177246

178247
loop {
179248
interval.tick().await;
@@ -182,6 +251,7 @@ pub async fn monitor_process_metrics(interval_seconds: u64) {
182251
state = tokio::task::spawn_blocking(move || {
183252
let mut state = passed_state.unwrap();
184253
collect_system_and_process_metrics(&mut state.cpu_state);
254+
collect_network_metrics(&mut state.network_state);
185255
Some(state)
186256
})
187257
.await

0 commit comments

Comments
 (0)