github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 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  }