package broker import ( "context" "log/slog" "github.com/mochi-mqtt/server/v2/packets" ) type redactHandler struct { inner slog.Handler } func newRedactHandler(inner slog.Handler) slog.Handler { if inner == nil { inner = slog.Default().Handler() } return &redactHandler{inner: inner} } func (h *redactHandler) Enabled(ctx context.Context, level slog.Level) bool { return h.inner.Enabled(ctx, level) } func (h *redactHandler) Handle(ctx context.Context, r slog.Record) error { rec := slog.NewRecord(r.Time, r.Level, r.Message, r.PC) r.Attrs(func(a slog.Attr) bool { rec.AddAttrs(redactSlogAttr(a)) return true }) return h.inner.Handle(ctx, rec) } func (h *redactHandler) WithAttrs(attrs []slog.Attr) slog.Handler { out := make([]slog.Attr, len(attrs)) for i, a := range attrs { out[i] = redactSlogAttr(a) } return &redactHandler{inner: h.inner.WithAttrs(out)} } func (h *redactHandler) WithGroup(name string) slog.Handler { return &redactHandler{inner: h.inner.WithGroup(name)} } func redactSlogAttr(a slog.Attr) slog.Attr { a.Value = a.Value.Resolve() switch v := a.Value.Any().(type) { case packets.Packet: return slog.Any(a.Key, summarizePacket(v)) case *packets.Packet: if v == nil { return a } return slog.Any(a.Key, summarizePacket(*v)) } if a.Value.Kind() == slog.KindGroup { group := a.Value.Group() out := make([]slog.Attr, len(group)) for i, g := range group { out[i] = redactSlogAttr(g) } return slog.Attr{Key: a.Key, Value: slog.GroupValue(out...)} } return a } type mqttPacketLog struct { Type string `json:"type"` QoS byte `json:"qos"` PacketID uint16 `json:"packet_id"` Topic string `json:"topic,omitempty"` PayloadLen int `json:"payload_len"` } func summarizePacket(pk packets.Packet) mqttPacketLog { name := packets.PacketNames[pk.FixedHeader.Type] if name == "" { name = "unknown" } return mqttPacketLog{ Type: name, QoS: pk.FixedHeader.Qos, PacketID: pk.PacketID, Topic: pk.TopicName, PayloadLen: len(pk.Payload), } }