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