github.com/richardwilkes/toolbox@v1.121.0/log/multilog/multilog.go (about) 1 package multilog 2 3 import ( 4 "context" 5 "log/slog" 6 7 "github.com/richardwilkes/toolbox/errs" 8 ) 9 10 var _ slog.Handler = &Handler{} 11 12 // Handler is a slog.Handler that fans out log records to multiple other handlers. 13 type Handler struct { 14 handlers []slog.Handler 15 } 16 17 // New creates a new Handler that fans out log records to the provided handlers. 18 func New(handlers ...slog.Handler) *Handler { 19 return &Handler{handlers: handlers} 20 } 21 22 // Enabled implements slog.Handler. 23 func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool { 24 for _, h := range h.handlers { 25 if h.Enabled(ctx, level) { 26 return true 27 } 28 } 29 return false 30 } 31 32 // WithGroup implements slog.Handler. 33 func (h *Handler) WithGroup(name string) slog.Handler { 34 if name == "" { 35 return h 36 } 37 handlers := make([]slog.Handler, len(h.handlers)) 38 for i, one := range h.handlers { 39 handlers[i] = one.WithGroup(name) 40 } 41 return &Handler{handlers: handlers} 42 } 43 44 // WithAttrs implements slog.Handler. 45 func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler { 46 handlers := make([]slog.Handler, len(h.handlers)) 47 for i, one := range h.handlers { 48 handlers[i] = one.WithAttrs(attrs) 49 } 50 return &Handler{handlers: handlers} 51 } 52 53 // Handle implements slog.Handler. 54 func (h *Handler) Handle(ctx context.Context, r slog.Record) error { //nolint:gocritic // Must use defined API 55 var result error 56 for _, one := range h.handlers { 57 if one.Enabled(ctx, r.Level) { 58 result = errs.Append(result, runHandler(ctx, &r, one)) 59 } 60 } 61 return result 62 } 63 64 func runHandler(ctx context.Context, r *slog.Record, h slog.Handler) (err error) { 65 defer errs.Recovery(func(rerr error) { err = rerr }) 66 err = h.Handle(ctx, r.Clone()) 67 return err 68 }