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.Value
20 defaultLogger.Store(New(newDefaultHandler(loginternal.DefaultOutput)))
23 // Default returns the default Logger.
24 func Default() *Logger { return defaultLogger.Load().(*Logger) }
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 new Logger that includes the given arguments, converted to
92 // Attrs as in [Logger.Log].
93 // The Attrs will be added to each output from the Logger.
94 // The new Logger shares the old Logger's context.
95 // The new Logger's handler is the result of calling WithAttrs on the receiver's
97 func (l *Logger) With(args ...any) *Logger {
99 c.handler = l.handler.WithAttrs(argsToAttrSlice(args))
103 // WithGroup returns a new Logger that starts a group. The keys of all
104 // attributes added to the Logger will be qualified by the given name.
105 // (How that qualification happens depends on the [Handler.WithGroup]
106 // method of the Logger's Handler.)
107 // The new Logger shares the old Logger's context.
109 // The new Logger's handler is the result of calling WithGroup on the receiver's
111 func (l *Logger) WithGroup(name string) *Logger {
113 c.handler = l.handler.WithGroup(name)
118 // New creates a new Logger with the given non-nil Handler and a nil context.
119 func New(h Handler) *Logger {
123 return &Logger{handler: h}
126 // With calls Logger.With on the default logger.
127 func With(args ...any) *Logger {
128 return Default().With(args...)
131 // Enabled reports whether l emits log records at the given context and level.
132 func (l *Logger) Enabled(ctx context.Context, level Level) bool {
134 ctx = context.Background()
136 return l.Handler().Enabled(ctx, level)
139 // NewLogLogger returns a new log.Logger such that each call to its Output method
140 // dispatches a Record to the specified handler. The logger acts as a bridge from
141 // the older log API to newer structured logging handlers.
142 func NewLogLogger(h Handler, level Level) *log.Logger {
143 return log.New(&handlerWriter{h, level, true}, "", 0)
146 // Log emits a log record with the current time and the given level and message.
147 // The Record's Attrs consist of the Logger's attributes followed by
148 // the Attrs specified by args.
150 // The attribute arguments are processed as follows:
151 // - If an argument is an Attr, it is used as is.
152 // - If an argument is a string and this is not the last argument,
153 // the following argument is treated as the value and the two are combined
155 // - Otherwise, the argument is treated as a value with key "!BADKEY".
156 func (l *Logger) Log(ctx context.Context, level Level, msg string, args ...any) {
157 l.log(ctx, level, msg, args...)
160 // LogAttrs is a more efficient version of [Logger.Log] that accepts only Attrs.
161 func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
162 l.logAttrs(ctx, level, msg, attrs...)
165 // Debug logs at LevelDebug.
166 func (l *Logger) Debug(msg string, args ...any) {
167 l.log(nil, LevelDebug, msg, args...)
170 // DebugCtx logs at LevelDebug with the given context.
171 func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) {
172 l.log(ctx, LevelDebug, msg, args...)
175 // Info logs at LevelInfo.
176 func (l *Logger) Info(msg string, args ...any) {
177 l.log(nil, LevelInfo, msg, args...)
180 // InfoCtx logs at LevelInfo with the given context.
181 func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) {
182 l.log(ctx, LevelInfo, msg, args...)
185 // Warn logs at LevelWarn.
186 func (l *Logger) Warn(msg string, args ...any) {
187 l.log(nil, LevelWarn, msg, args...)
190 // WarnCtx logs at LevelWarn with the given context.
191 func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) {
192 l.log(ctx, LevelWarn, msg, args...)
195 // Error logs at LevelError.
196 func (l *Logger) Error(msg string, args ...any) {
197 l.log(nil, LevelError, msg, args...)
200 // ErrorCtx logs at LevelError with the given context.
201 func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) {
202 l.log(ctx, LevelError, msg, args...)
205 // log is the low-level logging method for methods that take ...any.
206 // It must always be called directly by an exported logging method
207 // or function, because it uses a fixed call depth to obtain the pc.
208 func (l *Logger) log(ctx context.Context, level Level, msg string, args ...any) {
209 if !l.Enabled(ctx, level) {
213 if !internal.IgnorePC {
215 // skip [runtime.Callers, this function, this function's caller]
216 runtime.Callers(3, pcs[:])
219 r := NewRecord(time.Now(), level, msg, pc)
222 ctx = context.Background()
224 _ = l.Handler().Handle(ctx, r)
227 // logAttrs is like [Logger.log], but for methods that take ...Attr.
228 func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
229 if !l.Enabled(ctx, level) {
233 if !internal.IgnorePC {
235 // skip [runtime.Callers, this function, this function's caller]
236 runtime.Callers(3, pcs[:])
239 r := NewRecord(time.Now(), level, msg, pc)
242 ctx = context.Background()
244 _ = l.Handler().Handle(ctx, r)
247 // Debug calls Logger.Debug on the default logger.
248 func Debug(msg string, args ...any) {
249 Default().log(nil, LevelDebug, msg, args...)
252 // DebugCtx calls Logger.DebugCtx on the default logger.
253 func DebugCtx(ctx context.Context, msg string, args ...any) {
254 Default().log(ctx, LevelDebug, msg, args...)
257 // Info calls Logger.Info on the default logger.
258 func Info(msg string, args ...any) {
259 Default().log(nil, LevelInfo, msg, args...)
262 // InfoCtx calls Logger.InfoCtx on the default logger.
263 func InfoCtx(ctx context.Context, msg string, args ...any) {
264 Default().log(ctx, LevelInfo, msg, args...)
267 // Warn calls Logger.Warn on the default logger.
268 func Warn(msg string, args ...any) {
269 Default().log(nil, LevelWarn, msg, args...)
272 // WarnCtx calls Logger.WarnCtx on the default logger.
273 func WarnCtx(ctx context.Context, msg string, args ...any) {
274 Default().log(ctx, LevelWarn, msg, args...)
277 // Error calls Logger.Error on the default logger.
278 func Error(msg string, args ...any) {
279 Default().log(nil, LevelError, msg, args...)
282 // ErrorCtx calls Logger.ErrorCtx on the default logger.
283 func ErrorCtx(ctx context.Context, msg string, args ...any) {
284 Default().log(ctx, LevelError, msg, args...)
287 // Log calls Logger.Log on the default logger.
288 func Log(ctx context.Context, level Level, msg string, args ...any) {
289 Default().log(ctx, level, msg, args...)
292 // LogAttrs calls Logger.LogAttrs on the default logger.
293 func LogAttrs(ctx context.Context, level Level, msg string, attrs ...Attr) {
294 Default().logAttrs(ctx, level, msg, attrs...)