feat: add device traffic metrics with gateway telemetry reporting and admin UI display

Add rx_bytes and tx_bytes fields to Device type and API responses. Add formatDataSize helper for human-readable byte formatting with units from B to TB. Add Received and Sent columns to devices table in admin UI with formatted traffic totals. Add traffic metrics display to device action panel.

Add TelemetrySnapshot and PeerTelemetry types for gateway runtime stats. Add gateway telemetry endpoint at POST /gateway
This commit is contained in:
2026-03-18 07:43:22 +01:00
parent 21b7a140dd
commit 610c5459e5
14 changed files with 472 additions and 34 deletions

View File

@@ -3,6 +3,7 @@ use std::{
process::Command,
};
use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Manager};
pub fn current_tunnel_strategy() -> &'static str {
@@ -48,20 +49,32 @@ pub fn disconnect(app: &AppHandle, profile_path: &Path) -> Result<(), String> {
}
pub fn is_active(app: &AppHandle, profile_path: &Path) -> Result<bool, String> {
Ok(metrics(app, profile_path)?.active)
}
pub fn metrics(app: &AppHandle, profile_path: &Path) -> Result<TunnelMetrics, String> {
let backend = bundled_backend(app)?;
let output = Command::new(backend)
.arg("status")
.arg("metrics")
.arg("--profile")
.arg(profile_path)
.output()
.map_err(|err| format!("Unable to query embedded tunnel backend: {}", err))?;
if !output.status.success() {
return Err(format_helper_error("status", &output));
return Err(format_helper_error("metrics", &output));
}
let stdout = String::from_utf8_lossy(&output.stdout);
Ok(stdout.trim().eq_ignore_ascii_case("active"))
serde_json::from_slice::<TunnelMetrics>(&output.stdout)
.map_err(|err| format!("Unable to decode tunnel metrics: {}", err))
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TunnelMetrics {
pub active: bool,
pub rx_bytes: u64,
pub tx_bytes: u64,
}
fn bundled_backend(app: &AppHandle) -> Result<PathBuf, String> {