github.com/ActiveState/go@v0.0.0-20170614201249-0b81c023a722/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  // 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  // 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  	// Get time early if we need it.
   151  	var now time.Time
   152  	if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
   153  		now = time.Now()
   154  	}
   155  	var file string
   156  	var line int
   157  	l.mu.Lock()
   158  	defer l.mu.Unlock()
   159  	if l.flag&(Lshortfile|Llongfile) != 0 {
   160  		// release lock while getting caller info - it's expensive.
   161  		l.mu.Unlock()
   162  		var ok bool
   163  		_, file, line, ok = runtime.Caller(calldepth)
   164  		if !ok {
   165  			file = "???"
   166  			line = 0
   167  		}
   168  		l.mu.Lock()
   169  	}
   170  	l.buf = l.buf[:0]
   171  	l.formatHeader(&l.buf, now, file, line)
   172  	l.buf = append(l.buf, s...)
   173  	if len(s) == 0 || s[len(s)-1] != '\n' {
   174  		l.buf = append(l.buf, '\n')
   175  	}
   176  	_, err := l.out.Write(l.buf)
   177  	return err
   178  }
   179  
   180  // Printf calls l.Output to print to the logger.
   181  // Arguments are handled in the manner of fmt.Printf.
   182  func (l *Logger) Printf(format string, v ...interface{}) {
   183  	l.Output(2, fmt.Sprintf(format, v...))
   184  }
   185  
   186  // Print calls l.Output to print to the logger.
   187  // Arguments are handled in the manner of fmt.Print.
   188  func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) }
   189  
   190  // Println calls l.Output to print to the logger.
   191  // Arguments are handled in the manner of fmt.Println.
   192  func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
   193  
   194  // Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
   195  func (l *Logger) Fatal(v ...interface{}) {
   196  	l.Output(2, fmt.Sprint(v...))
   197  	os.Exit(1)
   198  }
   199  
   200  // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
   201  func (l *Logger) Fatalf(format string, v ...interface{}) {
   202  	l.Output(2, fmt.Sprintf(format, v...))
   203  	os.Exit(1)
   204  }
   205  
   206  // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
   207  func (l *Logger) Fatalln(v ...interface{}) {
   208  	l.Output(2, fmt.Sprintln(v...))
   209  	os.Exit(1)
   210  }
   211  
   212  // Panic is equivalent to l.Print() followed by a call to panic().
   213  func (l *Logger) Panic(v ...interface{}) {
   214  	s := fmt.Sprint(v...)
   215  	l.Output(2, s)
   216  	panic(s)
   217  }
   218  
   219  // Panicf is equivalent to l.Printf() followed by a call to panic().
   220  func (l *Logger) Panicf(format string, v ...interface{}) {
   221  	s := fmt.Sprintf(format, v...)
   222  	l.Output(2, s)
   223  	panic(s)
   224  }
   225  
   226  // Panicln is equivalent to l.Println() followed by a call to panic().
   227  func (l *Logger) Panicln(v ...interface{}) {
   228  	s := fmt.Sprintln(v...)
   229  	l.Output(2, s)
   230  	panic(s)
   231  }
   232  
   233  // Flags returns the output flags for the logger.
   234  func (l *Logger) Flags() int {
   235  	l.mu.Lock()
   236  	defer l.mu.Unlock()
   237  	return l.flag
   238  }
   239  
   240  // SetFlags sets the output flags for the logger.
   241  func (l *Logger) SetFlags(flag int) {
   242  	l.mu.Lock()
   243  	defer l.mu.Unlock()
   244  	l.flag = flag
   245  }
   246  
   247  // Prefix returns the output prefix for the logger.
   248  func (l *Logger) Prefix() string {
   249  	l.mu.Lock()
   250  	defer l.mu.Unlock()
   251  	return l.prefix
   252  }
   253  
   254  // SetPrefix sets the output prefix for the logger.
   255  func (l *Logger) SetPrefix(prefix string) {
   256  	l.mu.Lock()
   257  	defer l.mu.Unlock()
   258  	l.prefix = prefix
   259  }
   260  
   261  // SetOutput sets the output destination for the standard logger.
   262  func SetOutput(w io.Writer) {
   263  	std.mu.Lock()
   264  	defer std.mu.Unlock()
   265  	std.out = w
   266  }
   267  
   268  // Flags returns the output flags for the standard logger.
   269  func Flags() int {
   270  	return std.Flags()
   271  }
   272  
   273  // SetFlags sets the output flags for the standard logger.
   274  func SetFlags(flag int) {
   275  	std.SetFlags(flag)
   276  }
   277  
   278  // Prefix returns the output prefix for the standard logger.
   279  func Prefix() string {
   280  	return std.Prefix()
   281  }
   282  
   283  // SetPrefix sets the output prefix for the standard logger.
   284  func SetPrefix(prefix string) {
   285  	std.SetPrefix(prefix)
   286  }
   287  
   288  // These functions write to the standard logger.
   289  
   290  // Print calls Output to print to the standard logger.
   291  // Arguments are handled in the manner of fmt.Print.
   292  func Print(v ...interface{}) {
   293  	std.Output(2, fmt.Sprint(v...))
   294  }
   295  
   296  // Printf calls Output to print to the standard logger.
   297  // Arguments are handled in the manner of fmt.Printf.
   298  func Printf(format string, v ...interface{}) {
   299  	std.Output(2, fmt.Sprintf(format, v...))
   300  }
   301  
   302  // Println calls Output to print to the standard logger.
   303  // Arguments are handled in the manner of fmt.Println.
   304  func Println(v ...interface{}) {
   305  	std.Output(2, fmt.Sprintln(v...))
   306  }
   307  
   308  // Fatal is equivalent to Print() followed by a call to os.Exit(1).
   309  func Fatal(v ...interface{}) {
   310  	std.Output(2, fmt.Sprint(v...))
   311  	os.Exit(1)
   312  }
   313  
   314  // Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
   315  func Fatalf(format string, v ...interface{}) {
   316  	std.Output(2, fmt.Sprintf(format, v...))
   317  	os.Exit(1)
   318  }
   319  
   320  // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
   321  func Fatalln(v ...interface{}) {
   322  	std.Output(2, fmt.Sprintln(v...))
   323  	os.Exit(1)
   324  }
   325  
   326  // Panic is equivalent to Print() followed by a call to panic().
   327  func Panic(v ...interface{}) {
   328  	s := fmt.Sprint(v...)
   329  	std.Output(2, s)
   330  	panic(s)
   331  }
   332  
   333  // Panicf is equivalent to Printf() followed by a call to panic().
   334  func Panicf(format string, v ...interface{}) {
   335  	s := fmt.Sprintf(format, v...)
   336  	std.Output(2, s)
   337  	panic(s)
   338  }
   339  
   340  // Panicln is equivalent to Println() followed by a call to panic().
   341  func Panicln(v ...interface{}) {
   342  	s := fmt.Sprintln(v...)
   343  	std.Output(2, s)
   344  	panic(s)
   345  }
   346  
   347  // Output writes the output for a logging event. The string s contains
   348  // the text to print after the prefix specified by the flags of the
   349  // Logger. A newline is appended if the last character of s is not
   350  // already a newline. Calldepth is the count of the number of
   351  // frames to skip when computing the file name and line number
   352  // if Llongfile or Lshortfile is set; a value of 1 will print the details
   353  // for the caller of Output.
   354  func Output(calldepth int, s string) error {
   355  	return std.Output(calldepth+1, s) // +1 for this frame.
   356  }