diff --git a/tailnet/coordinator.go b/tailnet/coordinator.go
index 1373b370a5def..cd5e0e41d6def 100644
--- a/tailnet/coordinator.go
+++ b/tailnet/coordinator.go
@@ -14,6 +14,7 @@ import (
"time"
"github.com/google/uuid"
+ "golang.org/x/exp/slices"
"golang.org/x/xerrors"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
@@ -444,62 +445,109 @@ func (c *coordinator) ServeHTTPDebug(w http.ResponseWriter, _ *http.Request) {
defer c.mutex.RUnlock()
fmt.Fprintln(w, "
in-memory wireguard coordinator debug
")
- fmt.Fprintf(w, "# agents: total %d
\n", len(c.agentSockets))
- fmt.Fprintln(w, "")
- for id, conn := range c.agentSockets {
- fmt.Fprintf(w, "- %s (%s): created %v ago, write %v ago, overwrites %d
\n",
- conn.name,
- id.String(),
- now.Sub(time.Unix(conn.start, 0)).Round(time.Second),
- now.Sub(time.Unix(conn.lastWrite, 0)).Round(time.Second),
- conn.overwrites,
- )
-
- if connCount := len(c.agentToConnectionSockets[id]); connCount > 0 {
- fmt.Fprintf(w, "connections: total %d
\n", connCount)
- fmt.Fprintln(w, "")
- for id, conn := range c.agentToConnectionSockets[id] {
- fmt.Fprintf(w, "- %s (%s): created %v ago, write %v ago
\n",
- conn.name,
- id.String(),
- now.Sub(time.Unix(conn.start, 0)).Round(time.Second),
- now.Sub(time.Unix(conn.lastWrite, 0)).Round(time.Second),
- )
- }
- fmt.Fprintln(w, "
")
- }
+
+ type idConn struct {
+ id uuid.UUID
+ conn *trackedConn
}
- fmt.Fprintln(w, "
")
- missingAgents := map[uuid.UUID]map[uuid.UUID]*trackedConn{}
- for agentID, conns := range c.agentToConnectionSockets {
- if len(conns) == 0 {
- continue
+ {
+ fmt.Fprintf(w, "# agents: total %d
\n", len(c.agentSockets))
+ fmt.Fprintln(w, "")
+ agentSockets := make([]idConn, 0, len(c.agentSockets))
+
+ for id, conn := range c.agentSockets {
+ agentSockets = append(agentSockets, idConn{id, conn})
}
- if _, ok := c.agentSockets[agentID]; !ok {
- missingAgents[agentID] = conns
+ slices.SortFunc(agentSockets, func(a, b idConn) bool {
+ return a.conn.name < b.conn.name
+ })
+
+ for _, agent := range agentSockets {
+ fmt.Fprintf(w, "- %s (
%s
): created %v ago, write %v ago, overwrites %d \n",
+ agent.conn.name,
+ agent.id.String(),
+ now.Sub(time.Unix(agent.conn.start, 0)).Round(time.Second),
+ now.Sub(time.Unix(agent.conn.lastWrite, 0)).Round(time.Second),
+ agent.conn.overwrites,
+ )
+
+ if conns := c.agentToConnectionSockets[agent.id]; len(conns) > 0 {
+ fmt.Fprintf(w, "connections: total %d
\n", len(conns))
+
+ connSockets := make([]idConn, 0, len(conns))
+ for id, conn := range conns {
+ connSockets = append(connSockets, idConn{id, conn})
+ }
+ slices.SortFunc(connSockets, func(a, b idConn) bool {
+ return a.id.String() < b.id.String()
+ })
+
+ fmt.Fprintln(w, "")
+ for _, connSocket := range connSockets {
+ fmt.Fprintf(w, "- %s (
%s
): created %v ago, write %v ago \n",
+ connSocket.conn.name,
+ connSocket.id.String(),
+ now.Sub(time.Unix(connSocket.conn.start, 0)).Round(time.Second),
+ now.Sub(time.Unix(connSocket.conn.lastWrite, 0)).Round(time.Second),
+ )
+ }
+ fmt.Fprintln(w, "
")
+ }
}
+
+ fmt.Fprintln(w, "
")
}
- fmt.Fprintf(w, "# missing agents: total %d
\n", len(missingAgents))
- fmt.Fprintln(w, "")
- for agentID, conns := range missingAgents {
- fmt.Fprintf(w, "- unknown (%s): created ? ago, write ? ago, overwrites ?
\n",
- agentID.String(),
- )
+ {
+ type agentConns struct {
+ id uuid.UUID
+ conns []idConn
+ }
- fmt.Fprintf(w, "connections: total %d
\n", len(conns))
+ missingAgents := []agentConns{}
+ for agentID, conns := range c.agentToConnectionSockets {
+ if len(conns) == 0 {
+ continue
+ }
+
+ if _, ok := c.agentSockets[agentID]; !ok {
+ connsSlice := make([]idConn, 0, len(conns))
+ for id, conn := range conns {
+ connsSlice = append(connsSlice, idConn{id, conn})
+ }
+ slices.SortFunc(connsSlice, func(a, b idConn) bool {
+ return a.id.String() < b.id.String()
+ })
+
+ missingAgents = append(missingAgents, agentConns{agentID, connsSlice})
+ }
+ }
+ slices.SortFunc(missingAgents, func(a, b agentConns) bool {
+ return a.id.String() < b.id.String()
+ })
+
+ fmt.Fprintf(w, "# missing agents: total %d
\n", len(missingAgents))
fmt.Fprintln(w, "")
- for id, conn := range conns {
- fmt.Fprintf(w, "- %s (%s): created %v ago, write %v ago
\n",
- conn.name,
- id.String(),
- now.Sub(time.Unix(conn.start, 0)).Round(time.Second),
- now.Sub(time.Unix(conn.lastWrite, 0)).Round(time.Second),
+
+ for _, agentConns := range missingAgents {
+ fmt.Fprintf(w, "- unknown (
%s
): created ? ago, write ? ago, overwrites ? \n",
+ agentConns.id.String(),
)
+
+ fmt.Fprintf(w, "connections: total %d
\n", len(agentConns.conns))
+ fmt.Fprintln(w, "")
+ for _, agentConn := range agentConns.conns {
+ fmt.Fprintf(w, "- %s (
%s
): created %v ago, write %v ago \n",
+ agentConn.conn.name,
+ agentConn.id.String(),
+ now.Sub(time.Unix(agentConn.conn.start, 0)).Round(time.Second),
+ now.Sub(time.Unix(agentConn.conn.lastWrite, 0)).Round(time.Second),
+ )
+ }
+ fmt.Fprintln(w, "
")
}
fmt.Fprintln(w, "
")
}
- fmt.Fprintln(w, "
")
}