logger/slog: wrap handler

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2024-11-24 23:28:15 +03:00
parent d1c6e121c1
commit 9dd3ed1e46

View File

@ -31,6 +31,28 @@ var (
fatalValue = slog.StringValue("fatal") fatalValue = slog.StringValue("fatal")
) )
type wrapper struct {
h slog.Handler
level logger.Level
}
func (h *wrapper) Enabled(ctx context.Context, level slog.Level) bool {
lvl := slogToLoggerLevel(level)
return h.level.Enabled(lvl)
}
func (h *wrapper) Handle(ctx context.Context, rec slog.Record) error {
return h.h.Handle(ctx, rec)
}
func (h *wrapper) WithAttrs(attrs []slog.Attr) slog.Handler {
return h.WithAttrs(attrs)
}
func (h *wrapper) WithGroup(name string) slog.Handler {
return h.WithGroup(name)
}
func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr { func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr {
switch a.Key { switch a.Key {
case slog.SourceKey: case slog.SourceKey:
@ -68,7 +90,7 @@ func (s *slogLogger) renameAttr(_ []string, a slog.Attr) slog.Attr {
type slogLogger struct { type slogLogger struct {
leveler *slog.LevelVar leveler *slog.LevelVar
handler slog.Handler handler *wrapper
opts logger.Options opts logger.Options
mu sync.RWMutex mu sync.RWMutex
} }
@ -76,19 +98,21 @@ type slogLogger struct {
func (s *slogLogger) Clone(opts ...logger.Option) logger.Logger { func (s *slogLogger) Clone(opts ...logger.Option) logger.Logger {
s.mu.RLock() s.mu.RLock()
options := s.opts options := s.opts
level := s.leveler.Level()
s.mu.RUnlock() s.mu.RUnlock()
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
l := &slogLogger{opts: options} if len(options.ContextAttrFuncs) == 0 {
options.ContextAttrFuncs = logger.DefaultContextAttrFuncs
}
l.leveler = new(slog.LevelVar) attrs, _ := s.argsAttrs(options.Fields)
l.leveler.Set(level) l := &slogLogger{
attrs, _ := s.argsAttrs(l.opts.Fields) handler: &wrapper{level: options.Level, h: s.handler.h.WithAttrs(attrs)},
l.handler = s.handler.WithAttrs(attrs) opts: options,
}
return l return l
} }
@ -98,7 +122,9 @@ func (s *slogLogger) V(level logger.Level) bool {
} }
func (s *slogLogger) Level(level logger.Level) { func (s *slogLogger) Level(level logger.Level) {
s.leveler.Set(loggerToSlogLevel(level)) s.mu.Lock()
s.opts.Level = level
s.mu.Unlock()
} }
func (s *slogLogger) Options() logger.Options { func (s *slogLogger) Options() logger.Options {
@ -107,16 +133,17 @@ func (s *slogLogger) Options() logger.Options {
func (s *slogLogger) Fields(fields ...interface{}) logger.Logger { func (s *slogLogger) Fields(fields ...interface{}) logger.Logger {
s.mu.RLock() s.mu.RLock()
level := s.leveler.Level()
options := s.opts options := s.opts
s.mu.RUnlock() s.mu.RUnlock()
l := &slogLogger{opts: options} l := &slogLogger{opts: options}
l.leveler = new(slog.LevelVar)
l.leveler.Set(level) if len(options.ContextAttrFuncs) == 0 {
options.ContextAttrFuncs = logger.DefaultContextAttrFuncs
}
attrs, _ := s.argsAttrs(fields) attrs, _ := s.argsAttrs(fields)
l.handler = s.handler.WithAttrs(attrs) l.handler = &wrapper{level: s.opts.Level, h: s.handler.h.WithAttrs(attrs)}
return l return l
} }
@ -124,22 +151,22 @@ func (s *slogLogger) Fields(fields ...interface{}) logger.Logger {
func (s *slogLogger) Init(opts ...logger.Option) error { func (s *slogLogger) Init(opts ...logger.Option) error {
s.mu.Lock() s.mu.Lock()
if len(s.opts.ContextAttrFuncs) == 0 {
s.opts.ContextAttrFuncs = logger.DefaultContextAttrFuncs
}
for _, o := range opts { for _, o := range opts {
o(&s.opts) o(&s.opts)
} }
s.leveler = new(slog.LevelVar) if len(s.opts.ContextAttrFuncs) == 0 {
s.opts.ContextAttrFuncs = logger.DefaultContextAttrFuncs
}
handleOpt := &slog.HandlerOptions{ handleOpt := &slog.HandlerOptions{
ReplaceAttr: s.renameAttr, ReplaceAttr: s.renameAttr,
Level: s.leveler, Level: loggerToSlogLevel(logger.TraceLevel),
AddSource: s.opts.AddSource, AddSource: s.opts.AddSource,
} }
s.leveler.Set(loggerToSlogLevel(s.opts.Level))
s.handler = slog.New(slog.NewJSONHandler(s.opts.Out, handleOpt)).With(s.opts.Fields...).Handler() attrs, _ := s.argsAttrs(s.opts.Fields)
s.handler = &wrapper{level: s.opts.Level, h: slog.NewJSONHandler(s.opts.Out, handleOpt).WithAttrs(attrs)}
s.mu.Unlock() s.mu.Unlock()
return nil return nil