github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/logger/slog.go (about)

     1  package logger
     2  
     3  import (
     4  	"context"
     5  	"log/slog"
     6  
     7  	"github.com/go-logr/logr"
     8  	"go.uber.org/zap/exp/zapslog"
     9  )
    10  
    11  // NewSlogDiscard creates a slog.Handler that discards all logs.
    12  func NewSlogDiscard() slog.Handler {
    13  	return slogDiscard{}
    14  }
    15  
    16  // ToSlogHandler converts Logger to slog.Handler.
    17  func ToSlogHandler(log Logger) slog.Handler {
    18  	switch log := log.(type) {
    19  	case ZapLogger:
    20  		zlog := log.ToZap().Desugar()
    21  		return zapslog.NewHandler(zlog.Core(), &zapslog.HandlerOptions{AddSource: true})
    22  	case LogRLogger:
    23  		return logr.ToSlogHandler(log.toLogr())
    24  	}
    25  	return slogHandler{log, ""}
    26  }
    27  
    28  type slogDiscard struct{}
    29  
    30  func (_ slogDiscard) Enabled(ctx context.Context, level slog.Level) bool {
    31  	return false
    32  }
    33  
    34  func (_ slogDiscard) Handle(ctx context.Context, record slog.Record) error {
    35  	return nil
    36  }
    37  
    38  func (l slogDiscard) WithAttrs(attrs []slog.Attr) slog.Handler {
    39  	return l
    40  }
    41  
    42  func (l slogDiscard) WithGroup(name string) slog.Handler {
    43  	return l
    44  }
    45  
    46  type slogHandler struct {
    47  	log   Logger
    48  	group string
    49  }
    50  
    51  func (l slogHandler) Enabled(ctx context.Context, level slog.Level) bool {
    52  	return true // so such method on Logger
    53  }
    54  
    55  func (l slogHandler) getGroup() string {
    56  	group := l.group
    57  	if group != "" {
    58  		group = group + "."
    59  	}
    60  	return group
    61  }
    62  
    63  func (l slogHandler) Handle(ctx context.Context, r slog.Record) error {
    64  	keysAndValues := make([]any, 0, r.NumAttrs()*2)
    65  	group := l.getGroup()
    66  	r.Attrs(func(attr slog.Attr) bool {
    67  		keysAndValues = append(keysAndValues, group+attr.Key, attr.Value.Resolve().Any())
    68  		return true
    69  	})
    70  	switch r.Level {
    71  	case slog.LevelDebug:
    72  		l.log.Debugw(r.Message, keysAndValues...)
    73  	default:
    74  		fallthrough
    75  	case slog.LevelInfo:
    76  		l.log.Infow(r.Message, keysAndValues...)
    77  	case slog.LevelWarn:
    78  		l.log.Warnw(r.Message, nil, keysAndValues...)
    79  	case slog.LevelError:
    80  		l.log.Errorw(r.Message, nil, keysAndValues...)
    81  	}
    82  	return nil
    83  }
    84  
    85  func (l slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
    86  	log := l.log
    87  	keysAndValues := make([]any, 0, len(attrs)*2)
    88  	group := l.getGroup()
    89  	for _, attr := range attrs {
    90  		keysAndValues = append(keysAndValues, group+attr.Key, attr.Value.Resolve().Any())
    91  	}
    92  	log = log.WithValues(keysAndValues...)
    93  	return slogHandler{log, l.group}
    94  }
    95  
    96  func (l slogHandler) WithGroup(name string) slog.Handler {
    97  	group := name
    98  	if l.group != "" {
    99  		group = l.group + "." + name
   100  	}
   101  	return slogHandler{l.log, group}
   102  }