feat(client): report relay RTT diagnostics
Expose the active QUIC connection RTT in shared client diagnostics and in the Windows client status line. This gives operators a live relay-path latency signal without pretending to measure end-to-end gateway or LAN latency. The new diagnostics field defaults to unknown when older JSON snapshots omit it, so consumers can read pre-change snapshots without special migration code. The user-facing diagnostics now print Relay RTT only when the client has an active QUIC measurement. Test Plan: - cargo fmt --check - git diff --check - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings Refs: PLAN.md logging and diagnostics section
This commit is contained in:
@@ -258,6 +258,8 @@ impl RelayDiagnostics {
|
||||
pub struct QuicDiagnostics {
|
||||
datagram_supported: bool,
|
||||
max_datagram_size: Option<u16>,
|
||||
#[serde(default)]
|
||||
relay_rtt_ms: Option<u64>,
|
||||
}
|
||||
|
||||
impl QuicDiagnostics {
|
||||
@@ -266,9 +268,16 @@ impl QuicDiagnostics {
|
||||
Self {
|
||||
datagram_supported,
|
||||
max_datagram_size,
|
||||
relay_rtt_ms: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn with_relay_rtt_ms(mut self, relay_rtt_ms: Option<u64>) -> Self {
|
||||
self.relay_rtt_ms = relay_rtt_ms;
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn datagram_supported(&self) -> bool {
|
||||
self.datagram_supported
|
||||
@@ -278,6 +287,11 @@ impl QuicDiagnostics {
|
||||
pub const fn max_datagram_size(&self) -> Option<u16> {
|
||||
self.max_datagram_size
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn relay_rtt_ms(&self) -> Option<u64> {
|
||||
self.relay_rtt_ms
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
|
||||
@@ -408,6 +422,13 @@ impl ClientDiagnostics {
|
||||
diagnostics.push(UserDiagnostic::new(UserDiagnosticLevel::Info, message));
|
||||
}
|
||||
|
||||
if let Some(rtt_ms) = self.quic.relay_rtt_ms() {
|
||||
diagnostics.push(UserDiagnostic::new(
|
||||
UserDiagnosticLevel::Info,
|
||||
format!("Relay RTT: {rtt_ms} ms"),
|
||||
));
|
||||
}
|
||||
|
||||
if self.stats.broadcast_frames_tx() > 0 || self.stats.broadcast_frames_rx() > 0 {
|
||||
diagnostics.push(UserDiagnostic::new(
|
||||
UserDiagnosticLevel::Info,
|
||||
@@ -537,6 +558,7 @@ mod tests {
|
||||
assert!(diagnostics.relay().gateway_connected());
|
||||
assert!(diagnostics.quic().datagram_supported());
|
||||
assert_eq!(diagnostics.quic().max_datagram_size(), Some(1400));
|
||||
assert_eq!(diagnostics.quic().relay_rtt_ms(), None);
|
||||
assert!(diagnostics.tap().adapter_found());
|
||||
assert_eq!(diagnostics.tap().mac(), Some(mac));
|
||||
assert_eq!(diagnostics.tap().mtu(), Some(1200));
|
||||
@@ -564,11 +586,24 @@ mod tests {
|
||||
assert_eq!(stats.broadcast_frames_rx(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn defaults_missing_relay_rtt_to_unknown() {
|
||||
let diagnostics: QuicDiagnostics = serde_json::from_str(
|
||||
r#"{
|
||||
"datagram_supported": true,
|
||||
"max_datagram_size": 1400
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(diagnostics.relay_rtt_ms(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derives_user_diagnostics_from_client_snapshot() {
|
||||
let diagnostics = ClientDiagnostics::new(
|
||||
RelayDiagnostics::new(true, true, true),
|
||||
QuicDiagnostics::new(true, Some(1400)),
|
||||
QuicDiagnostics::new(true, Some(1400)).with_relay_rtt_ms(Some(23)),
|
||||
TapDiagnostics::new(
|
||||
true,
|
||||
Some(MacAddr::new([0x02, 1, 2, 3, 4, 5])),
|
||||
@@ -590,6 +625,7 @@ mod tests {
|
||||
"Connected to relay",
|
||||
"Connected to LAN gateway",
|
||||
"DHCP received: 10.73.42.51",
|
||||
"Relay RTT: 23 ms",
|
||||
"Broadcast traffic flowing",
|
||||
]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user