...
1
2
3
4
19
20 package logr
21
22 import (
23 "context"
24 "log/slog"
25 )
26
27 type slogHandler struct {
28
29 sink LogSink
30
31 slogSink SlogSink
32
33
34
35 groupPrefix string
36
37
38
39
40
41
42 levelBias slog.Level
43 }
44
45 var _ slog.Handler = &slogHandler{}
46
47
48 const groupSeparator = "."
49
50
51 func (l *slogHandler) GetLevel() slog.Level {
52 return l.levelBias
53 }
54
55 func (l *slogHandler) Enabled(_ context.Context, level slog.Level) bool {
56 return l.sink != nil && (level >= slog.LevelError || l.sink.Enabled(l.levelFromSlog(level)))
57 }
58
59 func (l *slogHandler) Handle(ctx context.Context, record slog.Record) error {
60 if l.slogSink != nil {
61
62 if record.Level < slog.LevelError {
63 record.Level -= l.levelBias
64 }
65 return l.slogSink.Handle(ctx, record)
66 }
67
68
69
70
71 kvList := make([]any, 0, 2*record.NumAttrs())
72 record.Attrs(func(attr slog.Attr) bool {
73 kvList = attrToKVs(attr, l.groupPrefix, kvList)
74 return true
75 })
76 if record.Level >= slog.LevelError {
77 l.sinkWithCallDepth().Error(nil, record.Message, kvList...)
78 } else {
79 level := l.levelFromSlog(record.Level)
80 l.sinkWithCallDepth().Info(level, record.Message, kvList...)
81 }
82 return nil
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96 func (l *slogHandler) sinkWithCallDepth() LogSink {
97 if sink, ok := l.sink.(CallDepthLogSink); ok {
98 return sink.WithCallDepth(2)
99 }
100 return l.sink
101 }
102
103 func (l *slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
104 if l.sink == nil || len(attrs) == 0 {
105 return l
106 }
107
108 clone := *l
109 if l.slogSink != nil {
110 clone.slogSink = l.slogSink.WithAttrs(attrs)
111 clone.sink = clone.slogSink
112 } else {
113 kvList := make([]any, 0, 2*len(attrs))
114 for _, attr := range attrs {
115 kvList = attrToKVs(attr, l.groupPrefix, kvList)
116 }
117 clone.sink = l.sink.WithValues(kvList...)
118 }
119 return &clone
120 }
121
122 func (l *slogHandler) WithGroup(name string) slog.Handler {
123 if l.sink == nil {
124 return l
125 }
126 if name == "" {
127
128 return l
129 }
130 clone := *l
131 if l.slogSink != nil {
132 clone.slogSink = l.slogSink.WithGroup(name)
133 clone.sink = clone.slogSink
134 } else {
135 clone.groupPrefix = addPrefix(clone.groupPrefix, name)
136 }
137 return &clone
138 }
139
140
141
142 func attrToKVs(attr slog.Attr, groupPrefix string, kvList []any) []any {
143 attrVal := attr.Value.Resolve()
144 if attrVal.Kind() == slog.KindGroup {
145 groupVal := attrVal.Group()
146 grpKVs := make([]any, 0, 2*len(groupVal))
147 prefix := groupPrefix
148 if attr.Key != "" {
149 prefix = addPrefix(groupPrefix, attr.Key)
150 }
151 for _, attr := range groupVal {
152 grpKVs = attrToKVs(attr, prefix, grpKVs)
153 }
154 kvList = append(kvList, grpKVs...)
155 } else if attr.Key != "" {
156 kvList = append(kvList, addPrefix(groupPrefix, attr.Key), attrVal.Any())
157 }
158
159 return kvList
160 }
161
162 func addPrefix(prefix, name string) string {
163 if prefix == "" {
164 return name
165 }
166 if name == "" {
167 return prefix
168 }
169 return prefix + groupSeparator + name
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 func (l *slogHandler) levelFromSlog(level slog.Level) int {
186 result := -level
187 result += l.levelBias
188 if result < 0 {
189 result = 0
190 }
191 return int(result)
192 }
193
View as plain text