...

Source file src/log/log.go

Documentation: log

     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  	"log/internal"
    21  	"os"
    22  	"runtime"
    23  	"sync"
    24  	"sync/atomic"
    25  	"time"
    26  )
    27  
    28  // These flags define which text to prefix to each log entry generated by the [Logger].
    29  // Bits are or'ed together to control what's printed.
    30  // With the exception of the Lmsgprefix flag, there is no
    31  // control over the order they appear (the order listed here)
    32  // or the format they present (as described in the comments).
    33  // The prefix is followed by a colon only when Llongfile or Lshortfile
    34  // is specified.
    35  // For example, flags Ldate | Ltime (or LstdFlags) produce,
    36  //
    37  //	2009/01/23 01:23:23 message
    38  //
    39  // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
    40  //
    41  //	2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
    42  const (
    43  	Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23
    44  	Ltime                         // the time in the local time zone: 01:23:23
    45  	Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
    46  	Llongfile                     // full file name and line number: /a/b/c/d.go:23
    47  	Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
    48  	LUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zone
    49  	Lmsgprefix                    // move the "prefix" from the beginning of the line to before the message
    50  	LstdFlags     = Ldate | Ltime // initial values for the standard logger
    51  )
    52  
    53  // A Logger represents an active logging object that generates lines of
    54  // output to an [io.Writer]. Each logging operation makes a single call to
    55  // the Writer's Write method. A Logger can be used simultaneously from
    56  // multiple goroutines; it guarantees to serialize access to the Writer.
    57  type Logger struct {
    58  	outMu sync.Mutex
    59  	out   io.Writer // destination for output
    60  
    61  	prefix    atomic.Pointer[string] // prefix on each line to identify the logger (but see Lmsgprefix)
    62  	flag      atomic.Int32           // properties
    63  	isDiscard atomic.Bool
    64  }
    65  
    66  // New creates a new [Logger]. The out variable sets the
    67  // destination to which log data will be written.
    68  // The prefix appears at the beginning of each generated log line, or
    69  // after the log header if the [Lmsgprefix] flag is provided.
    70  // The flag argument defines the logging properties.
    71  func New(out io.Writer, prefix string, flag int) *Logger {
    72  	l := new(Logger)
    73  	l.SetOutput(out)
    74  	l.SetPrefix(prefix)
    75  	l.SetFlags(flag)
    76  	return l
    77  }
    78  
    79  // SetOutput sets the output destination for the logger.
    80  func (l *Logger) SetOutput(w io.Writer) {
    81  	l.outMu.Lock()
    82  	defer l.outMu.Unlock()
    83  	l.out = w
    84  	l.isDiscard.Store(w == io.Discard)
    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 formatHeader(buf *[]byte, t time.Time, prefix string, flag int, file string, line int) {
   115  	if flag&Lmsgprefix == 0 {
   116  		*buf = append(*buf, prefix...)
   117  	}
   118  	if flag&(Ldate|Ltime|Lmicroseconds) != 0 {
   119  		if flag&LUTC != 0 {
   120  			t = t.UTC()
   121  		}
   122  		if 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 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 flag&Lmicroseconds != 0 {
   139  				*buf = append(*buf, '.')
   140  				itoa(buf, t.Nanosecond()/1e3, 6)
   141  			}
   142  			*buf = append(*buf, ' ')
   143  		}
   144  	}
   145  	if flag&(Lshortfile|Llongfile) != 0 {
   146  		if 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 flag&Lmsgprefix != 0 {
   162  		*buf = append(*buf, prefix...)
   163  	}
   164  }
   165  
   166  var bufferPool = sync.Pool{New: func() any { return new([]byte) }}
   167  
   168  func getBuffer() *[]byte {
   169  	p := bufferPool.Get().(*[]byte)
   170  	*p = (*p)[:0]
   171  	return p
   172  }
   173  
   174  func putBuffer(p *[]byte) {
   175  	// Proper usage of a sync.Pool requires each entry to have approximately
   176  	// the same memory cost. To obtain this property when the stored type
   177  	// contains a variably-sized buffer, we add a hard limit on the maximum buffer
   178  	// to place back in the pool.
   179  	//
   180  	// See https://go.dev/issue/23199
   181  	if cap(*p) > 64<<10 {
   182  		*p = nil
   183  	}
   184  	bufferPool.Put(p)
   185  }
   186  
   187  // Output writes the output for a logging event. The string s contains
   188  // the text to print after the prefix specified by the flags of the
   189  // Logger. A newline is appended if the last character of s is not
   190  // already a newline. Calldepth is used to recover the PC and is
   191  // provided for generality, although at the moment on all pre-defined
   192  // paths it will be 2.
   193  func (l *Logger) Output(calldepth int, s string) error {
   194  	calldepth++ // +1 for this frame.
   195  	return l.output(0, calldepth, func(b []byte) []byte {
   196  		return append(b, s...)
   197  	})
   198  }
   199  
   200  // output can take either a calldepth or a pc to get source line information.
   201  // It uses the pc if it is non-zero.
   202  func (l *Logger) output(pc uintptr, calldepth int, appendOutput func([]byte) []byte) error {
   203  	if l.isDiscard.Load() {
   204  		return nil
   205  	}
   206  
   207  	now := time.Now() // get this early.
   208  
   209  	// Load prefix and flag once so that their value is consistent within
   210  	// this call regardless of any concurrent changes to their value.
   211  	prefix := l.Prefix()
   212  	flag := l.Flags()
   213  
   214  	var file string
   215  	var line int
   216  	if flag&(Lshortfile|Llongfile) != 0 {
   217  		if pc == 0 {
   218  			var ok bool
   219  			_, file, line, ok = runtime.Caller(calldepth)
   220  			if !ok {
   221  				file = "???"
   222  				line = 0
   223  			}
   224  		} else {
   225  			fs := runtime.CallersFrames([]uintptr{pc})
   226  			f, _ := fs.Next()
   227  			file = f.File
   228  			if file == "" {
   229  				file = "???"
   230  			}
   231  			line = f.Line
   232  		}
   233  	}
   234  
   235  	buf := getBuffer()
   236  	defer putBuffer(buf)
   237  	formatHeader(buf, now, prefix, flag, file, line)
   238  	*buf = appendOutput(*buf)
   239  	if len(*buf) == 0 || (*buf)[len(*buf)-1] != '\n' {
   240  		*buf = append(*buf, '\n')
   241  	}
   242  
   243  	l.outMu.Lock()
   244  	defer l.outMu.Unlock()
   245  	_, err := l.out.Write(*buf)
   246  	return err
   247  }
   248  
   249  func init() {
   250  	internal.DefaultOutput = func(pc uintptr, data []byte) error {
   251  		return std.output(pc, 0, func(buf []byte) []byte {
   252  			return append(buf, data...)
   253  		})
   254  	}
   255  }
   256  
   257  // Print calls l.Output to print to the logger.
   258  // Arguments are handled in the manner of [fmt.Print].
   259  func (l *Logger) Print(v ...any) {
   260  	l.output(0, 2, func(b []byte) []byte {
   261  		return fmt.Append(b, v...)
   262  	})
   263  }
   264  
   265  // Printf calls l.Output to print to the logger.
   266  // Arguments are handled in the manner of [fmt.Printf].
   267  func (l *Logger) Printf(format string, v ...any) {
   268  	l.output(0, 2, func(b []byte) []byte {
   269  		return fmt.Appendf(b, format, v...)
   270  	})
   271  }
   272  
   273  // Println calls l.Output to print to the logger.
   274  // Arguments are handled in the manner of [fmt.Println].
   275  func (l *Logger) Println(v ...any) {
   276  	l.output(0, 2, func(b []byte) []byte {
   277  		return fmt.Appendln(b, v...)
   278  	})
   279  }
   280  
   281  // Fatal is equivalent to l.Print() followed by a call to [os.Exit](1).
   282  func (l *Logger) Fatal(v ...any) {
   283  	l.Output(2, fmt.Sprint(v...))
   284  	os.Exit(1)
   285  }
   286  
   287  // Fatalf is equivalent to l.Printf() followed by a call to [os.Exit](1).
   288  func (l *Logger) Fatalf(format string, v ...any) {
   289  	l.Output(2, fmt.Sprintf(format, v...))
   290  	os.Exit(1)
   291  }
   292  
   293  // Fatalln is equivalent to l.Println() followed by a call to [os.Exit](1).
   294  func (l *Logger) Fatalln(v ...any) {
   295  	l.Output(2, fmt.Sprintln(v...))
   296  	os.Exit(1)
   297  }
   298  
   299  // Panic is equivalent to l.Print() followed by a call to panic().
   300  func (l *Logger) Panic(v ...any) {
   301  	s := fmt.Sprint(v...)
   302  	l.Output(2, s)
   303  	panic(s)
   304  }
   305  
   306  // Panicf is equivalent to l.Printf() followed by a call to panic().
   307  func (l *Logger) Panicf(format string, v ...any) {
   308  	s := fmt.Sprintf(format, v...)
   309  	l.Output(2, s)
   310  	panic(s)
   311  }
   312  
   313  // Panicln is equivalent to l.Println() followed by a call to panic().
   314  func (l *Logger) Panicln(v ...any) {
   315  	s := fmt.Sprintln(v...)
   316  	l.Output(2, s)
   317  	panic(s)
   318  }
   319  
   320  // Flags returns the output flags for the logger.
   321  // The flag bits are [Ldate], [Ltime], and so on.
   322  func (l *Logger) Flags() int {
   323  	return int(l.flag.Load())
   324  }
   325  
   326  // SetFlags sets the output flags for the logger.
   327  // The flag bits are [Ldate], [Ltime], and so on.
   328  func (l *Logger) SetFlags(flag int) {
   329  	l.flag.Store(int32(flag))
   330  }
   331  
   332  // Prefix returns the output prefix for the logger.
   333  func (l *Logger) Prefix() string {
   334  	if p := l.prefix.Load(); p != nil {
   335  		return *p
   336  	}
   337  	return ""
   338  }
   339  
   340  // SetPrefix sets the output prefix for the logger.
   341  func (l *Logger) SetPrefix(prefix string) {
   342  	l.prefix.Store(&prefix)
   343  }
   344  
   345  // Writer returns the output destination for the logger.
   346  func (l *Logger) Writer() io.Writer {
   347  	l.outMu.Lock()
   348  	defer l.outMu.Unlock()
   349  	return l.out
   350  }
   351  
   352  // SetOutput sets the output destination for the standard logger.
   353  func SetOutput(w io.Writer) {
   354  	std.SetOutput(w)
   355  }
   356  
   357  // Flags returns the output flags for the standard logger.
   358  // The flag bits are [Ldate], [Ltime], and so on.
   359  func Flags() int {
   360  	return std.Flags()
   361  }
   362  
   363  // SetFlags sets the output flags for the standard logger.
   364  // The flag bits are [Ldate], [Ltime], and so on.
   365  func SetFlags(flag int) {
   366  	std.SetFlags(flag)
   367  }
   368  
   369  // Prefix returns the output prefix for the standard logger.
   370  func Prefix() string {
   371  	return std.Prefix()
   372  }
   373  
   374  // SetPrefix sets the output prefix for the standard logger.
   375  func SetPrefix(prefix string) {
   376  	std.SetPrefix(prefix)
   377  }
   378  
   379  // Writer returns the output destination for the standard logger.
   380  func Writer() io.Writer {
   381  	return std.Writer()
   382  }
   383  
   384  // These functions write to the standard logger.
   385  
   386  // Print calls Output to print to the standard logger.
   387  // Arguments are handled in the manner of [fmt.Print].
   388  func Print(v ...any) {
   389  	std.output(0, 2, func(b []byte) []byte {
   390  		return fmt.Append(b, v...)
   391  	})
   392  }
   393  
   394  // Printf calls Output to print to the standard logger.
   395  // Arguments are handled in the manner of [fmt.Printf].
   396  func Printf(format string, v ...any) {
   397  	std.output(0, 2, func(b []byte) []byte {
   398  		return fmt.Appendf(b, format, v...)
   399  	})
   400  }
   401  
   402  // Println calls Output to print to the standard logger.
   403  // Arguments are handled in the manner of [fmt.Println].
   404  func Println(v ...any) {
   405  	std.output(0, 2, func(b []byte) []byte {
   406  		return fmt.Appendln(b, v...)
   407  	})
   408  }
   409  
   410  // Fatal is equivalent to [Print] followed by a call to [os.Exit](1).
   411  func Fatal(v ...any) {
   412  	std.Output(2, fmt.Sprint(v...))
   413  	os.Exit(1)
   414  }
   415  
   416  // Fatalf is equivalent to [Printf] followed by a call to [os.Exit](1).
   417  func Fatalf(format string, v ...any) {
   418  	std.Output(2, fmt.Sprintf(format, v...))
   419  	os.Exit(1)
   420  }
   421  
   422  // Fatalln is equivalent to [Println] followed by a call to [os.Exit](1).
   423  func Fatalln(v ...any) {
   424  	std.Output(2, fmt.Sprintln(v...))
   425  	os.Exit(1)
   426  }
   427  
   428  // Panic is equivalent to [Print] followed by a call to panic().
   429  func Panic(v ...any) {
   430  	s := fmt.Sprint(v...)
   431  	std.Output(2, s)
   432  	panic(s)
   433  }
   434  
   435  // Panicf is equivalent to [Printf] followed by a call to panic().
   436  func Panicf(format string, v ...any) {
   437  	s := fmt.Sprintf(format, v...)
   438  	std.Output(2, s)
   439  	panic(s)
   440  }
   441  
   442  // Panicln is equivalent to [Println] followed by a call to panic().
   443  func Panicln(v ...any) {
   444  	s := fmt.Sprintln(v...)
   445  	std.Output(2, s)
   446  	panic(s)
   447  }
   448  
   449  // Output writes the output for a logging event. The string s contains
   450  // the text to print after the prefix specified by the flags of the
   451  // Logger. A newline is appended if the last character of s is not
   452  // already a newline. Calldepth is the count of the number of
   453  // frames to skip when computing the file name and line number
   454  // if [Llongfile] or [Lshortfile] is set; a value of 1 will print the details
   455  // for the caller of Output.
   456  func Output(calldepth int, s string) error {
   457  	return std.Output(calldepth+1, s) // +1 for this frame.
   458  }
   459  

View as plain text