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