From bc95a1f425078f70cdcd16e370d9775f15b9a4e1 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 10 Nov 2025 12:41:23 +1100 Subject: [PATCH] chore(snownet): log connection state on failure (#10820) When investigating, why a connection fails it is useful to know right away, what the last connection state was, including the kind of connection, such as `PeerToPeer`, `RelayToPeer` etc. --- rust/connlib/snownet/src/node.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/rust/connlib/snownet/src/node.rs b/rust/connlib/snownet/src/node.rs index ba863e4c5..b25193538 100644 --- a/rust/connlib/snownet/src/node.rs +++ b/rust/connlib/snownet/src/node.rs @@ -1726,6 +1726,19 @@ impl ConnectionState { } } +impl fmt::Display for ConnectionState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConnectionState::Connecting { .. } => write!(f, "Connecting"), + ConnectionState::Connected { peer_socket, .. } => { + write!(f, "Connected({})", peer_socket.kind()) + } + ConnectionState::Idle { peer_socket } => write!(f, "Idle({})", peer_socket.kind()), + ConnectionState::Failed => write!(f, "Failed"), + } + } +} + fn idle_at(last_activity: Instant) -> Instant { const MAX_IDLE: Duration = Duration::from_secs(20); // Must be longer than the ICE timeout otherwise we might not detect a failed connection early enough. @@ -1775,6 +1788,15 @@ impl PeerSocket { } } } + + fn kind(&self) -> &'static str { + match self { + PeerSocket::PeerToPeer { .. } => "PeerToPeer", + PeerSocket::PeerToRelay { .. } => "PeerToRelay", + PeerSocket::RelayToPeer { .. } => "RelayToPeer", + PeerSocket::RelayToRelay { .. } => "RelayToRelay", + } + } } impl Connection @@ -1839,7 +1861,7 @@ where .candidate_timeout() .is_some_and(|timeout| now >= timeout) { - tracing::info!("Connection failed (no candidates received)"); + tracing::info!(state = %self.state, "Connection failed (no candidates received)"); self.state = ConnectionState::Failed; return; } @@ -1848,7 +1870,7 @@ where .disconnect_timeout() .is_some_and(|timeout| now >= timeout) { - tracing::info!("Connection failed (ICE timeout)"); + tracing::info!(state = %self.state, "Connection failed (ICE timeout)"); self.state = ConnectionState::Failed; return; } @@ -2080,7 +2102,7 @@ where match self.tunnel.update_timers_at(&mut buf, now) { TunnResult::Done => {} TunnResult::Err(WireGuardError::ConnectionExpired) => { - tracing::info!("Connection failed (wireguard tunnel expired)"); + tracing::info!(state = %self.state, "Connection failed (wireguard tunnel expired)"); self.state = ConnectionState::Failed; } TunnResult::Err(e) => {