Source file src/log/log.go

     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  	"sync/atomic"
    24  	"time"
    25  )
    26  
    27  // These flags define which text to prefix to each log entry generated by the Logger.
    28  // Bits are or'ed together to control what's printed.
    29  // With the exception of the Lmsgprefix flag, there is no
    30  // control over the order they appear (the order listed here)
    31  // or the format they present (as described in the comments).
    32  // The prefix is followed by a colon only when Llongfile or Lshortfile
    33  // is specified.
    34  // For example, flags Ldate | Ltime (or LstdFlags) produce,
    35  //	2009/01/23 01:23:23 message
    36  // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
    37  //	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
    38  const (
    39  	Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
    40  	Ltime                         // the time in the local time zone: 01:23:23
    41  	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
    42  	Llongfile                     // full file name and line number: /a/b/c/d.go:23
    43  	Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
    44  	LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
    45  	Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
    46  	LstdFlags     = Ldate | Ltime // initial values for the standard logger
    47  )
    48  
    49  // A Logger represents an active logging object that generates lines of
    50  // output to an io.Writer. Each logging operation makes a single call to
    51  // the Writer's Write method. A Logger can be used simultaneously from
    52  // multiple goroutines; it guarantees to serialize access to the Writer.
    53  type Logger struct {
    54  	mu        sync.Mutex // ensures atomic writes; protects the following fields
    55  	prefix    string     // prefix on each line to identify the logger (but see Lmsgprefix)
    56  	flag      int        // properties
    57  	out       io.Writer  // destination for output
    58  	buf       []byte     // for accumulating text to write
    59  	isDiscard int32      // atomic boolean: whether out == io.Discard
    60  }
    61  
    62  // New creates a new Logger. The out variable sets the
    63  // destination to which log data will be written.
    64  // The prefix appears at the beginning of each generated log line, or
    65  // after the log header if the Lmsgprefix flag is provided.
    66  // The flag argument defines the logging properties.
    67  func New(out io.Writer, prefix string, flag int) *Logger {
    68  	l := &Logger{out: out, prefix: prefix, flag: flag}
    69  	if out == io.Discard {
    70  		l.isDiscard = 1
    71  	}
    72  	return l
    73  }
    74  
    75  // SetOutput sets the output destination for the logger.
    76  func (l *Logger) SetOutput(w io.Writer) {
    77  	l.mu.Lock()
    78  	defer l.mu.Unlock()
    79  	l.out = w
    80  	isDiscard := int32(0)
    81  	if w == io.Discard {
    82  		isDiscard = 1
    83  	}
    84  	atomic.StoreInt32(&l.isDiscard, isDiscard)
    85  }
    86  
    87  var std = New(os.Stderr, "", LstdFlags)
    88  
    89  // Default returns the standard logger used by the package-level output functions.
    90  func Default() *Logger { return std }
    91  
    92  // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding.
    93  func itoa(buf *[]byte, i int, wid int) {
    94  	// Assemble decimal in reverse order.
    95  	var b [20]byte
    96  	bp := len(b) - 1
    97  	for i >= 10 || wid > 1 {
    98  		wid--
    99  		q := i / 10
   100  		b[bp] = byte('0' + i - q*10)
   101  		bp--
   102  		i = q
   103  	}
   104  	// i < 10
   105  	b[bp] = byte('0' + i)
   106  	*buf = append(*buf, b[bp:]...)
   107  }
   108  
   109  // formatHeader writes log header to buf in following order:
   110  //   * l.prefix (if it's not blank and Lmsgprefix is unset),
   111  //   * date and/or time (if corresponding flags are provided),
   112  //   * file and line number (if corresponding flags are provided),
   113  //   * l.prefix (if it's not blank and Lmsgprefix is set).
   114  func (l *Logger) formatHeader(buf *[]byte, t time.Time, file string, line int) {
   115  	if l.flag&Lmsgprefix == 0 {
   116  		*buf = append(*buf, l.prefix...)
   117  	}
   118  	if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
   119  		if l.flag&LUTC != 0 {
   120  			t = t.UTC()
   121  		}
   122  		if l.flag&Ldate != 0 {
   123  			year, month, day := t.Date()
   124  			itoa(buf, year, 4)
   125  			*buf = append(*buf, '/')
   126  			itoa(buf, int(month), 2)
   127  			*buf = append(*buf, '/')
   128  			itoa(buf, day, 2)
   129  			*buf = append(*buf, ' ')
   130  		}
   131  		if l.flag&(Ltime|Lmicroseconds) != 0 {
   132  			hour, min, sec := t.Clock()
   133  			itoa(buf, hour, 2)
   134  			*buf = append(*buf, ':')
   135  			itoa(buf, min, 2)
   136  			*buf = append(*buf, ':')
   137  			itoa(buf, sec, 2)
   138  			if l.flag&Lmicroseconds != 0 {
   139  				*buf = append(*buf, '.')
   140  				itoa(buf, t.Nanosecond()/1e3, 6)
   141  			}
   142  			*buf = append(*buf, ' ')
   143  		}
   144  	}
   145  	if l.flag&(Lshortfile|Llongfile) != 0 {
   146  		if l.flag&Lshortfile != 0 {
   147  			short := file
   148  			for i := len(file) - 1; i > 0; i-- {
   149  				if file[i] == '/' {
   150  					short = file[i+1:]
   151  					break
   152  				}
   153  			}
   154  			file = short
   155  		}
   156  		*buf = append(*buf, file...)
   157  		*buf = append(*buf, ':')
   158  		itoa(buf, line, -1)
   159  		*buf = append(*buf, ": "...)
   160  	}
   161  	if l.flag&Lmsgprefix != 0 {
   162  		*buf = append(*buf, l.prefix...)
   163  	}
   164  }
   165  
   166  // Output writes the output for a logging event. The string s contains
   167  // the text to print after the prefix specified by the flags of the
   168  // Logger. A newline is appended if the last character of s is not
   169  // already a newline. Calldepth is used to recover the PC and is
   170  // provided for generality, although at the moment on all pre-defined
   171  // paths it will be 2.
   172  func (l *Logger) Output(calldepth int, s string) error {
   173  	now := time.Now() // get this early.
   174  	var file string
   175  	var line int
   176  	l.mu.Lock()
   177  	defer l.mu.Unlock()
   178  	if l.flag&(Lshortfile|Llongfile) != 0 {
   179  		// Release lock while getting caller info - it's expensive.
   180  		l.mu.Unlock()
   181  		var ok bool
   182  		_, file, line, ok = runtime.Caller(calldepth)
   183  		if !ok {
   184  			file = "???"
   185  			line = 0
   186  		}
   187  		l.mu.Lock()
   188  	}
   189  	l.buf = l.buf[:0]
   190  	l.formatHeader(&l.buf, now, file, line)
   191  	l.buf = append(l.buf, s...)
   192  	if len(s) == 0 || s[len(s)-1] != '\n' {
   193  		l.buf = append(l.buf, '\n')
   194  	}
   195  	_, err := l.out.Write(l.buf)
   196  	return err
   197  }
   198  
   199  // Printf calls l.Output to print to the logger.
   200  // Arguments are handled in the manner of fmt.Printf.
   201  func (l *Logger) Printf(format string, v ...any) {
   202  	if atomic.LoadInt32(&l.isDiscard) != 0 {
   203  		return
   204  	}
   205  	l.Output(2, fmt.Sprintf(format, v...))
   206  }
   207  
   208  // Print calls l.Output to print to the logger.
   209  // Arguments are handled in the manner of fmt.Print.
   210  func (l *Logger) Print(v ...any) {
   211  	if atomic.LoadInt32(&l.isDiscard) != 0 {
   212  		return
   213  	}
   214  	l.Output(2, fmt.Sprint(v...))
   215  }
   216  
   217  // Println calls l.Output to print to the logger.
   218  // Arguments are handled in the manner of fmt.Println.
   219  func (l *Logger) Println(v ...any) {
   220  	if atomic.LoadInt32(&l.isDiscard) != 0 {
   221  		return
   222  	}
   223  	l.Output(2, fmt.Sprintln(v...))
   224  }
   225  
   226  // Fatal is equivalent to l.Print() followed by a call to os.Exit(1).
   227  func (l *Logger) Fatal(v ...any) {
   228  	l.Output(2, fmt.Sprint(v...))
   229  	os.Exit(1)
   230  }
   231  
   232  // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
   233  func (l *Logger) Fatalf(format string, v ...any) {
   234  	l.Output(2, fmt.Sprintf(format, v...))
   235  	os.Exit(1)
   236  }
   237  
   238  // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
   239  func (l *Logger) Fatalln(v ...any) {
   240  	l.Output(2, fmt.Sprintln(v...))
   241  	os.Exit(1)
   242  }
   243  
   244  // Panic is equivalent to l.Print() followed by a call to panic().
   245  func (l *Logger) Panic(v ...any) {
   246  	s := fmt.Sprint(v...)
   247  	l.Output(2, s)
   248  	panic(s)
   249  }
   250  
   251  // Panicf is equivalent to l.Printf() followed by a call to panic().
   252  func (l *Logger) Panicf(format string, v ...any) {
   253  	s := fmt.Sprintf(format, v...)
   254  	l.Output(2, s)
   255  	panic(s)
   256  }
   257  
   258  // Panicln is equivalent to l.Println() followed by a call to panic().
   259  func (l *Logger) Panicln(v ...any) {
   260  	s := fmt.Sprintln(v...)
   261  	l.Output(2, s)
   262  	panic(s)
   263  }
   264  
   265  // Flags returns the output flags for the logger.
   266  // The flag bits are Ldate, Ltime, and so on.
   267  func (l *Logger) Flags() int {
   268  	l.mu.Lock()
   269  	defer l.mu.Unlock()
   270  	return l.flag
   271  }
   272  
   273  // SetFlags sets the output flags for the logger.
   274  // The flag bits are Ldate, Ltime, and so on.
   275  func (l *Logger) SetFlags(flag int) {
   276  	l.mu.Lock()
   277  	defer l.mu.Unlock()
   278  	l.flag = flag
   279  }
   280  
   281  // Prefix returns the output prefix for the logger.
   282  func (l *Logger) Prefix() string {
   283  	l.mu.Lock()
   284  	defer l.mu.Unlock()
   285  	return l.prefix
   286  }
   287  
   288  // SetPrefix sets the output prefix for the logger.
   289  func (l *Logger) SetPrefix(prefix string) {
   290  	l.mu.Lock()
   291  	defer l.mu.Unlock()
   292  	l.prefix = prefix
   293  }
   294  
   295  // Writer returns the output destination for the logger.
   296  func (l *Logger) Writer() io.Writer {
   297  	l.mu.Lock()
   298  	defer l.mu.Unlock()
   299  	return l.out
   300  }
   301  
   302  // SetOutput sets the output destination for the standard logger.
   303  func SetOutput(w io.Writer) {
   304  	std.SetOutput(w)
   305  }
   306  
   307  // Flags returns the output flags for the standard logger.
   308  // The flag bits are Ldate, Ltime, and so on.
   309  func Flags() int {
   310  	return std.Flags()
   311  }
   312  
   313  // SetFlags sets the output flags for the standard logger.
   314  // The flag bits are Ldate, Ltime, and so on.
   315  func SetFlags(flag int) {
   316  	std.SetFlags(flag)
   317  }
   318  
   319  // Prefix returns the output prefix for the standard logger.
   320  func Prefix() string {
   321  	return std.Prefix()
   322  }
   323  
   324  // SetPrefix sets the output prefix for the standard logger.
   325  func SetPrefix(prefix string) {
   326  	std.SetPrefix(prefix)
   327  }
   328  
   329  // Writer returns the output destination for the standard logger.
   330  func Writer() io.Writer {
   331  	return std.Writer()
   332  }
   333  
   334  // These functions write to the standard logger.
   335  
   336  // Print calls Output to print to the standard logger.
   337  // Arguments are handled in the manner of fmt.Print.
   338  func Print(v ...any) {
   339  	if atomic.LoadInt32(&std.isDiscard) != 0 {
   340  		return
   341  	}
   342  	std.Output(2, fmt.Sprint(v...))
   343  }
   344  
   345  // Printf calls Output to print to the standard logger.
   346  // Arguments are handled in the manner of fmt.Printf.
   347  func Printf(format string, v ...any) {
   348  	if atomic.LoadInt32(&std.isDiscard) != 0 {
   349  		return
   350  	}
   351  	std.Output(2, fmt.Sprintf(format, v...))
   352  }
   353  
   354  // Println calls Output to print to the standard logger.
   355  // Arguments are handled in the manner of fmt.Println.
   356  func Println(v ...any) {
   357  	if atomic.LoadInt32(&std.isDiscard) != 0 {
   358  		return
   359  	}
   360  	std.Output(2, fmt.Sprintln(v...))
   361  }
   362  
   363  // Fatal is equivalent to Print() followed by a call to os.Exit(1).
   364  func Fatal(v ...any) {
   365  	std.Output(2, fmt.Sprint(v...))
   366  	os.Exit(1)
   367  }
   368  
   369  // Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
   370  func Fatalf(format string, v ...any) {
   371  	std.Output(2, fmt.Sprintf(format, v...))
   372  	os.Exit(1)
   373  }
   374  
   375  // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
   376  func Fatalln(v ...any) {
   377  	std.Output(2, fmt.Sprintln(v...))
   378  	os.Exit(1)
   379  }
   380  
   381  // Panic is equivalent to Print() followed by a call to panic().
   382  func Panic(v ...any) {
   383  	s := fmt.Sprint(v...)
   384  	std.Output(2, s)
   385  	panic(s)
   386  }
   387  
   388  // Panicf is equivalent to Printf() followed by a call to panic().
   389  func Panicf(format string, v ...any) {
   390  	s := fmt.Sprintf(format, v...)
   391  	std.Output(2, s)
   392  	panic(s)
   393  }
   394  
   395  // Panicln is equivalent to Println() followed by a call to panic().
   396  func Panicln(v ...any) {
   397  	s := fmt.Sprintln(v...)
   398  	std.Output(2, s)
   399  	panic(s)
   400  }
   401  
   402  // Output writes the output for a logging event. The string s contains
   403  // the text to print after the prefix specified by the flags of the
   404  // Logger. A newline is appended if the last character of s is not
   405  // already a newline. Calldepth is the count of the number of
   406  // frames to skip when computing the file name and line number
   407  // if Llongfile or Lshortfile is set; a value of 1 will print the details
   408  // for the caller of Output.
   409  func Output(calldepth int, s string) error {
   410  	return std.Output(calldepth+1, s) // +1 for this frame.
   411  }
   412  

View as plain text