1//go:build go1.21
2// +build go1.21
3
4package log
5
6import (
7 "context"
8 "log/slog"
9 "runtime"
10 "sync/atomic"
11)
12
13// type aliases for slog.
14type (
15 slogAttr = slog.Attr
16 slogValue = slog.Value
17 slogLogValuer = slog.LogValuer
18)
19
20const slogKindGroup = slog.KindGroup
21
22// Enabled reports whether the logger is enabled for the given level.
23//
24// Implements slog.Handler.
25func (l *Logger) Enabled(_ context.Context, level slog.Level) bool {
26 return atomic.LoadInt64(&l.level) <= int64(level)
27}
28
29// Handle handles the Record. It will only be called if Enabled returns true.
30//
31// Implements slog.Handler.
32func (l *Logger) Handle(ctx context.Context, record slog.Record) error {
33 if !l.Enabled(ctx, record.Level) {
34 return nil
35 }
36
37 fields := make([]interface{}, 0, record.NumAttrs()*2)
38 record.Attrs(func(a slog.Attr) bool {
39 fields = append(fields, a.Key, a.Value)
40 return true
41 })
42 // Get the caller frame using the record's PC.
43 frames := runtime.CallersFrames([]uintptr{record.PC})
44 frame, _ := frames.Next()
45 l.handle(Level(record.Level), l.timeFunc(record.Time), []runtime.Frame{frame}, record.Message, fields...)
46 return nil
47}
48
49// WithAttrs returns a new Handler with the given attributes added.
50//
51// Implements slog.Handler.
52func (l *Logger) WithAttrs(attrs []slog.Attr) slog.Handler {
53 fields := make([]interface{}, 0, len(attrs)*2)
54 for _, attr := range attrs {
55 fields = append(fields, attr.Key, attr.Value)
56 }
57 return l.With(fields...)
58}
59
60// WithGroup returns a new Handler with the given group name prepended to the
61// current group name or prefix.
62//
63// Implements slog.Handler.
64func (l *Logger) WithGroup(name string) slog.Handler {
65 if l.prefix != "" {
66 name = l.prefix + "." + name
67 }
68 return l.WithPrefix(name)
69}
70
71var _ slog.Handler = (*Logger)(nil)