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 const (
     28 	// Bits or'ed together to control what's printed.
     29 	// There is no control over the order they appear (the order listed
     30 	// here) or the format they present (as described in the comments).
     31 	// The prefix is followed by a colon only when Llongfile or Lshortfile
     32 	// is specified.
     33 	// For example, flags Ldate | Ltime (or LstdFlags) produce,
     34 	//	2009/01/23 01:23:23 message
     35 	// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
     36 	//	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
     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 func (l *Logger) formatHeader(buf *[]byte, t time.Time, file string, line int) {
     93 	*buf = append(*buf, l.prefix...)
     94 	if l.flag&LUTC != 0 {
     95 		t = t.UTC()
     96 	}
     97 	if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
     98 		if l.flag&Ldate != 0 {
     99 			year, month, day := t.Date()
    100 			itoa(buf, year, 4)
    101 			*buf = append(*buf, '/')
    102 			itoa(buf, int(month), 2)
    103 			*buf = append(*buf, '/')
    104 			itoa(buf, day, 2)
    105 			*buf = append(*buf, ' ')
    106 		}
    107 		if l.flag&(Ltime|Lmicroseconds) != 0 {
    108 			hour, min, sec := t.Clock()
    109 			itoa(buf, hour, 2)
    110 			*buf = append(*buf, ':')
    111 			itoa(buf, min, 2)
    112 			*buf = append(*buf, ':')
    113 			itoa(buf, sec, 2)
    114 			if l.flag&Lmicroseconds != 0 {
    115 				*buf = append(*buf, '.')
    116 				itoa(buf, t.Nanosecond()/1e3, 6)
    117 			}
    118 			*buf = append(*buf, ' ')
    119 		}
    120 	}
    121 	if l.flag&(Lshortfile|Llongfile) != 0 {
    122 		if l.flag&Lshortfile != 0 {
    123 			short := file
    124 			for i := len(file) - 1; i > 0; i-- {
    125 				if file[i] == '/' {
    126 					short = file[i+1:]
    127 					break
    128 				}
    129 			}
    130 			file = short
    131 		}
    132 		*buf = append(*buf, file...)
    133 		*buf = append(*buf, ':')
    134 		itoa(buf, line, -1)
    135 		*buf = append(*buf, ": "...)
    136 	}
    137 }
    138 
    139 // Output writes the output for a logging event. The string s contains
    140 // the text to print after the prefix specified by the flags of the
    141 // Logger. A newline is appended if the last character of s is not
    142 // already a newline. Calldepth is used to recover the PC and is
    143 // provided for generality, although at the moment on all pre-defined
    144 // paths it will be 2.
    145 func (l *Logger) Output(calldepth int, s string) error {
    146 	now := time.Now() // get this early.
    147 	var file string
    148 	var line int
    149 	l.mu.Lock()
    150 	defer l.mu.Unlock()
    151 	if l.flag&(Lshortfile|Llongfile) != 0 {
    152 		// release lock while getting caller info - it's expensive.
    153 		l.mu.Unlock()
    154 		var ok bool
    155 		_, file, line, ok = runtime.Caller(calldepth)
    156 		if !ok {
    157 			file = "???"
    158 			line = 0
    159 		}
    160 		l.mu.Lock()
    161 	}
    162 	l.buf = l.buf[:0]
    163 	l.formatHeader(&l.buf, now, file, line)
    164 	l.buf = append(l.buf, s...)
    165 	if len(s) == 0 || s[len(s)-1] != '\n' {
    166 		l.buf = append(l.buf, '\n')
    167 	}
    168 	_, err := l.out.Write(l.buf)
    169 	return err
    170 }
    171 
    172 // Printf calls l.Output to print to the logger.
    173 // Arguments are handled in the manner of fmt.Printf.
    174 func (l *Logger) Printf(format string, v ...interface{}) {
    175 	l.Output(2, fmt.Sprintf(format, v...))
    176 }
    177 
    178 // Print calls l.Output to print to the logger.
    179 // Arguments are handled in the manner of fmt.Print.
    180 func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) }
    181 
    182 // Println calls l.Output to print to the logger.
    183 // Arguments are handled in the manner of fmt.Println.
    184 func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
    185 
    186 // Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
    187 func (l *Logger) Fatal(v ...interface{}) {
    188 	l.Output(2, fmt.Sprint(v...))
    189 	os.Exit(1)
    190 }
    191 
    192 // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
    193 func (l *Logger) Fatalf(format string, v ...interface{}) {
    194 	l.Output(2, fmt.Sprintf(format, v...))
    195 	os.Exit(1)
    196 }
    197 
    198 // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
    199 func (l *Logger) Fatalln(v ...interface{}) {
    200 	l.Output(2, fmt.Sprintln(v...))
    201 	os.Exit(1)
    202 }
    203 
    204 // Panic is equivalent to l.Print() followed by a call to panic().
    205 func (l *Logger) Panic(v ...interface{}) {
    206 	s := fmt.Sprint(v...)
    207 	l.Output(2, s)
    208 	panic(s)
    209 }
    210 
    211 // Panicf is equivalent to l.Printf() followed by a call to panic().
    212 func (l *Logger) Panicf(format string, v ...interface{}) {
    213 	s := fmt.Sprintf(format, v...)
    214 	l.Output(2, s)
    215 	panic(s)
    216 }
    217 
    218 // Panicln is equivalent to l.Println() followed by a call to panic().
    219 func (l *Logger) Panicln(v ...interface{}) {
    220 	s := fmt.Sprintln(v...)
    221 	l.Output(2, s)
    222 	panic(s)
    223 }
    224 
    225 // Flags returns the output flags for the logger.
    226 func (l *Logger) Flags() int {
    227 	l.mu.Lock()
    228 	defer l.mu.Unlock()
    229 	return l.flag
    230 }
    231 
    232 // SetFlags sets the output flags for the logger.
    233 func (l *Logger) SetFlags(flag int) {
    234 	l.mu.Lock()
    235 	defer l.mu.Unlock()
    236 	l.flag = flag
    237 }
    238 
    239 // Prefix returns the output prefix for the logger.
    240 func (l *Logger) Prefix() string {
    241 	l.mu.Lock()
    242 	defer l.mu.Unlock()
    243 	return l.prefix
    244 }
    245 
    246 // SetPrefix sets the output prefix for the logger.
    247 func (l *Logger) SetPrefix(prefix string) {
    248 	l.mu.Lock()
    249 	defer l.mu.Unlock()
    250 	l.prefix = prefix
    251 }
    252 
    253 // SetOutput sets the output destination for the standard logger.
    254 func SetOutput(w io.Writer) {
    255 	std.mu.Lock()
    256 	defer std.mu.Unlock()
    257 	std.out = w
    258 }
    259 
    260 // Flags returns the output flags for the standard logger.
    261 func Flags() int {
    262 	return std.Flags()
    263 }
    264 
    265 // SetFlags sets the output flags for the standard logger.
    266 func SetFlags(flag int) {
    267 	std.SetFlags(flag)
    268 }
    269 
    270 // Prefix returns the output prefix for the standard logger.
    271 func Prefix() string {
    272 	return std.Prefix()
    273 }
    274 
    275 // SetPrefix sets the output prefix for the standard logger.
    276 func SetPrefix(prefix string) {
    277 	std.SetPrefix(prefix)
    278 }
    279 
    280 // These functions write to the standard logger.
    281 
    282 // Print calls Output to print to the standard logger.
    283 // Arguments are handled in the manner of fmt.Print.
    284 func Print(v ...interface{}) {
    285 	std.Output(2, fmt.Sprint(v...))
    286 }
    287 
    288 // Printf calls Output to print to the standard logger.
    289 // Arguments are handled in the manner of fmt.Printf.
    290 func Printf(format string, v ...interface{}) {
    291 	std.Output(2, fmt.Sprintf(format, v...))
    292 }
    293 
    294 // Println calls Output to print to the standard logger.
    295 // Arguments are handled in the manner of fmt.Println.
    296 func Println(v ...interface{}) {
    297 	std.Output(2, fmt.Sprintln(v...))
    298 }
    299 
    300 // Fatal is equivalent to Print() followed by a call to os.Exit(1).
    301 func Fatal(v ...interface{}) {
    302 	std.Output(2, fmt.Sprint(v...))
    303 	os.Exit(1)
    304 }
    305 
    306 // Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
    307 func Fatalf(format string, v ...interface{}) {
    308 	std.Output(2, fmt.Sprintf(format, v...))
    309 	os.Exit(1)
    310 }
    311 
    312 // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
    313 func Fatalln(v ...interface{}) {
    314 	std.Output(2, fmt.Sprintln(v...))
    315 	os.Exit(1)
    316 }
    317 
    318 // Panic is equivalent to Print() followed by a call to panic().
    319 func Panic(v ...interface{}) {
    320 	s := fmt.Sprint(v...)
    321 	std.Output(2, s)
    322 	panic(s)
    323 }
    324 
    325 // Panicf is equivalent to Printf() followed by a call to panic().
    326 func Panicf(format string, v ...interface{}) {
    327 	s := fmt.Sprintf(format, v...)
    328 	std.Output(2, s)
    329 	panic(s)
    330 }
    331 
    332 // Panicln is equivalent to Println() followed by a call to panic().
    333 func Panicln(v ...interface{}) {
    334 	s := fmt.Sprintln(v...)
    335 	std.Output(2, s)
    336 	panic(s)
    337 }
    338 
    339 // Output writes the output for a logging event. The string s contains
    340 // the text to print after the prefix specified by the flags of the
    341 // Logger. A newline is appended if the last character of s is not
    342 // already a newline. Calldepth is the count of the number of
    343 // frames to skip when computing the file name and line number
    344 // if Llongfile or Lshortfile is set; a value of 1 will print the details
    345 // for the caller of Output.
    346 func Output(calldepth int, s string) error {
    347 	return std.Output(calldepth+1, s) // +1 for this frame.
    348 }
    349