Source file
    src/log/log.go
  
  
    Documentation: log
  
     1  
     2  
     3  
     4  
     5  
     6  
     7  
     8  
     9  
    10  
    11  
    12  
    13  
    14  
    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  
    29  
    30  
    31  
    32  
    33  
    34  
    35  
    36  
    37  
    38  
    39  
    40  
    41  
    42  const (
    43  	Ldate         = 1 << iota     
    44  	Ltime                         
    45  	Lmicroseconds                 
    46  	Llongfile                     
    47  	Lshortfile                    
    48  	LUTC                          
    49  	Lmsgprefix                    
    50  	LstdFlags     = Ldate | Ltime 
    51  )
    52  
    53  
    54  
    55  
    56  
    57  type Logger struct {
    58  	outMu sync.Mutex
    59  	out   io.Writer 
    60  
    61  	prefix    atomic.Pointer[string] 
    62  	flag      atomic.Int32           
    63  	isDiscard atomic.Bool
    64  }
    65  
    66  
    67  
    68  
    69  
    70  
    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  
    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  
    90  func Default() *Logger { return std }
    91  
    92  
    93  func itoa(buf *[]byte, i int, wid int) {
    94  	
    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  	
   105  	b[bp] = byte('0' + i)
   106  	*buf = append(*buf, b[bp:]...)
   107  }
   108  
   109  
   110  
   111  
   112  
   113  
   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  	
   176  	
   177  	
   178  	
   179  	
   180  	
   181  	if cap(*p) > 64<<10 {
   182  		*p = nil
   183  	}
   184  	bufferPool.Put(p)
   185  }
   186  
   187  
   188  
   189  
   190  
   191  
   192  
   193  func (l *Logger) Output(calldepth int, s string) error {
   194  	return l.output(0, calldepth+1, func(b []byte) []byte { 
   195  		return append(b, s...)
   196  	})
   197  }
   198  
   199  
   200  
   201  func (l *Logger) output(pc uintptr, calldepth int, appendOutput func([]byte) []byte) error {
   202  	if l.isDiscard.Load() {
   203  		return nil
   204  	}
   205  
   206  	now := time.Now() 
   207  
   208  	
   209  	
   210  	prefix := l.Prefix()
   211  	flag := l.Flags()
   212  
   213  	var file string
   214  	var line int
   215  	if flag&(Lshortfile|Llongfile) != 0 {
   216  		if pc == 0 {
   217  			var ok bool
   218  			_, file, line, ok = runtime.Caller(calldepth)
   219  			if !ok {
   220  				file = "???"
   221  				line = 0
   222  			}
   223  		} else {
   224  			fs := runtime.CallersFrames([]uintptr{pc})
   225  			f, _ := fs.Next()
   226  			file = f.File
   227  			if file == "" {
   228  				file = "???"
   229  			}
   230  			line = f.Line
   231  		}
   232  	}
   233  
   234  	buf := getBuffer()
   235  	defer putBuffer(buf)
   236  	formatHeader(buf, now, prefix, flag, file, line)
   237  	*buf = appendOutput(*buf)
   238  	if len(*buf) == 0 || (*buf)[len(*buf)-1] != '\n' {
   239  		*buf = append(*buf, '\n')
   240  	}
   241  
   242  	l.outMu.Lock()
   243  	defer l.outMu.Unlock()
   244  	_, err := l.out.Write(*buf)
   245  	return err
   246  }
   247  
   248  func init() {
   249  	internal.DefaultOutput = func(pc uintptr, data []byte) error {
   250  		return std.output(pc, 0, func(buf []byte) []byte {
   251  			return append(buf, data...)
   252  		})
   253  	}
   254  }
   255  
   256  
   257  
   258  func (l *Logger) Print(v ...any) {
   259  	l.output(0, 2, func(b []byte) []byte {
   260  		return fmt.Append(b, v...)
   261  	})
   262  }
   263  
   264  
   265  
   266  func (l *Logger) Printf(format string, v ...any) {
   267  	l.output(0, 2, func(b []byte) []byte {
   268  		return fmt.Appendf(b, format, v...)
   269  	})
   270  }
   271  
   272  
   273  
   274  func (l *Logger) Println(v ...any) {
   275  	l.output(0, 2, func(b []byte) []byte {
   276  		return fmt.Appendln(b, v...)
   277  	})
   278  }
   279  
   280  
   281  func (l *Logger) Fatal(v ...any) {
   282  	l.output(0, 2, func(b []byte) []byte {
   283  		return fmt.Append(b, v...)
   284  	})
   285  	os.Exit(1)
   286  }
   287  
   288  
   289  func (l *Logger) Fatalf(format string, v ...any) {
   290  	l.output(0, 2, func(b []byte) []byte {
   291  		return fmt.Appendf(b, format, v...)
   292  	})
   293  	os.Exit(1)
   294  }
   295  
   296  
   297  func (l *Logger) Fatalln(v ...any) {
   298  	l.output(0, 2, func(b []byte) []byte {
   299  		return fmt.Appendln(b, v...)
   300  	})
   301  	os.Exit(1)
   302  }
   303  
   304  
   305  func (l *Logger) Panic(v ...any) {
   306  	s := fmt.Sprint(v...)
   307  	l.output(0, 2, func(b []byte) []byte {
   308  		return append(b, s...)
   309  	})
   310  	panic(s)
   311  }
   312  
   313  
   314  func (l *Logger) Panicf(format string, v ...any) {
   315  	s := fmt.Sprintf(format, v...)
   316  	l.output(0, 2, func(b []byte) []byte {
   317  		return append(b, s...)
   318  	})
   319  	panic(s)
   320  }
   321  
   322  
   323  func (l *Logger) Panicln(v ...any) {
   324  	s := fmt.Sprintln(v...)
   325  	l.output(0, 2, func(b []byte) []byte {
   326  		return append(b, s...)
   327  	})
   328  	panic(s)
   329  }
   330  
   331  
   332  
   333  func (l *Logger) Flags() int {
   334  	return int(l.flag.Load())
   335  }
   336  
   337  
   338  
   339  func (l *Logger) SetFlags(flag int) {
   340  	l.flag.Store(int32(flag))
   341  }
   342  
   343  
   344  func (l *Logger) Prefix() string {
   345  	if p := l.prefix.Load(); p != nil {
   346  		return *p
   347  	}
   348  	return ""
   349  }
   350  
   351  
   352  func (l *Logger) SetPrefix(prefix string) {
   353  	l.prefix.Store(&prefix)
   354  }
   355  
   356  
   357  func (l *Logger) Writer() io.Writer {
   358  	l.outMu.Lock()
   359  	defer l.outMu.Unlock()
   360  	return l.out
   361  }
   362  
   363  
   364  func SetOutput(w io.Writer) {
   365  	std.SetOutput(w)
   366  }
   367  
   368  
   369  
   370  func Flags() int {
   371  	return std.Flags()
   372  }
   373  
   374  
   375  
   376  func SetFlags(flag int) {
   377  	std.SetFlags(flag)
   378  }
   379  
   380  
   381  func Prefix() string {
   382  	return std.Prefix()
   383  }
   384  
   385  
   386  func SetPrefix(prefix string) {
   387  	std.SetPrefix(prefix)
   388  }
   389  
   390  
   391  func Writer() io.Writer {
   392  	return std.Writer()
   393  }
   394  
   395  
   396  
   397  
   398  
   399  func Print(v ...any) {
   400  	std.output(0, 2, func(b []byte) []byte {
   401  		return fmt.Append(b, v...)
   402  	})
   403  }
   404  
   405  
   406  
   407  func Printf(format string, v ...any) {
   408  	std.output(0, 2, func(b []byte) []byte {
   409  		return fmt.Appendf(b, format, v...)
   410  	})
   411  }
   412  
   413  
   414  
   415  func Println(v ...any) {
   416  	std.output(0, 2, func(b []byte) []byte {
   417  		return fmt.Appendln(b, v...)
   418  	})
   419  }
   420  
   421  
   422  func Fatal(v ...any) {
   423  	std.output(0, 2, func(b []byte) []byte {
   424  		return fmt.Append(b, v...)
   425  	})
   426  	os.Exit(1)
   427  }
   428  
   429  
   430  func Fatalf(format string, v ...any) {
   431  	std.output(0, 2, func(b []byte) []byte {
   432  		return fmt.Appendf(b, format, v...)
   433  	})
   434  	os.Exit(1)
   435  }
   436  
   437  
   438  func Fatalln(v ...any) {
   439  	std.output(0, 2, func(b []byte) []byte {
   440  		return fmt.Appendln(b, v...)
   441  	})
   442  	os.Exit(1)
   443  }
   444  
   445  
   446  func Panic(v ...any) {
   447  	s := fmt.Sprint(v...)
   448  	std.output(0, 2, func(b []byte) []byte {
   449  		return append(b, s...)
   450  	})
   451  	panic(s)
   452  }
   453  
   454  
   455  func Panicf(format string, v ...any) {
   456  	s := fmt.Sprintf(format, v...)
   457  	std.output(0, 2, func(b []byte) []byte {
   458  		return append(b, s...)
   459  	})
   460  	panic(s)
   461  }
   462  
   463  
   464  func Panicln(v ...any) {
   465  	s := fmt.Sprintln(v...)
   466  	std.output(0, 2, func(b []byte) []byte {
   467  		return append(b, s...)
   468  	})
   469  	panic(s)
   470  }
   471  
   472  
   473  
   474  
   475  
   476  
   477  
   478  
   479  func Output(calldepth int, s string) error {
   480  	return std.output(0, calldepth+1, func(b []byte) []byte { 
   481  		return append(b, s...)
   482  	})
   483  }
   484  
View as plain text