Files
fancy-dns/internal/server/stats.go
T
developer e8c5b414d9
build / build-push (push) Failing after 23s
half broken
2026-09-27 17:17:53 +00:00

64 lines
2.2 KiB
Go

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.Dropped = s.load(t, "dropped")
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"`
// Dropped is queries answered with silence on this transport. It is
// bumped for every transport (a DoH drop used to be counted as an error
// only, which made the console's transport tab under-report it), and
// aggregating it per transport is the only way the UI can show it: the
// aggregate in HandlerStats cannot say which transport dropped.
Dropped uint64 `json:"dropped"`
Truncated uint64 `json:"truncated"`
Sent uint64 `json:"sent"`
}