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  }