Skip to content

Commit 527f57c

Browse files
committed
feat(observability): relay visibility, health metrics, richer status output
pilotctl: - peers: add PATH column (direct/relay) — shows which peers go via beacon relay - daemon status: peers line shows encrypted + relay counts, pending handshakes - info: peers shows direct/relay split, pending handshake count, active beacon addr - health: adds encrypted/relay/pending/queue-drop/webhook-drop counters to text output - ping: always show dial/echo split in text mode (was --trace-only) - handshake: print "sending handshake to node N..." before blocking RPC call daemon/ipc: - peer_list entries now include "relay" field - handleInfo: expose accept_queue_drops, webhook_queue_dropped, webhook_circuit_skips, relay_peer_count, beacon_addr - handleHealth: expose same health fields so pilotctl health has full picture daemon: - DaemonInfo: add RelayPeerCount and BeaconAddr fields, populated in Info() - keyexchange/loop: rekey retransmit demoted from Info → Debug (prevents log flooding on networks with many peers)
1 parent 2ef6586 commit 527f57c

4 files changed

Lines changed: 135 additions & 151 deletions

File tree

cmd/pilotctl/main.go

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,8 +2100,28 @@ func cmdDaemonStatus(args []string) {
21002100
fmt.Printf(" Hostname: %s\n", h)
21012101
}
21022102
fmt.Printf(" Uptime: %02d:%02d:%02d\n", hours, mins, secs)
2103-
fmt.Printf(" Peers: %d\n", int(info["peers"].(float64)))
2103+
peers := int(info["peers"].(float64))
2104+
encPeers := 0
2105+
if ep, ok := info["encrypted_peers"].(float64); ok {
2106+
encPeers = int(ep)
2107+
}
2108+
relayPeers := 0
2109+
if rp, ok := info["relay_peer_count"].(float64); ok {
2110+
relayPeers = int(rp)
2111+
}
2112+
pending := 0
2113+
if hp, ok := info["handshake_pending_count"].(float64); ok {
2114+
pending = int(hp)
2115+
}
2116+
peerLine := fmt.Sprintf("%d", peers)
2117+
if peers > 0 {
2118+
peerLine = fmt.Sprintf("%d (%d encrypted, %d via relay)", peers, encPeers, relayPeers)
2119+
}
2120+
fmt.Printf(" Peers: %s\n", peerLine)
21042121
fmt.Printf(" Connections: %d\n", int(info["connections"].(float64)))
2122+
if pending > 0 {
2123+
fmt.Printf(" Handshakes: %d pending\n", pending)
2124+
}
21052125
return
21062126
}
21072127
output(result)
@@ -3420,6 +3440,9 @@ func cmdHandshake(args []string) {
34203440
justification = args[1]
34213441
}
34223442

3443+
if !jsonOutput {
3444+
fmt.Fprintf(os.Stderr, "sending handshake to node %d...\n", nodeID)
3445+
}
34233446
result, err := d.Handshake(nodeID, justification)
34243447
if err != nil {
34253448
fatalCode("connection_failed", "handshake: %v", err)
@@ -3747,17 +3770,29 @@ func cmdInfo(args []string) {
37473770
fmt.Printf(" Uptime: %02d:%02d:%02d\n", hours, mins, secs)
37483771
fmt.Printf(" Connections: %d\n", int(info["connections"].(float64)))
37493772
fmt.Printf(" Ports: %d\n", int(info["ports"].(float64)))
3750-
fmt.Printf(" Peers: %d\n", int(info["peers"].(float64)))
3773+
totalPeers := int(info["peers"].(float64))
3774+
relayPeers := 0
3775+
if rp, ok := info["relay_peer_count"].(float64); ok {
3776+
relayPeers = int(rp)
3777+
}
3778+
directPeers := totalPeers - relayPeers
3779+
fmt.Printf(" Peers: %d (%d direct, %d via relay)\n", totalPeers, directPeers, relayPeers)
37513780
authenticatedPeers := 0
37523781
if ap, ok := info["authenticated_peers"].(float64); ok {
37533782
authenticatedPeers = int(ap)
37543783
}
37553784
if encryptEnabled {
37563785
fmt.Printf(" Encryption: enabled (X25519 + AES-256-GCM), %d/%d peers encrypted, %d authenticated\n",
3757-
encryptedPeers, int(info["peers"].(float64)), authenticatedPeers)
3786+
encryptedPeers, totalPeers, authenticatedPeers)
37583787
} else {
37593788
fmt.Printf(" Encryption: disabled\n")
37603789
}
3790+
if pending, ok := info["handshake_pending_count"].(float64); ok && int(pending) > 0 {
3791+
fmt.Printf(" Handshakes: %d pending approval\n", int(pending))
3792+
}
3793+
if beacon, ok := info["beacon_addr"].(string); ok && beacon != "" {
3794+
fmt.Printf(" Beacon: %s\n", beacon)
3795+
}
37613796
hasIdentity := false
37623797
if id, ok := info["identity"].(bool); ok {
37633798
hasIdentity = id
@@ -3853,13 +3888,44 @@ func cmdHealth() {
38533888
mins := (uptime % 3600) / 60
38543889
secs := uptime % 60
38553890

3891+
peers := int(health["peers"].(float64))
3892+
encPeers := 0
3893+
if ep, ok := health["encrypted_peers"].(float64); ok {
3894+
encPeers = int(ep)
3895+
}
3896+
relayPeers := 0
3897+
if rp, ok := health["relay_peer_count"].(float64); ok {
3898+
relayPeers = int(rp)
3899+
}
3900+
pending := 0
3901+
if hp, ok := health["handshake_pending_count"].(float64); ok {
3902+
pending = int(hp)
3903+
}
3904+
queueDrops := uint64(0)
3905+
if qd, ok := health["accept_queue_drops"].(float64); ok {
3906+
queueDrops = uint64(qd)
3907+
}
3908+
webhookDropped := uint64(0)
3909+
if wd, ok := health["webhook_queue_dropped"].(float64); ok {
3910+
webhookDropped = uint64(wd)
3911+
}
3912+
38563913
fmt.Printf("Daemon Health\n")
38573914
fmt.Printf(" Status: %s\n", health["status"])
38583915
fmt.Printf(" Uptime: %02d:%02d:%02d\n", hours, mins, secs)
38593916
fmt.Printf(" Connections: %d\n", int(health["connections"].(float64)))
3860-
fmt.Printf(" Peers: %d\n", int(health["peers"].(float64)))
3917+
fmt.Printf(" Peers: %d (%d encrypted, %d via relay)\n", peers, encPeers, relayPeers)
3918+
if pending > 0 {
3919+
fmt.Printf(" Handshakes: %d pending\n", pending)
3920+
}
38613921
fmt.Printf(" Bytes Sent: %s\n", formatBytes(uint64(health["bytes_sent"].(float64))))
38623922
fmt.Printf(" Bytes Recv: %s\n", formatBytes(uint64(health["bytes_recv"].(float64))))
3923+
if queueDrops > 0 {
3924+
fmt.Printf(" Queue Drops: %d (accept queue full — increase system limits if persistent)\n", queueDrops)
3925+
}
3926+
if webhookDropped > 0 {
3927+
fmt.Printf(" Webhook: %d events dropped\n", webhookDropped)
3928+
}
38633929
}
38643930

38653931
func cmdPeers(args []string) {
@@ -3945,9 +4011,9 @@ func cmdPeers(args []string) {
39454011

39464012
maxDisplay := 50
39474013
if showEndpoints {
3948-
fmt.Printf("%-10s %-30s %-20s %s\n", "NODE ID", "ENDPOINT", "ENCRYPTED", "AUTH")
4014+
fmt.Printf("%-10s %-30s %-20s %-16s %-6s\n", "NODE ID", "ENDPOINT", "ENCRYPTED", "AUTH", "PATH")
39494015
} else {
3950-
fmt.Printf("%-10s %-20s %s\n", "NODE ID", "ENCRYPTED", "AUTH")
4016+
fmt.Printf("%-10s %-20s %-16s %-6s\n", "NODE ID", "ENCRYPTED", "AUTH", "PATH")
39514017
}
39524018
displayed := 0
39534019
for _, p := range filtered {
@@ -3957,14 +4023,9 @@ func cmdPeers(args []string) {
39574023
}
39584024
displayed++
39594025
peer := p.(map[string]interface{})
3960-
encrypted := false
3961-
if e, ok := peer["encrypted"].(bool); ok {
3962-
encrypted = e
3963-
}
3964-
authenticated := false
3965-
if a, ok := peer["authenticated"].(bool); ok {
3966-
authenticated = a
3967-
}
4026+
encrypted, _ := peer["encrypted"].(bool)
4027+
authenticated, _ := peer["authenticated"].(bool)
4028+
relay, _ := peer["relay"].(bool)
39684029
encStr := "no"
39694030
if encrypted {
39704031
encStr = "yes (AES-256-GCM)"
@@ -3973,10 +4034,14 @@ func cmdPeers(args []string) {
39734034
if authenticated {
39744035
authStr = "yes (Ed25519)"
39754036
}
4037+
pathStr := "direct"
4038+
if relay {
4039+
pathStr = "relay"
4040+
}
39764041
if showEndpoints {
3977-
fmt.Printf("%-10d %-30s %-20s %s\n", int(peer["node_id"].(float64)), peer["endpoint"], encStr, authStr)
4042+
fmt.Printf("%-10d %-30s %-20s %-16s %-6s\n", int(peer["node_id"].(float64)), peer["endpoint"], encStr, authStr, pathStr)
39784043
} else {
3979-
fmt.Printf("%-10d %-20s %s\n", int(peer["node_id"].(float64)), encStr, authStr)
4044+
fmt.Printf("%-10d %-20s %-16s %-6s\n", int(peer["node_id"].(float64)), encStr, authStr, pathStr)
39804045
}
39814046
}
39824047
}
@@ -4223,14 +4288,14 @@ func cmdPing(args []string) {
42234288
toServer.Round(time.Microsecond),
42244289
fromServer.Round(time.Microsecond))
42254290
}
4226-
} else if traceTime {
4291+
} else {
4292+
// Always show dial/echo breakdown — tells you whether RTT
4293+
// is dominated by relay setup or actual peer latency.
42274294
if connReused {
42284295
fmt.Printf("seq=%d bytes=%d time=%v [echo=%v]%s\n", i, n, rtt, echoElapsed.Round(time.Microsecond), reusedTag)
42294296
} else {
42304297
fmt.Printf("seq=%d bytes=%d time=%v [dial=%v echo=%v]\n", i, n, rtt, dialElapsed.Round(time.Microsecond), echoElapsed.Round(time.Microsecond))
42314298
}
4232-
} else {
4233-
fmt.Printf("seq=%d bytes=%d time=%v%s\n", i, n, rtt, reusedTag)
42344299
}
42354300
}
42364301
}

pkg/daemon/daemon.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,9 @@ type DaemonInfo struct {
20622062
AcceptQueueDrops uint64
20632063
WebhookQueueDropped uint64
20642064
WebhookCircuitSkips uint64
2065+
2066+
RelayPeerCount int // peers currently on relay path (symmetric NAT)
2067+
BeaconAddr string // active beacon address
20652068
}
20662069

20672070
// Info returns current daemon status.
@@ -2151,6 +2154,8 @@ func (d *Daemon) Info() *DaemonInfo {
21512154
AcceptQueueDrops: atomic.LoadUint64(&d.AcceptQueueDrops),
21522155
WebhookQueueDropped: d.webhookStats().Dropped,
21532156
WebhookCircuitSkips: d.webhookStats().CircuitSkips,
2157+
RelayPeerCount: len(d.tunnels.RelayPeerIDs()),
2158+
BeaconAddr: d.config.BeaconAddr,
21542159
}
21552160
}
21562161

0 commit comments

Comments
 (0)