github.com/AndrienkoAleksandr/go@v0.0.19/src/log/log.go (about) 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 ) 27 28 // These flags define which text to prefix to each log entry generated by the Logger. 29 // Bits are or'ed together to control what's printed. 30 // With the exception of the Lmsgprefix flag, there is no 31 // control over the order they appear (the order listed here) 32 // or the format they present (as described in the comments). 33 // The prefix is followed by a colon only when Llongfile or Lshortfile 34 // is specified. 35 // For example, flags Ldate | Ltime (or LstdFlags) produce, 36 // 37 // 2009/01/23 01:23:23 message 38 // 39 // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce, 40 // 41 // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message 42 const ( 43 Ldate = 1 << iota // the date in the local time zone: 2009/01/23 44 Ltime // the time in the local time zone: 01:23:23 45 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 46 Llongfile // full file name and line number: /a/b/c/d.go:23 47 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 48 LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone 49 Lmsgprefix // move the "prefix" from the beginning of the line to before the message 50 LstdFlags = Ldate | Ltime // initial values for the standard logger 51 ) 52 53 // A Logger represents an active logging object that generates lines of 54 // output to an io.Writer. Each logging operation makes a single call to 55 // the Writer's Write method. A Logger can be used simultaneously from 56 // multiple goroutines; it guarantees to serialize access to the Writer. 57 type Logger struct { 58 outMu sync.Mutex 59 out io.Writer // destination for output 60 61 prefix atomic.Pointer[string] // prefix on each line to identify the logger (but see Lmsgprefix) 62 flag atomic.Int32 // properties 63 isDiscard atomic.Bool 64 } 65 66 // New creates a new Logger. The out variable sets the 67 // destination to which log data will be written. 68 // The prefix appears at the beginning of each generated log line, or 69 // after the log header if the Lmsgprefix flag is provided. 70 // The flag argument defines the logging properties. 71 func New(out io.Writer, prefix string, flag int) *Logger { 72 l := new(Logger) 73 l.SetOutput(out) 74 l.SetPrefix(prefix) 75 l.SetFlags(flag) 76 return l 77 } 78 79 // SetOutput sets the output destination for the logger. 80 func (l *Logger) SetOutput(w io.Writer) { 81 l.outMu.Lock() 82 defer l.outMu.Unlock() 83 l.out = w 84 l.isDiscard.Store(w == io.Discard) 85 } 86 87 var std = New(os.Stderr, "", LstdFlags) 88 89 // Default returns the standard logger used by the package-level output functions. 90 func Default() *Logger { return std } 91 92 // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. 93 func itoa(buf *[]byte, i int, wid int) { 94 // Assemble decimal in reverse order. 95 var b [20]byte 96 bp := len(b) - 1 97 for i >= 10 || wid > 1 { 98 wid-- 99 q := i / 10 100 b[bp] = byte('0' + i - q*10) 101 bp-- 102 i = q 103 } 104 // i < 10 105 b[bp] = byte('0' + i) 106 *buf = append(*buf, b[bp:]...) 107 } 108 109 // formatHeader writes log header to buf in following order: 110 // - l.prefix (if it's not blank and Lmsgprefix is unset), 111 // - date and/or time (if corresponding flags are provided), 112 // - file and line number (if corresponding flags are provided), 113 // - l.prefix (if it's not blank and Lmsgprefix is set). 114 func formatHeader(buf *[]byte, t time.Time, prefix string, flag int, file string, line int) { 115 if flag&Lmsgprefix == 0 { 116 *buf = append(*buf, prefix...) 117 } 118 if flag&(Ldate|Ltime|Lmicroseconds) != 0 { 119 if flag&LUTC != 0 { 120 t = t.UTC() 121 } 122 if flag&Ldate != 0 { 123 year, month, day := t.Date() 124 itoa(buf, year, 4) 125 *buf = append(*buf, '/') 126 itoa(buf, int(month), 2) 127 *buf = append(*buf, '/') 128 itoa(buf, day, 2) 129 *buf = append(*buf, ' ') 130 } 131 if flag&(Ltime|Lmicroseconds) != 0 { 132 hour, min, sec := t.Clock() 133 itoa(buf, hour, 2) 134 *buf = append(*buf, ':') 135 itoa(buf, min, 2) 136 *buf = append(*buf, ':') 137 itoa(buf, sec, 2) 138 if flag&Lmicroseconds != 0 { 139 *buf = append(*buf, '.') 140 itoa(buf, t.Nanosecond()/1e3, 6) 141 } 142 *buf = append(*buf, ' ') 143 } 144 } 145 if flag&(Lshortfile|Llongfile) != 0 { 146 if flag&Lshortfile != 0 { 147 short := file 148 for i := len(file) - 1; i > 0; i-- { 149 if file[i] == '/' { 150 short = file[i+1:] 151 break 152 } 153 } 154 file = short 155 } 156 *buf = append(*buf, file...) 157 *buf = append(*buf, ':') 158 itoa(buf, line, -1) 159 *buf = append(*buf, ": "...) 160 } 161 if flag&Lmsgprefix != 0 { 162 *buf = append(*buf, prefix...) 163 } 164 } 165 166 var bufferPool = sync.Pool{New: func() any { return new([]byte) }} 167 168 func getBuffer() *[]byte { 169 p := bufferPool.Get().(*[]byte) 170 *p = (*p)[:0] 171 return p 172 } 173 174 func putBuffer(p *[]byte) { 175 // Proper usage of a sync.Pool requires each entry to have approximately 176 // the same memory cost. To obtain this property when the stored type 177 // contains a variably-sized buffer, we add a hard limit on the maximum buffer 178 // to place back in the pool. 179 // 180 // See https://go.dev/issue/23199 181 if cap(*p) > 64<<10 { 182 *p = nil 183 } 184 bufferPool.Put(p) 185 } 186 187 // Output writes the output for a logging event. The string s contains 188 // the text to print after the prefix specified by the flags of the 189 // Logger. A newline is appended if the last character of s is not 190 // already a newline. Calldepth is used to recover the PC and is 191 // provided for generality, although at the moment on all pre-defined 192 // paths it will be 2. 193 func (l *Logger) Output(calldepth int, s string) error { 194 calldepth++ // +1 for this frame. 195 return l.output(0, calldepth, func(b []byte) []byte { 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 string 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 string, 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(2, fmt.Sprint(v...)) 284 os.Exit(1) 285 } 286 287 // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). 288 func (l *Logger) Fatalf(format string, v ...any) { 289 l.Output(2, fmt.Sprintf(format, v...)) 290 os.Exit(1) 291 } 292 293 // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). 294 func (l *Logger) Fatalln(v ...any) { 295 l.Output(2, fmt.Sprintln(v...)) 296 os.Exit(1) 297 } 298 299 // Panic is equivalent to l.Print() followed by a call to panic(). 300 func (l *Logger) Panic(v ...any) { 301 s := fmt.Sprint(v...) 302 l.Output(2, s) 303 panic(s) 304 } 305 306 // Panicf is equivalent to l.Printf() followed by a call to panic(). 307 func (l *Logger) Panicf(format string, v ...any) { 308 s := fmt.Sprintf(format, v...) 309 l.Output(2, s) 310 panic(s) 311 } 312 313 // Panicln is equivalent to l.Println() followed by a call to panic(). 314 func (l *Logger) Panicln(v ...any) { 315 s := fmt.Sprintln(v...) 316 l.Output(2, s) 317 panic(s) 318 } 319 320 // Flags returns the output flags for the logger. 321 // The flag bits are Ldate, Ltime, and so on. 322 func (l *Logger) Flags() int { 323 return int(l.flag.Load()) 324 } 325 326 // SetFlags sets the output flags for the logger. 327 // The flag bits are Ldate, Ltime, and so on. 328 func (l *Logger) SetFlags(flag int) { 329 l.flag.Store(int32(flag)) 330 } 331 332 // Prefix returns the output prefix for the logger. 333 func (l *Logger) Prefix() string { 334 if p := l.prefix.Load(); p != nil { 335 return *p 336 } 337 return "" 338 } 339 340 // SetPrefix sets the output prefix for the logger. 341 func (l *Logger) SetPrefix(prefix string) { 342 l.prefix.Store(&prefix) 343 } 344 345 // Writer returns the output destination for the logger. 346 func (l *Logger) Writer() io.Writer { 347 l.outMu.Lock() 348 defer l.outMu.Unlock() 349 return l.out 350 } 351 352 // SetOutput sets the output destination for the standard logger. 353 func SetOutput(w io.Writer) { 354 std.SetOutput(w) 355 } 356 357 // Flags returns the output flags for the standard logger. 358 // The flag bits are Ldate, Ltime, and so on. 359 func Flags() int { 360 return std.Flags() 361 } 362 363 // SetFlags sets the output flags for the standard logger. 364 // The flag bits are Ldate, Ltime, and so on. 365 func SetFlags(flag int) { 366 std.SetFlags(flag) 367 } 368 369 // Prefix returns the output prefix for the standard logger. 370 func Prefix() string { 371 return std.Prefix() 372 } 373 374 // SetPrefix sets the output prefix for the standard logger. 375 func SetPrefix(prefix string) { 376 std.SetPrefix(prefix) 377 } 378 379 // Writer returns the output destination for the standard logger. 380 func Writer() io.Writer { 381 return std.Writer() 382 } 383 384 // These functions write to the standard logger. 385 386 // Print calls Output to print to the standard logger. 387 // Arguments are handled in the manner of fmt.Print. 388 func Print(v ...any) { 389 std.output(0, 2, func(b []byte) []byte { 390 return fmt.Append(b, v...) 391 }) 392 } 393 394 // Printf calls Output to print to the standard logger. 395 // Arguments are handled in the manner of fmt.Printf. 396 func Printf(format string, v ...any) { 397 std.output(0, 2, func(b []byte) []byte { 398 return fmt.Appendf(b, format, v...) 399 }) 400 } 401 402 // Println calls Output to print to the standard logger. 403 // Arguments are handled in the manner of fmt.Println. 404 func Println(v ...any) { 405 std.output(0, 2, func(b []byte) []byte { 406 return fmt.Appendln(b, v...) 407 }) 408 } 409 410 // Fatal is equivalent to Print() followed by a call to os.Exit(1). 411 func Fatal(v ...any) { 412 std.Output(2, fmt.Sprint(v...)) 413 os.Exit(1) 414 } 415 416 // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). 417 func Fatalf(format string, v ...any) { 418 std.Output(2, fmt.Sprintf(format, v...)) 419 os.Exit(1) 420 } 421 422 // Fatalln is equivalent to Println() followed by a call to os.Exit(1). 423 func Fatalln(v ...any) { 424 std.Output(2, fmt.Sprintln(v...)) 425 os.Exit(1) 426 } 427 428 // Panic is equivalent to Print() followed by a call to panic(). 429 func Panic(v ...any) { 430 s := fmt.Sprint(v...) 431 std.Output(2, s) 432 panic(s) 433 } 434 435 // Panicf is equivalent to Printf() followed by a call to panic(). 436 func Panicf(format string, v ...any) { 437 s := fmt.Sprintf(format, v...) 438 std.Output(2, s) 439 panic(s) 440 } 441 442 // Panicln is equivalent to Println() followed by a call to panic(). 443 func Panicln(v ...any) { 444 s := fmt.Sprintln(v...) 445 std.Output(2, s) 446 panic(s) 447 } 448 449 // Output writes the output for a logging event. The string s contains 450 // the text to print after the prefix specified by the flags of the 451 // Logger. A newline is appended if the last character of s is not 452 // already a newline. Calldepth is the count of the number of 453 // frames to skip when computing the file name and line number 454 // if Llongfile or Lshortfile is set; a value of 1 will print the details 455 // for the caller of Output. 456 func Output(calldepth int, s string) error { 457 return std.Output(calldepth+1, s) // +1 for this frame. 458 }