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

View as plain text