github.com/searKing/golang/go@v1.2.117/log/slog/multi.go (about)

     1  // Copyright 2023 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package slog
     6  
     7  import (
     8  	"context"
     9  	"log/slog"
    10  )
    11  
    12  var _ slog.Handler = (*multiHandler)(nil)
    13  
    14  type multiHandler []slog.Handler
    15  
    16  func (t multiHandler) Enabled(ctx context.Context, level slog.Level) bool {
    17  	for _, w := range t {
    18  		if w != nil && w.Enabled(ctx, level) {
    19  			return true
    20  		}
    21  	}
    22  	return false
    23  }
    24  
    25  func (t multiHandler) Handle(ctx context.Context, record slog.Record) error {
    26  	for _, w := range t {
    27  		if w == nil || !w.Enabled(ctx, record.Level) {
    28  			continue
    29  		}
    30  		if err := w.Handle(ctx, record); err != nil {
    31  			return err
    32  		}
    33  	}
    34  	return nil
    35  }
    36  
    37  func (t multiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    38  	var handlers []slog.Handler
    39  	for _, w := range t {
    40  		if w != nil {
    41  			handlers = append(handlers, w.WithAttrs(attrs))
    42  		}
    43  	}
    44  	return MultiHandler(handlers...)
    45  }
    46  
    47  func (t multiHandler) WithGroup(name string) slog.Handler {
    48  	var handlers []slog.Handler
    49  	for _, w := range t {
    50  		if w != nil {
    51  			handlers = append(handlers, w.WithGroup(name))
    52  		}
    53  	}
    54  	return MultiHandler(handlers...)
    55  }
    56  
    57  // MultiHandler creates a slog.Handler that duplicates its writes to all the
    58  // provided handlers, similar to the Unix tee(1) command.
    59  //
    60  // Each write is written to each listed writer, one at a time.
    61  // If a listed writer returns an error, that overall write operation
    62  // stops and returns the error; it does not continue down the list.
    63  func MultiHandler(handlers ...slog.Handler) slog.Handler {
    64  	allHandlers := make([]slog.Handler, 0, len(handlers))
    65  	for _, w := range handlers {
    66  		if w == nil {
    67  			continue
    68  		}
    69  		if mw, ok := w.(multiHandler); ok {
    70  			allHandlers = append(allHandlers, mw...)
    71  		} else {
    72  			allHandlers = append(allHandlers, w)
    73  		}
    74  	}
    75  	return multiHandler(allHandlers)
    76  }
    77  
    78  // MultiReplaceAttr creates a [ReplaceAttr] that call all the provided replacers one by one
    79  func MultiReplaceAttr(replacers ...func(groups []string, a slog.Attr) slog.Attr) func(groups []string, a slog.Attr) slog.Attr {
    80  	return func(groups []string, a slog.Attr) slog.Attr {
    81  		for _, h := range replacers {
    82  			if h != nil {
    83  				a = h(groups, a)
    84  			}
    85  		}
    86  		return a
    87  	}
    88  }