package main import ( "context" "encoding/json" "strings" "time" ) // CountConnections reads the bus driver's Debug.Stats answer (`busctl call … GetStats --json=short`): // dbus-broker lists one accounting entry per peer, the reference daemon says ActiveConnections. func CountConnections(out string) (int, bool) { var reply struct { Data []map[string]struct { Data json.RawMessage `json:"data"` } `json:"data"` } if json.Unmarshal([]byte(strings.TrimSpace(out)), &reply) != nil || len(reply.Data) != 1 { return 0, false } if v, ok := reply.Data[0]["org.bus1.DBus.Debug.Stats.PeerAccounting"]; ok { var peers []json.RawMessage if json.Unmarshal(v.Data, &peers) == nil { return len(peers), true } } if v, ok := reply.Data[0]["ActiveConnections"]; ok { var n int if json.Unmarshal(v.Data, &n) == nil { return n, true } } return 0, false } // CountUniqueNames counts the connections among ListNames' answer (`busctl call … ListNames`). func CountUniqueNames(out string) (int, bool) { var reply struct { Data [][]string `json:"data"` } if json.Unmarshal([]byte(strings.TrimSpace(out)), &reply) != nil || len(reply.Data) != 1 { return 0, false } n := 0 for _, name := range reply.Data[0] { if strings.HasPrefix(name, ":") { n++ } } return n, true } // Health is the system bus's health now: a ping through the watcher's connection, how many // connections the bus has, and how long it has run. func (m *Machine) Health(ctx context.Context, w *Watcher) map[string]any { h := map[string]any{"bus": "system"} if w != nil { took, err := w.PingNow() if err != nil { h["ping"] = "no answer: " + err.Error() } else { h["ping_ms"] = float64(took.Microseconds()) / 1000 } h["watcher"] = w.Snapshot() } // Debug.Stats is root's on the system bus; asked as the account it is refused and logged as a // denial, which the watcher would then publish. So it is asked through sudo -n or not at all. call := []string{"busctl", "--system", "--json=short", "--no-pager", "call", busName, busPath} if out, err := m.privileged(ctx, call[0], append(call[1:], busName+".Debug.Stats", "GetStats")...); err == nil { if n, ok := CountConnections(out); ok { h["connections"], h["connections_from"] = n, "the bus's Debug.Stats" } } if _, ok := h["connections"]; !ok { if out, err := m.Run(ctx, call[0], append(call[1:], busName, "ListNames")...); err == nil { if n, ok := CountUniqueNames(out); ok { h["connections"], h["connections_from"] = n, "the unique names on the bus (Debug.Stats needs sudo -n)" } } } if u, err := m.SystemBusUnit(ctx); err != nil { h["unit"] = err.Error() } else { h["unit"], h["active"], h["pid"] = u.Unit, u.Active, u.PID if !u.Since.IsZero() { h["started"] = u.Started h["uptime"] = m.Now().Sub(u.Since).Round(time.Second).String() } } return h }