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