feat: add mesh network visualizer
- D3.js force-directed graph for real-time mesh visualization - WebSocket server (mesh-viz-bridge crate) for live updates - Demo mode with simulated topology - JSONL file upload for offline analysis - Optional viz logging in mesh_node forwarding
This commit is contained in:
@@ -42,6 +42,7 @@ pub mod transport_iroh;
|
||||
pub mod transport_manager;
|
||||
pub mod transport_tcp;
|
||||
pub mod transport_lora;
|
||||
pub mod viz_log;
|
||||
#[cfg(feature = "traffic-resistance")]
|
||||
pub mod traffic_resistance;
|
||||
|
||||
|
||||
@@ -352,8 +352,14 @@ impl MeshNode {
|
||||
IncomingAction::Deliver(_) => {
|
||||
self.metrics.store.messages_delivered.inc();
|
||||
}
|
||||
IncomingAction::Forward { .. } => {
|
||||
IncomingAction::Forward {
|
||||
envelope: _,
|
||||
next_hop,
|
||||
} => {
|
||||
self.metrics.routing.announcements_forwarded.inc();
|
||||
let from = format!("{sender}");
|
||||
let to = next_hop.to_string();
|
||||
crate::viz_log::log_forward_hop(&from, &to, 0);
|
||||
}
|
||||
IncomingAction::Store(_) => {
|
||||
self.metrics.store.messages_stored.inc();
|
||||
|
||||
45
crates/quicprochat-p2p/src/viz_log.rs
Normal file
45
crates/quicprochat-p2p/src/viz_log.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
//! Optional NDJSON events for the mesh graph visualizer (`viz/mesh-graph.html`).
|
||||
//!
|
||||
//! When the environment variable `QPC_MESH_VIZ_LOG` is set to a file path, one JSON object
|
||||
//! per line is appended for selected mesh events. The `viz/bridge` binary can tail this file
|
||||
//! and forward lines to the browser over WebSocket.
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct HopEvent<'a> {
|
||||
#[serde(rename = "type")]
|
||||
kind: &'static str,
|
||||
from: &'a str,
|
||||
to: &'a str,
|
||||
ms: u64,
|
||||
}
|
||||
|
||||
/// Log a relay hop (forwarding to `next_hop`). No-op unless `QPC_MESH_VIZ_LOG` is set.
|
||||
pub fn log_forward_hop(from_sender: &str, next_hop: &str, latency_ms: u64) {
|
||||
let Ok(path) = std::env::var("QPC_MESH_VIZ_LOG") else {
|
||||
return;
|
||||
};
|
||||
let ev = HopEvent {
|
||||
kind: "hop",
|
||||
from: from_sender,
|
||||
to: next_hop,
|
||||
ms: latency_ms,
|
||||
};
|
||||
let Ok(line) = serde_json::to_string(&ev) else {
|
||||
return;
|
||||
};
|
||||
append_line(&path, &line);
|
||||
}
|
||||
|
||||
fn append_line(path: &str, line: &str) {
|
||||
use std::io::Write;
|
||||
let Ok(mut f) = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(path)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let _ = writeln!(f, "{line}");
|
||||
}
|
||||
Reference in New Issue
Block a user