github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/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  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  }