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