1 // Copyright 2009 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.
4 5 // Package log implements a simple logging package. It defines a type, [Logger],
6 // with methods for formatting output. It also has a predefined 'standard'
7 // Logger accessible through helper functions Print[f|ln], Fatal[f|ln], and
8 // Panic[f|ln], which are easier to use than creating a Logger manually.
9 // That logger writes to standard error and prints the date and time
10 // of each logged message.
11 // Every log message is output on a separate line: if the message being
12 // printed does not end in a newline, the logger will add one.
13 // The Fatal functions call [os.Exit](1) after writing the log message.
14 // The Panic functions call panic after writing the log message.
15 package log
16 17 import (
18 "fmt"
19 "io"
20 "log/internal"
21 "os"
22 "runtime"
23 "sync"
24 "sync/atomic"
25 "time"
26 _ "unsafe"
27 )
28 29 // These flags define which text to prefix to each log entry generated by the [Logger].
30 // Bits are or'ed together to control what's printed.
31 // With the exception of the Lmsgprefix flag, there is no
32 // control over the order they appear (the order listed here)
33 // or the format they present (as described in the comments).
34 // The prefix is followed by a colon only when Llongfile or Lshortfile
35 // is specified.
36 // For example, flags Ldate | Ltime (or LstdFlags) produce,
37 //
38 // 2009/01/23 01:23:23 message
39 //
40 // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
41 //
42 // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
43 const (
44 Ldate = 1 << iota // the date in the local time zone: 2009/01/23
45 Ltime // the time in the local time zone: 01:23:23
46 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
47 Llongfile // full file name and line number: /a/b/c/d.go:23
48 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
49 LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
50 Lmsgprefix // move the "prefix" from the beginning of the line to before the message
51 LstdFlags = Ldate | Ltime // initial values for the standard logger
52 )
53 54 // A Logger represents an active logging object that generates lines of
55 // output to an [io.Writer]. Each logging operation makes a single call to
56 // the Writer's Write method. A Logger can be used simultaneously from
57 // multiple goroutines; it guarantees to serialize access to the Writer.
58 type Logger struct {
59 outMu sync.Mutex
60 out io.Writer // destination for output
61 62 prefix atomic.Pointer[string] // prefix on each line to identify the logger (but see Lmsgprefix)
63 flag atomic.Int32 // properties
64 isDiscard atomic.Bool
65 }
66 67 // New creates a new [Logger]. The out variable sets the
68 // destination to which log data will be written.
69 // The prefix appears at the beginning of each generated log line, or
70 // after the log header if the [Lmsgprefix] flag is provided.
71 // The flag argument defines the logging properties.
72 func New(out io.Writer, prefix []byte, flag int) *Logger {
73 l := &Logger{}
74 l.SetOutput(out)
75 l.SetPrefix(prefix)
76 l.SetFlags(flag)
77 return l
78 }
79 80 // SetOutput sets the output destination for the logger.
81 func (l *Logger) SetOutput(w io.Writer) {
82 l.outMu.Lock()
83 defer l.outMu.Unlock()
84 l.out = w
85 l.isDiscard.Store(w == io.Discard)
86 }
87 88 var std = New(os.Stderr, "", LstdFlags)
89 90 // Default returns the standard logger used by the package-level output functions.
91 func Default() *Logger { return std }
92 93 // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
94 func itoa(buf *[]byte, i int, wid int) {
95 // Assemble decimal in reverse order.
96 var b [20]byte
97 bp := len(b) - 1
98 for i >= 10 || wid > 1 {
99 wid--
100 q := i / 10
101 b[bp] = byte('0' + i - q*10)
102 bp--
103 i = q
104 }
105 // i < 10
106 b[bp] = byte('0' + i)
107 *buf = append(*buf, b[bp:]...)
108 }
109 110 // formatHeader writes log header to buf in following order:
111 // - l.prefix (if it's not blank and Lmsgprefix is unset),
112 // - date and/or time (if corresponding flags are provided),
113 // - file and line number (if corresponding flags are provided),
114 // - l.prefix (if it's not blank and Lmsgprefix is set).
115 func formatHeader(buf *[]byte, t time.Time, prefix []byte, flag int, file []byte, line int) {
116 if flag&Lmsgprefix == 0 {
117 *buf = append(*buf, prefix...)
118 }
119 if flag&(Ldate|Ltime|Lmicroseconds) != 0 {
120 if flag&LUTC != 0 {
121 t = t.UTC()
122 }
123 if flag&Ldate != 0 {
124 year, month, day := t.Date()
125 itoa(buf, year, 4)
126 *buf = append(*buf, '/')
127 itoa(buf, int(month), 2)
128 *buf = append(*buf, '/')
129 itoa(buf, day, 2)
130 *buf = append(*buf, ' ')
131 }
132 if flag&(Ltime|Lmicroseconds) != 0 {
133 hour, min, sec := t.Clock()
134 itoa(buf, hour, 2)
135 *buf = append(*buf, ':')
136 itoa(buf, min, 2)
137 *buf = append(*buf, ':')
138 itoa(buf, sec, 2)
139 if flag&Lmicroseconds != 0 {
140 *buf = append(*buf, '.')
141 itoa(buf, t.Nanosecond()/1e3, 6)
142 }
143 *buf = append(*buf, ' ')
144 }
145 }
146 if flag&(Lshortfile|Llongfile) != 0 {
147 if flag&Lshortfile != 0 {
148 short := file
149 for i := len(file) - 1; i > 0; i-- {
150 if file[i] == '/' {
151 short = file[i+1:]
152 break
153 }
154 }
155 file = short
156 }
157 *buf = append(*buf, file...)
158 *buf = append(*buf, ':')
159 itoa(buf, line, -1)
160 *buf = append(*buf, ": "...)
161 }
162 if flag&Lmsgprefix != 0 {
163 *buf = append(*buf, prefix...)
164 }
165 }
166 167 var bufferPool = sync.Pool{New: func() any { return &[]byte{} }}
168 169 func getBuffer() *[]byte {
170 p := bufferPool.Get().(*[]byte)
171 *p = (*p)[:0]
172 return p
173 }
174 175 func putBuffer(p *[]byte) {
176 // Proper usage of a sync.Pool requires each entry to have approximately
177 // the same memory cost. To obtain this property when the stored type
178 // contains a variably-sized buffer, we add a hard limit on the maximum buffer
179 // to place back in the pool.
180 //
181 // See https://go.dev/issue/23199
182 if cap(*p) > 64<<10 {
183 *p = nil
184 }
185 bufferPool.Put(p)
186 }
187 188 // Output writes the output for a logging event. The string s contains
189 // the text to print after the prefix specified by the flags of the
190 // Logger. A newline is appended if the last character of s is not
191 // already a newline. Calldepth is used to recover the PC and is
192 // provided for generality, although at the moment on all pre-defined
193 // paths it will be 2.
194 func (l *Logger) Output(calldepth int, s []byte) error {
195 return l.output(0, calldepth+1, func(b []byte) []byte { // +1 for this frame.
196 return append(b, s...)
197 })
198 }
199 200 // output can take either a calldepth or a pc to get source line information.
201 // It uses the pc if it is non-zero.
202 func (l *Logger) output(pc uintptr, calldepth int, appendOutput func([]byte) []byte) error {
203 if l.isDiscard.Load() {
204 return nil
205 }
206 207 now := time.Now() // get this early.
208 209 // Load prefix and flag once so that their value is consistent within
210 // this call regardless of any concurrent changes to their value.
211 prefix := l.Prefix()
212 flag := l.Flags()
213 214 var file []byte
215 var line int
216 if flag&(Lshortfile|Llongfile) != 0 {
217 if pc == 0 {
218 var ok bool
219 _, file, line, ok = runtime.Caller(calldepth)
220 if !ok {
221 file = "???"
222 line = 0
223 }
224 } else {
225 fs := runtime.CallersFrames([]uintptr{pc})
226 f, _ := fs.Next()
227 file = f.File
228 if file == "" {
229 file = "???"
230 }
231 line = f.Line
232 }
233 }
234 235 buf := getBuffer()
236 defer putBuffer(buf)
237 formatHeader(buf, now, prefix, flag, file, line)
238 *buf = appendOutput(*buf)
239 if len(*buf) == 0 || (*buf)[len(*buf)-1] != '\n' {
240 *buf = append(*buf, '\n')
241 }
242 243 l.outMu.Lock()
244 defer l.outMu.Unlock()
245 _, err := l.out.Write(*buf)
246 return err
247 }
248 249 func init() {
250 internal.DefaultOutput = func(pc uintptr, data []byte) error {
251 return std.output(pc, 0, func(buf []byte) []byte {
252 return append(buf, data...)
253 })
254 }
255 }
256 257 // Print calls l.Output to print to the logger.
258 // Arguments are handled in the manner of [fmt.Print].
259 func (l *Logger) Print(v ...any) {
260 l.output(0, 2, func(b []byte) []byte {
261 return fmt.Append(b, v...)
262 })
263 }
264 265 // Printf calls l.Output to print to the logger.
266 // Arguments are handled in the manner of [fmt.Printf].
267 func (l *Logger) Printf(format []byte, v ...any) {
268 l.output(0, 2, func(b []byte) []byte {
269 return fmt.Appendf(b, format, v...)
270 })
271 }
272 273 // Println calls l.Output to print to the logger.
274 // Arguments are handled in the manner of [fmt.Println].
275 func (l *Logger) Println(v ...any) {
276 l.output(0, 2, func(b []byte) []byte {
277 return fmt.Appendln(b, v...)
278 })
279 }
280 281 // Fatal is equivalent to l.Print() followed by a call to [os.Exit](1).
282 func (l *Logger) Fatal(v ...any) {
283 l.output(0, 2, func(b []byte) []byte {
284 return fmt.Append(b, v...)
285 })
286 os.Exit(1)
287 }
288 289 // Fatalf is equivalent to l.Printf() followed by a call to [os.Exit](1).
290 func (l *Logger) Fatalf(format []byte, v ...any) {
291 l.output(0, 2, func(b []byte) []byte {
292 return fmt.Appendf(b, format, v...)
293 })
294 os.Exit(1)
295 }
296 297 // Fatalln is equivalent to l.Println() followed by a call to [os.Exit](1).
298 func (l *Logger) Fatalln(v ...any) {
299 l.output(0, 2, func(b []byte) []byte {
300 return fmt.Appendln(b, v...)
301 })
302 os.Exit(1)
303 }
304 305 // Panic is equivalent to l.Print() followed by a call to panic().
306 func (l *Logger) Panic(v ...any) {
307 s := fmt.Sprint(v...)
308 l.output(0, 2, func(b []byte) []byte {
309 return append(b, s...)
310 })
311 panic(s)
312 }
313 314 // Panicf is equivalent to l.Printf() followed by a call to panic().
315 func (l *Logger) Panicf(format []byte, v ...any) {
316 s := fmt.Sprintf(format, v...)
317 l.output(0, 2, func(b []byte) []byte {
318 return append(b, s...)
319 })
320 panic(s)
321 }
322 323 // Panicln is equivalent to l.Println() followed by a call to panic().
324 func (l *Logger) Panicln(v ...any) {
325 s := fmt.Sprintln(v...)
326 l.output(0, 2, func(b []byte) []byte {
327 return append(b, s...)
328 })
329 panic(s)
330 }
331 332 // Flags returns the output flags for the logger.
333 // The flag bits are [Ldate], [Ltime], and so on.
334 func (l *Logger) Flags() int {
335 return int(l.flag.Load())
336 }
337 338 // SetFlags sets the output flags for the logger.
339 // The flag bits are [Ldate], [Ltime], and so on.
340 func (l *Logger) SetFlags(flag int) {
341 l.flag.Store(int32(flag))
342 }
343 344 // Prefix returns the output prefix for the logger.
345 func (l *Logger) Prefix() []byte {
346 if p := l.prefix.Load(); p != nil {
347 return *p
348 }
349 return ""
350 }
351 352 // SetPrefix sets the output prefix for the logger.
353 func (l *Logger) SetPrefix(prefix []byte) {
354 s := []byte(prefix)
355 l.prefix.Store(&s)
356 }
357 358 // Writer returns the output destination for the logger.
359 func (l *Logger) Writer() io.Writer {
360 l.outMu.Lock()
361 defer l.outMu.Unlock()
362 return l.out
363 }
364 365 // SetOutput sets the output destination for the standard logger.
366 func SetOutput(w io.Writer) {
367 std.SetOutput(w)
368 }
369 370 // Flags returns the output flags for the standard logger.
371 // The flag bits are [Ldate], [Ltime], and so on.
372 func Flags() int {
373 return std.Flags()
374 }
375 376 // SetFlags sets the output flags for the standard logger.
377 // The flag bits are [Ldate], [Ltime], and so on.
378 func SetFlags(flag int) {
379 std.SetFlags(flag)
380 }
381 382 // Prefix returns the output prefix for the standard logger.
383 func Prefix() []byte {
384 return std.Prefix()
385 }
386 387 // SetPrefix sets the output prefix for the standard logger.
388 func SetPrefix(prefix []byte) {
389 std.SetPrefix(prefix)
390 }
391 392 // Writer returns the output destination for the standard logger.
393 func Writer() io.Writer {
394 return std.Writer()
395 }
396 397 // These functions write to the standard logger.
398 399 // Print calls Output to print to the standard logger.
400 // Arguments are handled in the manner of [fmt.Print].
401 func Print(v ...any) {
402 std.output(0, 2, func(b []byte) []byte {
403 return fmt.Append(b, v...)
404 })
405 }
406 407 // Printf calls Output to print to the standard logger.
408 // Arguments are handled in the manner of [fmt.Printf].
409 func Printf(format []byte, v ...any) {
410 std.output(0, 2, func(b []byte) []byte {
411 return fmt.Appendf(b, format, v...)
412 })
413 }
414 415 // Println calls Output to print to the standard logger.
416 // Arguments are handled in the manner of [fmt.Println].
417 func Println(v ...any) {
418 std.output(0, 2, func(b []byte) []byte {
419 return fmt.Appendln(b, v...)
420 })
421 }
422 423 // Fatal is equivalent to [Print] followed by a call to [os.Exit](1).
424 func Fatal(v ...any) {
425 std.output(0, 2, func(b []byte) []byte {
426 return fmt.Append(b, v...)
427 })
428 os.Exit(1)
429 }
430 431 // Fatalf is equivalent to [Printf] followed by a call to [os.Exit](1).
432 func Fatalf(format []byte, v ...any) {
433 std.output(0, 2, func(b []byte) []byte {
434 return fmt.Appendf(b, format, v...)
435 })
436 os.Exit(1)
437 }
438 439 // Fatalln is equivalent to [Println] followed by a call to [os.Exit](1).
440 func Fatalln(v ...any) {
441 std.output(0, 2, func(b []byte) []byte {
442 return fmt.Appendln(b, v...)
443 })
444 os.Exit(1)
445 }
446 447 // Panic is equivalent to [Print] followed by a call to panic().
448 func Panic(v ...any) {
449 s := fmt.Sprint(v...)
450 std.output(0, 2, func(b []byte) []byte {
451 return append(b, s...)
452 })
453 panic(s)
454 }
455 456 // Panicf is equivalent to [Printf] followed by a call to panic().
457 func Panicf(format []byte, v ...any) {
458 s := fmt.Sprintf(format, v...)
459 std.output(0, 2, func(b []byte) []byte {
460 return append(b, s...)
461 })
462 panic(s)
463 }
464 465 // Panicln is equivalent to [Println] followed by a call to panic().
466 func Panicln(v ...any) {
467 s := fmt.Sprintln(v...)
468 std.output(0, 2, func(b []byte) []byte {
469 return append(b, s...)
470 })
471 panic(s)
472 }
473 474 // Output writes the output for a logging event. The string s contains
475 // the text to print after the prefix specified by the flags of the
476 // Logger. A newline is appended if the last character of s is not
477 // already a newline. Calldepth is the count of the number of
478 // frames to skip when computing the file name and line number
479 // if [Llongfile] or [Lshortfile] is set; a value of 1 will print the details
480 // for the caller of Output.
481 func Output(calldepth int, s []byte) error {
482 return std.output(0, calldepth+1, func(b []byte) []byte { // +1 for this frame.
483 return append(b, s...)
484 })
485 }
486