Source file src/log/log.go
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 "os" 21 "runtime" 22 "sync" 23 "sync/atomic" 24 "time" 25 ) 26 27 // These flags define which text to prefix to each log entry generated by the Logger. 28 // Bits are or'ed together to control what's printed. 29 // With the exception of the Lmsgprefix flag, there is no 30 // control over the order they appear (the order listed here) 31 // or the format they present (as described in the comments). 32 // The prefix is followed by a colon only when Llongfile or Lshortfile 33 // is specified. 34 // For example, flags Ldate | Ltime (or LstdFlags) produce, 35 // 36 // 2009/01/23 01:23:23 message 37 // 38 // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce, 39 // 40 // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message 41 const ( 42 Ldate = 1 << iota // the date in the local time zone: 2009/01/23 43 Ltime // the time in the local time zone: 01:23:23 44 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 45 Llongfile // full file name and line number: /a/b/c/d.go:23 46 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 47 LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone 48 Lmsgprefix // move the "prefix" from the beginning of the line to before the message 49 LstdFlags = Ldate | Ltime // initial values for the standard logger 50 ) 51 52 // A Logger represents an active logging object that generates lines of 53 // output to an io.Writer. Each logging operation makes a single call to 54 // the Writer's Write method. A Logger can be used simultaneously from 55 // multiple goroutines; it guarantees to serialize access to the Writer. 56 type Logger struct { 57 mu sync.Mutex // ensures atomic writes; protects the following fields 58 prefix string // prefix on each line to identify the logger (but see Lmsgprefix) 59 flag int // properties 60 out io.Writer // destination for output 61 buf []byte // for accumulating text to write 62 isDiscard atomic.Bool // whether out == io.Discard 63 } 64 65 // New creates a new Logger. The out variable sets the 66 // destination to which log data will be written. 67 // The prefix appears at the beginning of each generated log line, or 68 // after the log header if the Lmsgprefix flag is provided. 69 // The flag argument defines the logging properties. 70 func New(out io.Writer, prefix string, flag int) *Logger { 71 l := &Logger{out: out, prefix: prefix, flag: flag} 72 if out == io.Discard { 73 l.isDiscard.Store(true) 74 } 75 return l 76 } 77 78 // SetOutput sets the output destination for the logger. 79 func (l *Logger) SetOutput(w io.Writer) { 80 l.mu.Lock() 81 defer l.mu.Unlock() 82 l.out = w 83 l.isDiscard.Store(w == io.Discard) 84 } 85 86 var std = New(os.Stderr, "", LstdFlags) 87 88 // Default returns the standard logger used by the package-level output functions. 89 func Default() *Logger { return std } 90 91 // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. 92 func itoa(buf *[]byte, i int, wid int) { 93 // Assemble decimal in reverse order. 94 var b [20]byte 95 bp := len(b) - 1 96 for i >= 10 || wid > 1 { 97 wid-- 98 q := i / 10 99 b[bp] = byte('0' + i - q*10) 100 bp-- 101 i = q 102 } 103 // i < 10 104 b[bp] = byte('0' + i) 105 *buf = append(*buf, b[bp:]...) 106 } 107 108 // formatHeader writes log header to buf in following order: 109 // - l.prefix (if it's not blank and Lmsgprefix is unset), 110 // - date and/or time (if corresponding flags are provided), 111 // - file and line number (if corresponding flags are provided), 112 // - l.prefix (if it's not blank and Lmsgprefix is set). 113 func (l *Logger) formatHeader(buf *[]byte, t time.Time, file string, line int) { 114 if l.flag&Lmsgprefix == 0 { 115 *buf = append(*buf, l.prefix...) 116 } 117 if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 { 118 if l.flag&LUTC != 0 { 119 t = t.UTC() 120 } 121 if l.flag&Ldate != 0 { 122 year, month, day := t.Date() 123 itoa(buf, year, 4) 124 *buf = append(*buf, '/') 125 itoa(buf, int(month), 2) 126 *buf = append(*buf, '/') 127 itoa(buf, day, 2) 128 *buf = append(*buf, ' ') 129 } 130 if l.flag&(Ltime|Lmicroseconds) != 0 { 131 hour, min, sec := t.Clock() 132 itoa(buf, hour, 2) 133 *buf = append(*buf, ':') 134 itoa(buf, min, 2) 135 *buf = append(*buf, ':') 136 itoa(buf, sec, 2) 137 if l.flag&Lmicroseconds != 0 { 138 *buf = append(*buf, '.') 139 itoa(buf, t.Nanosecond()/1e3, 6) 140 } 141 *buf = append(*buf, ' ') 142 } 143 } 144 if l.flag&(Lshortfile|Llongfile) != 0 { 145 if l.flag&Lshortfile != 0 { 146 short := file 147 for i := len(file) - 1; i > 0; i-- { 148 if file[i] == '/' { 149 short = file[i+1:] 150 break 151 } 152 } 153 file = short 154 } 155 *buf = append(*buf, file...) 156 *buf = append(*buf, ':') 157 itoa(buf, line, -1) 158 *buf = append(*buf, ": "...) 159 } 160 if l.flag&Lmsgprefix != 0 { 161 *buf = append(*buf, l.prefix...) 162 } 163 } 164 165 // Output writes the output for a logging event. The string s contains 166 // the text to print after the prefix specified by the flags of the 167 // Logger. A newline is appended if the last character of s is not 168 // already a newline. Calldepth is used to recover the PC and is 169 // provided for generality, although at the moment on all pre-defined 170 // paths it will be 2. 171 func (l *Logger) Output(calldepth int, s string) error { 172 now := time.Now() // get this early. 173 var file string 174 var line int 175 l.mu.Lock() 176 defer l.mu.Unlock() 177 if l.flag&(Lshortfile|Llongfile) != 0 { 178 // Release lock while getting caller info - it's expensive. 179 l.mu.Unlock() 180 var ok bool 181 _, file, line, ok = runtime.Caller(calldepth) 182 if !ok { 183 file = "???" 184 line = 0 185 } 186 l.mu.Lock() 187 } 188 l.buf = l.buf[:0] 189 l.formatHeader(&l.buf, now, file, line) 190 l.buf = append(l.buf, s...) 191 if len(s) == 0 || s[len(s)-1] != '\n' { 192 l.buf = append(l.buf, '\n') 193 } 194 _, err := l.out.Write(l.buf) 195 return err 196 } 197 198 // Printf calls l.Output to print to the logger. 199 // Arguments are handled in the manner of fmt.Printf. 200 func (l *Logger) Printf(format string, v ...any) { 201 if l.isDiscard.Load() { 202 return 203 } 204 l.Output(2, fmt.Sprintf(format, v...)) 205 } 206 207 // Print calls l.Output to print to the logger. 208 // Arguments are handled in the manner of fmt.Print. 209 func (l *Logger) Print(v ...any) { 210 if l.isDiscard.Load() { 211 return 212 } 213 l.Output(2, fmt.Sprint(v...)) 214 } 215 216 // Println calls l.Output to print to the logger. 217 // Arguments are handled in the manner of fmt.Println. 218 func (l *Logger) Println(v ...any) { 219 if l.isDiscard.Load() { 220 return 221 } 222 l.Output(2, fmt.Sprintln(v...)) 223 } 224 225 // Fatal is equivalent to l.Print() followed by a call to os.Exit(1). 226 func (l *Logger) Fatal(v ...any) { 227 l.Output(2, fmt.Sprint(v...)) 228 os.Exit(1) 229 } 230 231 // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). 232 func (l *Logger) Fatalf(format string, v ...any) { 233 l.Output(2, fmt.Sprintf(format, v...)) 234 os.Exit(1) 235 } 236 237 // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). 238 func (l *Logger) Fatalln(v ...any) { 239 l.Output(2, fmt.Sprintln(v...)) 240 os.Exit(1) 241 } 242 243 // Panic is equivalent to l.Print() followed by a call to panic(). 244 func (l *Logger) Panic(v ...any) { 245 s := fmt.Sprint(v...) 246 l.Output(2, s) 247 panic(s) 248 } 249 250 // Panicf is equivalent to l.Printf() followed by a call to panic(). 251 func (l *Logger) Panicf(format string, v ...any) { 252 s := fmt.Sprintf(format, v...) 253 l.Output(2, s) 254 panic(s) 255 } 256 257 // Panicln is equivalent to l.Println() followed by a call to panic(). 258 func (l *Logger) Panicln(v ...any) { 259 s := fmt.Sprintln(v...) 260 l.Output(2, s) 261 panic(s) 262 } 263 264 // Flags returns the output flags for the logger. 265 // The flag bits are Ldate, Ltime, and so on. 266 func (l *Logger) Flags() int { 267 l.mu.Lock() 268 defer l.mu.Unlock() 269 return l.flag 270 } 271 272 // SetFlags sets the output flags for the logger. 273 // The flag bits are Ldate, Ltime, and so on. 274 func (l *Logger) SetFlags(flag int) { 275 l.mu.Lock() 276 defer l.mu.Unlock() 277 l.flag = flag 278 } 279 280 // Prefix returns the output prefix for the logger. 281 func (l *Logger) Prefix() string { 282 l.mu.Lock() 283 defer l.mu.Unlock() 284 return l.prefix 285 } 286 287 // SetPrefix sets the output prefix for the logger. 288 func (l *Logger) SetPrefix(prefix string) { 289 l.mu.Lock() 290 defer l.mu.Unlock() 291 l.prefix = prefix 292 } 293 294 // Writer returns the output destination for the logger. 295 func (l *Logger) Writer() io.Writer { 296 l.mu.Lock() 297 defer l.mu.Unlock() 298 return l.out 299 } 300 301 // SetOutput sets the output destination for the standard logger. 302 func SetOutput(w io.Writer) { 303 std.SetOutput(w) 304 } 305 306 // Flags returns the output flags for the standard logger. 307 // The flag bits are Ldate, Ltime, and so on. 308 func Flags() int { 309 return std.Flags() 310 } 311 312 // SetFlags sets the output flags for the standard logger. 313 // The flag bits are Ldate, Ltime, and so on. 314 func SetFlags(flag int) { 315 std.SetFlags(flag) 316 } 317 318 // Prefix returns the output prefix for the standard logger. 319 func Prefix() string { 320 return std.Prefix() 321 } 322 323 // SetPrefix sets the output prefix for the standard logger. 324 func SetPrefix(prefix string) { 325 std.SetPrefix(prefix) 326 } 327 328 // Writer returns the output destination for the standard logger. 329 func Writer() io.Writer { 330 return std.Writer() 331 } 332 333 // These functions write to the standard logger. 334 335 // Print calls Output to print to the standard logger. 336 // Arguments are handled in the manner of fmt.Print. 337 func Print(v ...any) { 338 if std.isDiscard.Load() { 339 return 340 } 341 std.Output(2, fmt.Sprint(v...)) 342 } 343 344 // Printf calls Output to print to the standard logger. 345 // Arguments are handled in the manner of fmt.Printf. 346 func Printf(format string, v ...any) { 347 if std.isDiscard.Load() { 348 return 349 } 350 std.Output(2, fmt.Sprintf(format, v...)) 351 } 352 353 // Println calls Output to print to the standard logger. 354 // Arguments are handled in the manner of fmt.Println. 355 func Println(v ...any) { 356 if std.isDiscard.Load() { 357 return 358 } 359 std.Output(2, fmt.Sprintln(v...)) 360 } 361 362 // Fatal is equivalent to Print() followed by a call to os.Exit(1). 363 func Fatal(v ...any) { 364 std.Output(2, fmt.Sprint(v...)) 365 os.Exit(1) 366 } 367 368 // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). 369 func Fatalf(format string, v ...any) { 370 std.Output(2, fmt.Sprintf(format, v...)) 371 os.Exit(1) 372 } 373 374 // Fatalln is equivalent to Println() followed by a call to os.Exit(1). 375 func Fatalln(v ...any) { 376 std.Output(2, fmt.Sprintln(v...)) 377 os.Exit(1) 378 } 379 380 // Panic is equivalent to Print() followed by a call to panic(). 381 func Panic(v ...any) { 382 s := fmt.Sprint(v...) 383 std.Output(2, s) 384 panic(s) 385 } 386 387 // Panicf is equivalent to Printf() followed by a call to panic(). 388 func Panicf(format string, v ...any) { 389 s := fmt.Sprintf(format, v...) 390 std.Output(2, s) 391 panic(s) 392 } 393 394 // Panicln is equivalent to Println() followed by a call to panic(). 395 func Panicln(v ...any) { 396 s := fmt.Sprintln(v...) 397 std.Output(2, s) 398 panic(s) 399 } 400 401 // Output writes the output for a logging event. The string s contains 402 // the text to print after the prefix specified by the flags of the 403 // Logger. A newline is appended if the last character of s is not 404 // already a newline. Calldepth is the count of the number of 405 // frames to skip when computing the file name and line number 406 // if Llongfile or Lshortfile is set; a value of 1 will print the details 407 // for the caller of Output. 408 func Output(calldepth int, s string) error { 409 return std.Output(calldepth+1, s) // +1 for this frame. 410 } 411