package server import "sync/atomic" // HandlerStats aggregates the per-transport counters plus the engine's own // view. It is the "what is this thing doing right now" summary the admin API // and the health endpoint read. type HandlerStats struct { // Queries is every query the server accepted across all transports. Queries uint64 `json:"queries"` // Blocked is queries answered by a blocklist rule. Blocked uint64 `json:"blocked"` // Cached is queries answered from the cache. Cached uint64 `json:"cached"` // Errors is queries answered with SERVFAIL, dropped or malformed. Errors uint64 `json:"errors"` // Dropped is queries answered with silence. Dropped uint64 `json:"dropped"` // Inflight is the current in-flight count. Inflight int64 `json:"inflight"` } // ByTransport returns a per-transport breakdown for the UI's transport tab. func (s *Server) ByTransport() map[string]TransportStats { out := map[string]TransportStats{} for _, t := range []string{"udp", "tcp", "dot", "doh"} { ts := TransportStats{Transport: t} ts.Queries = s.load(t, "queries") ts.Blocked = s.load(t, "blocked") ts.Cached = s.load(t, "cached") ts.Errors = s.load(t, "errors") ts.Truncated = s.load(t, "truncated") ts.Sent = s.load(t, "sent") out[t] = ts } return out } func (s *Server) load(transport, field string) uint64 { v, ok := s.counters.Load(transport + "." + field) if !ok { return 0 } return v.(*atomic.Uint64).Load() } // TransportStats is a per-transport counter set. type TransportStats struct { Transport string `json:"transport"` Queries uint64 `json:"queries"` Blocked uint64 `json:"blocked"` Cached uint64 `json:"cached"` Errors uint64 `json:"errors"` Truncated uint64 `json:"truncated"` Sent uint64 `json:"sent"` }