github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/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 // The Fatal functions call os.Exit(1) after writing the log message. 12 // The Panic functions call panic after writing the log message. 13 package log 14 15 import ( 16 "fmt" 17 "io" 18 "os" 19 "runtime" 20 "sync" 21 "time" 22 ) 23 24 // These flags define which text to prefix to each log entry generated by the Logger. 25 const ( 26 // Bits or'ed together to control what's printed. There is no control over the 27 // order they appear (the order listed here) or the format they present (as 28 // described in the comments). A colon appears after these items: 29 // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message 30 Ldate = 1 << iota // the date: 2009/01/23 31 Ltime // the time: 01:23:23 32 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 33 Llongfile // full file name and line number: /a/b/c/d.go:23 34 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 35 LstdFlags = Ldate | Ltime // initial values for the standard logger 36 ) 37 38 // A Logger represents an active logging object that generates lines of 39 // output to an io.Writer. Each logging operation makes a single call to 40 // the Writer's Write method. A Logger can be used simultaneously from 41 // multiple goroutines; it guarantees to serialize access to the Writer. 42 type Logger struct { 43 mu sync.Mutex // ensures atomic writes; protects the following fields 44 prefix string // prefix to write at beginning of each line 45 flag int // properties 46 out io.Writer // destination for output 47 buf []byte // for accumulating text to write 48 } 49 50 // New creates a new Logger. The out variable sets the 51 // destination to which log data will be written. 52 // The prefix appears at the beginning of each generated log line. 53 // The flag argument defines the logging properties. 54 func New(out io.Writer, prefix string, flag int) *Logger { 55 return &Logger{out: out, prefix: prefix, flag: flag} 56 } 57 58 var std = New(os.Stderr, "", LstdFlags) 59 60 // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. 61 // Knows the buffer has capacity. 62 func itoa(buf *[]byte, i int, wid int) { 63 var u uint = uint(i) 64 if u == 0 && wid <= 1 { 65 *buf = append(*buf, '0') 66 return 67 } 68 69 // Assemble decimal in reverse order. 70 var b [32]byte 71 bp := len(b) 72 for ; u > 0 || wid > 0; u /= 10 { 73 bp-- 74 wid-- 75 b[bp] = byte(u%10) + '0' 76 } 77 *buf = append(*buf, b[bp:]...) 78 } 79 80 func (l *Logger) formatHeader(buf *[]byte, t time.Time, file string, line int) { 81 *buf = append(*buf, l.prefix...) 82 if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 { 83 if l.flag&Ldate != 0 { 84 year, month, day := t.Date() 85 itoa(buf, year, 4) 86 *buf = append(*buf, '/') 87 itoa(buf, int(month), 2) 88 *buf = append(*buf, '/') 89 itoa(buf, day, 2) 90 *buf = append(*buf, ' ') 91 } 92 if l.flag&(Ltime|Lmicroseconds) != 0 { 93 hour, min, sec := t.Clock() 94 itoa(buf, hour, 2) 95 *buf = append(*buf, ':') 96 itoa(buf, min, 2) 97 *buf = append(*buf, ':') 98 itoa(buf, sec, 2) 99 if l.flag&Lmicroseconds != 0 { 100 *buf = append(*buf, '.') 101 itoa(buf, t.Nanosecond()/1e3, 6) 102 } 103 *buf = append(*buf, ' ') 104 } 105 } 106 if l.flag&(Lshortfile|Llongfile) != 0 { 107 if l.flag&Lshortfile != 0 { 108 short := file 109 for i := len(file) - 1; i > 0; i-- { 110 if file[i] == '/' { 111 short = file[i+1:] 112 break 113 } 114 } 115 file = short 116 } 117 *buf = append(*buf, file...) 118 *buf = append(*buf, ':') 119 itoa(buf, line, -1) 120 *buf = append(*buf, ": "...) 121 } 122 } 123 124 // Output writes the output for a logging event. The string s contains 125 // the text to print after the prefix specified by the flags of the 126 // Logger. A newline is appended if the last character of s is not 127 // already a newline. Calldepth is used to recover the PC and is 128 // provided for generality, although at the moment on all pre-defined 129 // paths it will be 2. 130 func (l *Logger) Output(calldepth int, s string) error { 131 now := time.Now() // get this early. 132 var file string 133 var line int 134 l.mu.Lock() 135 defer l.mu.Unlock() 136 if l.flag&(Lshortfile|Llongfile) != 0 { 137 // release lock while getting caller info - it's expensive. 138 l.mu.Unlock() 139 var ok bool 140 _, file, line, ok = runtime.Caller(calldepth) 141 if !ok { 142 file = "???" 143 line = 0 144 } 145 l.mu.Lock() 146 } 147 l.buf = l.buf[:0] 148 l.formatHeader(&l.buf, now, file, line) 149 l.buf = append(l.buf, s...) 150 if len(s) > 0 && s[len(s)-1] != '\n' { 151 l.buf = append(l.buf, '\n') 152 } 153 _, err := l.out.Write(l.buf) 154 return err 155 } 156 157 // Printf calls l.Output to print to the logger. 158 // Arguments are handled in the manner of fmt.Printf. 159 func (l *Logger) Printf(format string, v ...interface{}) { 160 l.Output(2, fmt.Sprintf(format, v...)) 161 } 162 163 // Print calls l.Output to print to the logger. 164 // Arguments are handled in the manner of fmt.Print. 165 func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) } 166 167 // Println calls l.Output to print to the logger. 168 // Arguments are handled in the manner of fmt.Println. 169 func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) } 170 171 // Fatal is equivalent to l.Print() followed by a call to os.Exit(1). 172 func (l *Logger) Fatal(v ...interface{}) { 173 l.Output(2, fmt.Sprint(v...)) 174 os.Exit(1) 175 } 176 177 // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). 178 func (l *Logger) Fatalf(format string, v ...interface{}) { 179 l.Output(2, fmt.Sprintf(format, v...)) 180 os.Exit(1) 181 } 182 183 // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). 184 func (l *Logger) Fatalln(v ...interface{}) { 185 l.Output(2, fmt.Sprintln(v...)) 186 os.Exit(1) 187 } 188 189 // Panic is equivalent to l.Print() followed by a call to panic(). 190 func (l *Logger) Panic(v ...interface{}) { 191 s := fmt.Sprint(v...) 192 l.Output(2, s) 193 panic(s) 194 } 195 196 // Panicf is equivalent to l.Printf() followed by a call to panic(). 197 func (l *Logger) Panicf(format string, v ...interface{}) { 198 s := fmt.Sprintf(format, v...) 199 l.Output(2, s) 200 panic(s) 201 } 202 203 // Panicln is equivalent to l.Println() followed by a call to panic(). 204 func (l *Logger) Panicln(v ...interface{}) { 205 s := fmt.Sprintln(v...) 206 l.Output(2, s) 207 panic(s) 208 } 209 210 // Flags returns the output flags for the logger. 211 func (l *Logger) Flags() int { 212 l.mu.Lock() 213 defer l.mu.Unlock() 214 return l.flag 215 } 216 217 // SetFlags sets the output flags for the logger. 218 func (l *Logger) SetFlags(flag int) { 219 l.mu.Lock() 220 defer l.mu.Unlock() 221 l.flag = flag 222 } 223 224 // Prefix returns the output prefix for the logger. 225 func (l *Logger) Prefix() string { 226 l.mu.Lock() 227 defer l.mu.Unlock() 228 return l.prefix 229 } 230 231 // SetPrefix sets the output prefix for the logger. 232 func (l *Logger) SetPrefix(prefix string) { 233 l.mu.Lock() 234 defer l.mu.Unlock() 235 l.prefix = prefix 236 } 237 238 // SetOutput sets the output destination for the standard logger. 239 func SetOutput(w io.Writer) { 240 std.mu.Lock() 241 defer std.mu.Unlock() 242 std.out = w 243 } 244 245 // Flags returns the output flags for the standard logger. 246 func Flags() int { 247 return std.Flags() 248 } 249 250 // SetFlags sets the output flags for the standard logger. 251 func SetFlags(flag int) { 252 std.SetFlags(flag) 253 } 254 255 // Prefix returns the output prefix for the standard logger. 256 func Prefix() string { 257 return std.Prefix() 258 } 259 260 // SetPrefix sets the output prefix for the standard logger. 261 func SetPrefix(prefix string) { 262 std.SetPrefix(prefix) 263 } 264 265 // These functions write to the standard logger. 266 267 // Print calls Output to print to the standard logger. 268 // Arguments are handled in the manner of fmt.Print. 269 func Print(v ...interface{}) { 270 std.Output(2, fmt.Sprint(v...)) 271 } 272 273 // Printf calls Output to print to the standard logger. 274 // Arguments are handled in the manner of fmt.Printf. 275 func Printf(format string, v ...interface{}) { 276 std.Output(2, fmt.Sprintf(format, v...)) 277 } 278 279 // Println calls Output to print to the standard logger. 280 // Arguments are handled in the manner of fmt.Println. 281 func Println(v ...interface{}) { 282 std.Output(2, fmt.Sprintln(v...)) 283 } 284 285 // Fatal is equivalent to Print() followed by a call to os.Exit(1). 286 func Fatal(v ...interface{}) { 287 std.Output(2, fmt.Sprint(v...)) 288 os.Exit(1) 289 } 290 291 // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). 292 func Fatalf(format string, v ...interface{}) { 293 std.Output(2, fmt.Sprintf(format, v...)) 294 os.Exit(1) 295 } 296 297 // Fatalln is equivalent to Println() followed by a call to os.Exit(1). 298 func Fatalln(v ...interface{}) { 299 std.Output(2, fmt.Sprintln(v...)) 300 os.Exit(1) 301 } 302 303 // Panic is equivalent to Print() followed by a call to panic(). 304 func Panic(v ...interface{}) { 305 s := fmt.Sprint(v...) 306 std.Output(2, s) 307 panic(s) 308 } 309 310 // Panicf is equivalent to Printf() followed by a call to panic(). 311 func Panicf(format string, v ...interface{}) { 312 s := fmt.Sprintf(format, v...) 313 std.Output(2, s) 314 panic(s) 315 } 316 317 // Panicln is equivalent to Println() followed by a call to panic(). 318 func Panicln(v ...interface{}) { 319 s := fmt.Sprintln(v...) 320 std.Output(2, s) 321 panic(s) 322 }