Source file
src/log/slog/logger.go
1
2
3
4
5 package slog
6
7 import (
8 "bytes"
9 "context"
10 "log"
11 loginternal "log/internal"
12 "log/slog/internal"
13 "runtime"
14 "sync/atomic"
15 "time"
16 )
17
18 var defaultLogger atomic.Pointer[Logger]
19
20 var logLoggerLevel LevelVar
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 func SetLogLoggerLevel(level Level) (oldLevel Level) {
45 oldLevel = logLoggerLevel.Level()
46 logLoggerLevel.Set(level)
47 return
48 }
49
50 func init() {
51 defaultLogger.Store(New(newDefaultHandler(loginternal.DefaultOutput)))
52 }
53
54
55 func Default() *Logger { return defaultLogger.Load() }
56
57
58
59
60
61
62 func SetDefault(l *Logger) {
63 defaultLogger.Store(l)
64
65
66
67
68
69
70 if _, ok := l.Handler().(*defaultHandler); !ok {
71 capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0
72 log.SetOutput(&handlerWriter{l.Handler(), &logLoggerLevel, capturePC})
73 log.SetFlags(0)
74 }
75 }
76
77
78
79 type handlerWriter struct {
80 h Handler
81 level Leveler
82 capturePC bool
83 }
84
85 func (w *handlerWriter) Write(buf []byte) (int, error) {
86 level := w.level.Level()
87 if !w.h.Enabled(context.Background(), level) {
88 return 0, nil
89 }
90 var pc uintptr
91 if !internal.IgnorePC && w.capturePC {
92
93 var pcs [1]uintptr
94 runtime.Callers(4, pcs[:])
95 pc = pcs[0]
96 }
97
98
99 origLen := len(buf)
100 buf = bytes.TrimSuffix(buf, []byte{'\n'})
101 r := NewRecord(time.Now(), level, string(buf), pc)
102 return origLen, w.h.Handle(context.Background(), r)
103 }
104
105
106
107
108
109
110
111 type Logger struct {
112 handler Handler
113 }
114
115 func (l *Logger) clone() *Logger {
116 c := *l
117 return &c
118 }
119
120
121 func (l *Logger) Handler() Handler { return l.handler }
122
123
124
125
126 func (l *Logger) With(args ...any) *Logger {
127 if len(args) == 0 {
128 return l
129 }
130 c := l.clone()
131 c.handler = l.handler.WithAttrs(argsToAttrSlice(args))
132 return c
133 }
134
135
136
137
138
139
140
141 func (l *Logger) WithGroup(name string) *Logger {
142 if name == "" {
143 return l
144 }
145 c := l.clone()
146 c.handler = l.handler.WithGroup(name)
147 return c
148 }
149
150
151 func New(h Handler) *Logger {
152 if h == nil {
153 panic("nil Handler")
154 }
155 return &Logger{handler: h}
156 }
157
158
159 func With(args ...any) *Logger {
160 return Default().With(args...)
161 }
162
163
164 func (l *Logger) Enabled(ctx context.Context, level Level) bool {
165 if ctx == nil {
166 ctx = context.Background()
167 }
168 return l.Handler().Enabled(ctx, level)
169 }
170
171
172
173
174 func NewLogLogger(h Handler, level Level) *log.Logger {
175 return log.New(&handlerWriter{h, level, true}, "", 0)
176 }
177
178
179
180
181
182
183
184
185
186
187
188 func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) {
189 l.log(ctx, level, msg, args...)
190 }
191
192
193 func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
194 l.logAttrs(ctx, level, msg, attrs...)
195 }
196
197
198 func (l *Logger) Debug(msg string, args ...any) {
199 l.log(context.Background(), LevelDebug, msg, args...)
200 }
201
202
203 func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) {
204 l.log(ctx, LevelDebug, msg, args...)
205 }
206
207
208 func (l *Logger) Info(msg string, args ...any) {
209 l.log(context.Background(), LevelInfo, msg, args...)
210 }
211
212
213 func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) {
214 l.log(ctx, LevelInfo, msg, args...)
215 }
216
217
218 func (l *Logger) Warn(msg string, args ...any) {
219 l.log(context.Background(), LevelWarn, msg, args...)
220 }
221
222
223 func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) {
224 l.log(ctx, LevelWarn, msg, args...)
225 }
226
227
228 func (l *Logger) Error(msg string, args ...any) {
229 l.log(context.Background(), LevelError, msg, args...)
230 }
231
232
233 func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) {
234 l.log(ctx, LevelError, msg, args...)
235 }
236
237
238
239
240 func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) {
241 if !l.Enabled(ctx, level) {
242 return
243 }
244 var pc uintptr
245 if !internal.IgnorePC {
246 var pcs [1]uintptr
247
248 runtime.Callers(3, pcs[:])
249 pc = pcs[0]
250 }
251 r := NewRecord(time.Now(), level, msg, pc)
252 r.Add(args...)
253 if ctx == nil {
254 ctx = context.Background()
255 }
256 _ = l.Handler().Handle(ctx, r)
257 }
258
259
260 func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
261 if !l.Enabled(ctx, level) {
262 return
263 }
264 var pc uintptr
265 if !internal.IgnorePC {
266 var pcs [1]uintptr
267
268 runtime.Callers(3, pcs[:])
269 pc = pcs[0]
270 }
271 r := NewRecord(time.Now(), level, msg, pc)
272 r.AddAttrs(attrs...)
273 if ctx == nil {
274 ctx = context.Background()
275 }
276 _ = l.Handler().Handle(ctx, r)
277 }
278
279
280 func Debug(msg string, args ...any) {
281 Default().log(context.Background(), LevelDebug, msg, args...)
282 }
283
284
285 func DebugContext(ctx context.Context, msg string, args ...any) {
286 Default().log(ctx, LevelDebug, msg, args...)
287 }
288
289
290 func Info(msg string, args ...any) {
291 Default().log(context.Background(), LevelInfo, msg, args...)
292 }
293
294
295 func InfoContext(ctx context.Context, msg string, args ...any) {
296 Default().log(ctx, LevelInfo, msg, args...)
297 }
298
299
300 func Warn(msg string, args ...any) {
301 Default().log(context.Background(), LevelWarn, msg, args...)
302 }
303
304
305 func WarnContext(ctx context.Context, msg string, args ...any) {
306 Default().log(ctx, LevelWarn, msg, args...)
307 }
308
309
310 func Error(msg string, args ...any) {
311 Default().log(context.Background(), LevelError, msg, args...)
312 }
313
314
315 func ErrorContext(ctx context.Context, msg string, args ...any) {
316 Default().log(ctx, LevelError, msg, args...)
317 }
318
319
320 func Log(ctx context.Context, level Level, msg string, args ...any) {
321 Default().log(ctx, level, msg, args...)
322 }
323
324
325 func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
326 Default().logAttrs(ctx, level, msg, attrs...)
327 }
328
View as plain text