1 // Copyright 2022 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
10 loginternal "log/internal"
17 var defaultLogger atomic.Pointer[Logger]
20 defaultLogger.Store(New(newDefaultHandler(loginternal.DefaultOutput)))
23 // Default returns the default [Logger].
24 func Default() *Logger { return defaultLogger.Load() }
26 // SetDefault makes l the default [Logger].
27 // After this call, output from the log package's default Logger
28 // (as with [log.Print], etc.) will be logged at [LevelInfo] using l's Handler.
29 func SetDefault(l *Logger) {
30 defaultLogger.Store(l)
31 // If the default's handler is a defaultHandler, then don't use a handleWriter,
32 // or we'll deadlock as they both try to acquire the log default mutex.
33 // The defaultHandler will use whatever the log default writer is currently
34 // set to, which is correct.
35 // This can occur with SetDefault(Default()).
36 // See TestSetDefault.
37 if _, ok := l.Handler().(*defaultHandler); !ok {
38 capturePC := log.Flags()&(log.Lshortfile|log.Llongfile) != 0
39 log.SetOutput(&handlerWriter{l.Handler(), LevelInfo, capturePC})
40 log.SetFlags(0) // we want just the log message, no time or location
44 // handlerWriter is an io.Writer that calls a Handler.
45 // It is used to link the default log.Logger to the default slog.Logger.
46 type handlerWriter struct {
52 func (w *handlerWriter) Write(buf []byte) (int, error) {
53 if !w.h.Enabled(context.Background(), w.level) {
57 if !internal.IgnorePC && w.capturePC {
58 // skip [runtime.Callers, w.Write, Logger.Output, log.Print]
60 runtime.Callers(4, pcs[:])
64 // Remove final newline.
65 origLen := len(buf) // Report that the entire buf was written.
66 if len(buf) > 0 && buf[len(buf)-1] == '\n' {
67 buf = buf[:len(buf)-1]
69 r := NewRecord(time.Now(), w.level, string(buf), pc)
70 return origLen, w.h.Handle(context.Background(), r)
73 // A Logger records structured information about each call to its
74 // Log, Debug, Info, Warn, and Error methods.
75 // For each call, it creates a [Record] and passes it to a [Handler].
77 // To create a new Logger, call [New] or a Logger method
78 // that begins "With".
80 handler Handler // for structured logging
83 func (l *Logger) clone() *Logger {
88 // Handler returns l's Handler.
89 func (l *Logger) Handler() Handler { return l.handler }
91 // With returns a Logger that includes the given attributes
92 // in each output operation. Arguments are converted to
93 // attributes as if by [Logger.Log].
94 func (l *Logger) With(args ...any) *Logger {
99 c.handler = l.handler.WithAttrs(argsToAttrSlice(args))
103 // WithGroup returns a Logger that starts a group, if name is non-empty.
104 // The keys of all attributes added to the Logger will be qualified by the given
105 // name. (How that qualification happens depends on the [Handler.WithGroup]
106 // method of the Logger's Handler.)
108 // If name is empty, WithGroup returns the receiver.
109 func (l *Logger) WithGroup(name string) *Logger {
114 c.handler = l.handler.WithGroup(name)
119 // New creates a new Logger with the given non-nil Handler.
120 func New(h Handler) *Logger {
124 return &Logger{handler: h}
127 // With calls [Logger.With] on the default logger.
128 func With(args ...any) *Logger {
129 return Default().With(args...)
132 // Enabled reports whether l emits log records at the given context and level.
133 func (l *Logger) Enabled(ctx context.Context, level Level) bool {
135 ctx = context.Background()
137 return l.Handler().Enabled(ctx, level)
140 // NewLogLogger returns a new [log.Logger] such that each call to its Output method
141 // dispatches a Record to the specified handler. The logger acts as a bridge from
142 // the older log API to newer structured logging handlers.
143 func NewLogLogger(h Handler, level Level) *log.Logger {
144 return log.New(&handlerWriter{h, level, true}, "", 0)
147 // Log emits a log record with the current time and the given level and message.
148 // The Record's Attrs consist of the Logger's attributes followed by
149 // the Attrs specified by args.
151 // The attribute arguments are processed as follows:
152 // - If an argument is an Attr, it is used as is.
153 // - If an argument is a string and this is not the last argument,
154 // the following argument is treated as the value and the two are combined
156 // - Otherwise, the argument is treated as a value with key "!BADKEY".
157 func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) {
158 l.log(ctx, level, msg, args...)
161 // LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs.
162 func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
163 l.logAttrs(ctx, level, msg, attrs...)
166 // Debug logs at [LevelDebug].
167 func (l *Logger) Debug(msg string, args ...any) {
168 l.log(context.Background(), LevelDebug, msg, args...)
171 // DebugContext logs at [LevelDebug] with the given context.
172 func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) {
173 l.log(ctx, LevelDebug, msg, args...)
176 // Info logs at [LevelInfo].
177 func (l *Logger) Info(msg string, args ...any) {
178 l.log(context.Background(), LevelInfo, msg, args...)
181 // InfoContext logs at [LevelInfo] with the given context.
182 func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) {
183 l.log(ctx, LevelInfo, msg, args...)
186 // Warn logs at [LevelWarn].
187 func (l *Logger) Warn(msg string, args ...any) {
188 l.log(context.Background(), LevelWarn, msg, args...)
191 // WarnContext logs at [LevelWarn] with the given context.
192 func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) {
193 l.log(ctx, LevelWarn, msg, args...)
196 // Error logs at [LevelError].
197 func (l *Logger) Error(msg string, args ...any) {
198 l.log(context.Background(), LevelError, msg, args...)
201 // ErrorContext logs at [LevelError] with the given context.
202 func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) {
203 l.log(ctx, LevelError, msg, args...)
206 // log is the low-level logging method for methods that take ...any.
207 // It must always be called directly by an exported logging method
208 // or function, because it uses a fixed call depth to obtain the pc.
209 func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) {
210 if !l.Enabled(ctx, level) {
214 if !internal.IgnorePC {
216 // skip [runtime.Callers, this function, this function's caller]
217 runtime.Callers(3, pcs[:])
220 r := NewRecord(time.Now(), level, msg, pc)
223 ctx = context.Background()
225 _ = l.Handler().Handle(ctx, r)
228 // logAttrs is like [Logger.log], but for methods that take ...Attr.
229 func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
230 if !l.Enabled(ctx, level) {
234 if !internal.IgnorePC {
236 // skip [runtime.Callers, this function, this function's caller]
237 runtime.Callers(3, pcs[:])
240 r := NewRecord(time.Now(), level, msg, pc)
243 ctx = context.Background()
245 _ = l.Handler().Handle(ctx, r)
248 // Debug calls [Logger.Debug] on the default logger.
249 func Debug(msg string, args ...any) {
250 Default().log(context.Background(), LevelDebug, msg, args...)
253 // DebugContext calls [Logger.DebugContext] on the default logger.
254 func DebugContext(ctx context.Context, msg string, args ...any) {
255 Default().log(ctx, LevelDebug, msg, args...)
258 // Info calls [Logger.Info] on the default logger.
259 func Info(msg string, args ...any) {
260 Default().log(context.Background(), LevelInfo, msg, args...)
263 // InfoContext calls [Logger.InfoContext] on the default logger.
264 func InfoContext(ctx context.Context, msg string, args ...any) {
265 Default().log(ctx, LevelInfo, msg, args...)
268 // Warn calls [Logger.Warn] on the default logger.
269 func Warn(msg string, args ...any) {
270 Default().log(context.Background(), LevelWarn, msg, args...)
273 // WarnContext calls [Logger.WarnContext] on the default logger.
274 func WarnContext(ctx context.Context, msg string, args ...any) {
275 Default().log(ctx, LevelWarn, msg, args...)
278 // Error calls [Logger.Error] on the default logger.
279 func Error(msg string, args ...any) {
280 Default().log(context.Background(), LevelError, msg, args...)
283 // ErrorContext calls [Logger.ErrorContext] on the default logger.
284 func ErrorContext(ctx context.Context, msg string, args ...any) {
285 Default().log(ctx, LevelError, msg, args...)
288 // Log calls [Logger.Log] on the default logger.
289 func Log(ctx context.Context, level Level, msg string, args ...any) {
290 Default().log(ctx, level, msg, args...)
293 // LogAttrs calls [Logger.LogAttrs] on the default logger.
294 func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
295 Default().logAttrs(ctx, level, msg, attrs...)