github.com/shogo82148/goa-v1@v1.6.2/logging/slog/adapter.go (about) 1 //go:build go1.21 2 // +build go1.21 3 4 /* 5 Package goaslog contains an adapter that makes it possible to configure goa so it uses [log/slog] 6 as logger backend. 7 Usage: 8 9 handler := slog.NewJSONHandler(os.Stderr, nil) 10 // Initialize logger handler using [log/slog] package 11 service.WithLogger(goaslog.New(handler)) 12 // ... Proceed with configuring and starting the goa service 13 14 // In handlers: 15 goaslog.Entry(ctx).Info("foo", "bar") 16 */ 17 package goaslog 18 19 import ( 20 "context" 21 "log/slog" 22 "runtime" 23 "time" 24 25 "github.com/shogo82148/goa-v1" 26 ) 27 28 var _ goa.LogAdapter = (*adapter)(nil) 29 var _ goa.ContextLogAdapter = (*adapter)(nil) 30 31 // adapter is the slog goa logger adapter. 32 type adapter struct { 33 handler slog.Handler 34 } 35 36 // New wraps a [log/slog.Handler] into a goa logger. 37 func New(handler slog.Handler) goa.LogAdapter { 38 return &adapter{handler: handler} 39 } 40 41 // Info logs messages using [log/slog]. 42 func (a *adapter) Info(msg string, data ...any) { 43 a.log(context.Background(), slog.LevelInfo, msg, data...) 44 } 45 46 // InfoContext logs messages using [log/slog]. 47 func (a *adapter) InfoContext(ctx context.Context, msg string, data ...any) { 48 a.log(ctx, slog.LevelInfo, msg, data...) 49 } 50 51 // Warn logs message using [log/slog]. 52 func (a *adapter) Warn(msg string, data ...any) { 53 a.log(context.Background(), slog.LevelWarn, msg, data...) 54 } 55 56 // WarnContext logs message using [log/slog]. 57 func (a *adapter) WarnContext(ctx context.Context, msg string, data ...any) { 58 a.log(ctx, slog.LevelWarn, msg, data...) 59 } 60 61 // Error logs errors using [log/slog]. 62 func (a *adapter) Error(msg string, data ...any) { 63 a.log(context.Background(), slog.LevelError, msg, data...) 64 } 65 66 // ErrorContext logs errors using [log/slog]. 67 func (a *adapter) ErrorContext(ctx context.Context, msg string, data ...any) { 68 a.log(ctx, slog.LevelError, msg, data...) 69 } 70 71 // New creates a new logger given a context. 72 func (a *adapter) New(data ...any) goa.LogAdapter { 73 r := slog.NewRecord(time.Now(), slog.LevelInfo, "", 0) 74 r.Add(data...) 75 76 attrs := make([]slog.Attr, 0, r.NumAttrs()) 77 r.Attrs(func(a slog.Attr) bool { 78 attrs = append(attrs, a) 79 return true 80 }) 81 h := a.handler.WithAttrs(attrs) 82 return &adapter{handler: h} 83 } 84 85 func (a *adapter) log(ctx context.Context, level slog.Level, msg string, data ...any) { 86 if !a.handler.Enabled(ctx, level) { 87 return 88 } 89 90 var pc uintptr 91 var pcs [1]uintptr 92 // skip [runtime.Callers, this functions, this functions caller, the caller of the adapter] 93 runtime.Callers(4, pcs[:]) 94 pc = pcs[0] 95 r := slog.NewRecord(time.Now(), level, msg, pc) 96 r.Add(data...) 97 a.handler.Handle(ctx, r) 98 }