github.com/qiniu/x@v1.11.9/log/logext.go (about)

     1  package log
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"runtime"
     9  	"strings"
    10  	"sync"
    11  	"time"
    12  )
    13  
    14  // These flags define which text to prefix to each log entry generated by the Logger.
    15  const (
    16  	// Bits or'ed together to control what's printed. There is no control over the
    17  	// order they appear (the order listed here) or the format they present (as
    18  	// described in the comments).  A colon appears after these items:
    19  	//	2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
    20  	Ldate         = 1 << iota                     // the date: 2009/0123
    21  	Ltime                                         // the time: 01:23:23
    22  	Lmicroseconds                                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
    23  	Llongfile                                     // full file name and line number: /a/b/c/d.go:23
    24  	Lshortfile                                    // final file name element and line number: d.go:23. overrides Llongfile
    25  	Lmodule                                       // module name
    26  	Llevel                                        // level: 0(Debug), 1(Info), 2(Warn), 3(Error), 4(Panic), 5(Fatal)
    27  	LstdFlags     = Ldate | Ltime | Lmicroseconds // initial values for the standard logger
    28  	Ldefault      = Lmodule | Llevel | Lshortfile | LstdFlags
    29  ) // [prefix][time][level][module][shortfile|longfile]
    30  
    31  const (
    32  	// Ldebug is a log output level that prints debug information.
    33  	Ldebug = iota
    34  	// Linfo is a log output level that prints prompting information.
    35  	Linfo
    36  	// Lwarn is a log output level that prints warning information.
    37  	Lwarn
    38  	// Lerror is a log output level that prints error information.
    39  	Lerror
    40  	// Lpanic is a log output level that prints error information.
    41  	Lpanic
    42  	// Lfatal is a log output level that prints fatal information.
    43  	Lfatal
    44  )
    45  
    46  var levels = []string{
    47  	"[DEBUG]",
    48  	"[INFO]",
    49  	"[WARN]",
    50  	"[ERROR]",
    51  	"[PANIC]",
    52  	"[FATAL]",
    53  }
    54  
    55  // A Logger represents an active logging object that generates lines of
    56  // output to an io.Writer.  Each logging operation makes a single call to
    57  // the Writer's Write method.  A Logger can be used simultaneously from
    58  // multiple goroutines; it guarantees to serialize access to the Writer.
    59  type Logger struct {
    60  	mu         sync.Mutex   // ensures atomic writes; protects the following fields
    61  	prefix     string       // prefix to write at beginning of each line
    62  	flag       int          // properties
    63  	Level      int          // debug level
    64  	out        io.Writer    // destination for output
    65  	buf        bytes.Buffer // for accumulating text to write
    66  	levelStats [6]int64
    67  }
    68  
    69  // New creates a new Logger.
    70  // The out variable sets the destination to which log data will be written.
    71  // The prefix appears at the beginning of each generated log line.
    72  // The flag argument defines the logging properties.
    73  func New(out io.Writer, prefix string, flag int) *Logger {
    74  	return &Logger{out: out, prefix: prefix, Level: 1, flag: flag}
    75  }
    76  
    77  // Std *Logger.
    78  var Std = New(os.Stderr, "", Ldefault)
    79  
    80  // Cheap integer to fixed-width decimal ASCII.  Give a negative width to avoid zero-padding.
    81  // Knows the buffer has capacity.
    82  func itoa(buf *bytes.Buffer, i int, wid int) {
    83  	var u uint = uint(i)
    84  	if u == 0 && wid <= 1 {
    85  		buf.WriteByte('0')
    86  		return
    87  	}
    88  
    89  	// Assemble decimal in reverse order.
    90  	var b [32]byte
    91  	bp := len(b)
    92  	for ; u > 0 || wid > 0; u /= 10 {
    93  		bp--
    94  		wid--
    95  		b[bp] = byte(u%10) + '0'
    96  	}
    97  
    98  	// avoid slicing b to avoid an allocation.
    99  	for bp < len(b) {
   100  		buf.WriteByte(b[bp])
   101  		bp++
   102  	}
   103  }
   104  
   105  func shortFile(file string, flag int) string {
   106  	sep := "/"
   107  	if (flag & Lmodule) != 0 {
   108  		sep = "/src/"
   109  	}
   110  	pos := strings.LastIndex(file, sep)
   111  	if pos != -1 {
   112  		return file[pos+5:]
   113  	}
   114  	return file
   115  }
   116  
   117  func (l *Logger) formatHeader(buf *bytes.Buffer, t time.Time, file string, line int, lvl int, reqID string) {
   118  	if l.prefix != "" {
   119  		buf.WriteString(l.prefix)
   120  	}
   121  	flag := l.flag
   122  	if flag&(Ldate|Ltime|Lmicroseconds) != 0 {
   123  		if flag&Ldate != 0 {
   124  			year, month, day := t.Date()
   125  			itoa(buf, year, 4)
   126  			buf.WriteByte('/')
   127  			itoa(buf, int(month), 2)
   128  			buf.WriteByte('/')
   129  			itoa(buf, day, 2)
   130  			buf.WriteByte(' ')
   131  		}
   132  		if flag&(Ltime|Lmicroseconds) != 0 {
   133  			hour, min, sec := t.Clock()
   134  			itoa(buf, hour, 2)
   135  			buf.WriteByte(':')
   136  			itoa(buf, min, 2)
   137  			buf.WriteByte(':')
   138  			itoa(buf, sec, 2)
   139  			if flag&Lmicroseconds != 0 {
   140  				buf.WriteByte('.')
   141  				itoa(buf, t.Nanosecond()/1e3, 6)
   142  			}
   143  			buf.WriteByte(' ')
   144  		}
   145  	}
   146  	if reqID != "" {
   147  		buf.WriteByte('[')
   148  		buf.WriteString(reqID)
   149  		buf.WriteByte(']')
   150  	}
   151  	if flag&Llevel != 0 {
   152  		buf.WriteString(levels[lvl])
   153  	}
   154  	if flag&(Lshortfile|Llongfile) != 0 {
   155  		if flag&Lshortfile != 0 {
   156  			file = shortFile(file, flag)
   157  		}
   158  		buf.WriteByte(' ')
   159  		buf.WriteString(file)
   160  		buf.WriteByte(':')
   161  		itoa(buf, line, -1)
   162  		buf.WriteString(": ")
   163  	} else if flag&Llevel != 0 {
   164  		buf.WriteByte(' ')
   165  	}
   166  }
   167  
   168  // Output writes the output for a logging event.  The string s contains
   169  // the text to print after the prefix specified by the flags of the
   170  // Logger.  A newline is appended if the last character of s is not
   171  // already a newline.  Calldepth is used to recover the PC and is
   172  // provided for generality, although at the moment on all pre-defined
   173  // paths it will be 2.
   174  func (l *Logger) Output(reqID string, lvl int, calldepth int, s string) error {
   175  	if lvl < l.Level {
   176  		return nil
   177  	}
   178  	now := time.Now() // get this early.
   179  	var file string
   180  	var line int
   181  	l.mu.Lock()
   182  	defer l.mu.Unlock()
   183  	if l.flag&(Lshortfile|Llongfile|Lmodule) != 0 {
   184  		// release lock while getting caller info - it's expensive.
   185  		l.mu.Unlock()
   186  		var ok bool
   187  		_, file, line, ok = runtime.Caller(calldepth)
   188  		if !ok {
   189  			file = "???"
   190  			line = 0
   191  		}
   192  		l.mu.Lock()
   193  	}
   194  	l.levelStats[lvl]++
   195  	l.buf.Reset()
   196  	l.formatHeader(&l.buf, now, file, line, lvl, reqID)
   197  	l.buf.WriteString(s)
   198  	if len(s) > 0 && s[len(s)-1] != '\n' {
   199  		l.buf.WriteByte('\n')
   200  	}
   201  	_, err := l.out.Write(l.buf.Bytes())
   202  	return err
   203  }
   204  
   205  // -----------------------------------------
   206  
   207  // Printf calls l.Output to print to the logger.
   208  // Arguments are handled in the manner of fmt.Printf.
   209  func (l *Logger) Printf(format string, v ...interface{}) {
   210  	l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
   211  }
   212  
   213  // Print calls l.Output to print to the logger.
   214  // Arguments are handled in the manner of fmt.Print.
   215  func (l *Logger) Print(v ...interface{}) { l.Output("", Linfo, 2, fmt.Sprint(v...)) }
   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 ...interface{}) { l.Output("", Linfo, 2, fmt.Sprintln(v...)) }
   220  
   221  // -----------------------------------------
   222  
   223  // Debugf prints a debug information.
   224  func (l *Logger) Debugf(format string, v ...interface{}) {
   225  	if Ldebug < l.Level {
   226  		return
   227  	}
   228  	l.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
   229  }
   230  
   231  // Debug prints a debug information.
   232  func (l *Logger) Debug(v ...interface{}) {
   233  	if Ldebug < l.Level {
   234  		return
   235  	}
   236  	l.Output("", Ldebug, 2, fmt.Sprintln(v...))
   237  }
   238  
   239  // -----------------------------------------
   240  
   241  // Infof prints a prompting information.
   242  func (l *Logger) Infof(format string, v ...interface{}) {
   243  	if Linfo < l.Level {
   244  		return
   245  	}
   246  	l.Output("", Linfo, 2, fmt.Sprintf(format, v...))
   247  }
   248  
   249  // Info prints a prompting information.
   250  func (l *Logger) Info(v ...interface{}) {
   251  	if Linfo < l.Level {
   252  		return
   253  	}
   254  	l.Output("", Linfo, 2, fmt.Sprintln(v...))
   255  }
   256  
   257  // -----------------------------------------
   258  
   259  // Warnf prints a warning information.
   260  func (l *Logger) Warnf(format string, v ...interface{}) {
   261  	l.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
   262  }
   263  
   264  // Warn prints a warning information.
   265  func (l *Logger) Warn(v ...interface{}) { l.Output("", Lwarn, 2, fmt.Sprintln(v...)) }
   266  
   267  // -----------------------------------------
   268  
   269  // Errorf prints an error information.
   270  func (l *Logger) Errorf(format string, v ...interface{}) {
   271  	l.Output("", Lerror, 2, fmt.Sprintf(format, v...))
   272  }
   273  
   274  // Error prints an error information.
   275  func (l *Logger) Error(v ...interface{}) { l.Output("", Lerror, 2, fmt.Sprintln(v...)) }
   276  
   277  // -----------------------------------------
   278  
   279  // Fatal prints an error information and exit app.
   280  func (l *Logger) Fatal(v ...interface{}) {
   281  	l.Output("", Lfatal, 2, fmt.Sprint(v...))
   282  	os.Exit(1)
   283  }
   284  
   285  // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).
   286  func (l *Logger) Fatalf(format string, v ...interface{}) {
   287  	l.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
   288  	os.Exit(1)
   289  }
   290  
   291  // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).
   292  func (l *Logger) Fatalln(v ...interface{}) {
   293  	l.Output("", Lfatal, 2, fmt.Sprintln(v...))
   294  	os.Exit(1)
   295  }
   296  
   297  // -----------------------------------------
   298  
   299  // Panic is equivalent to l.Print() followed by a call to panic().
   300  func (l *Logger) Panic(v ...interface{}) {
   301  	s := fmt.Sprint(v...)
   302  	l.Output("", Lpanic, 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 ...interface{}) {
   308  	s := fmt.Sprintf(format, v...)
   309  	l.Output("", Lpanic, 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 ...interface{}) {
   315  	s := fmt.Sprintln(v...)
   316  	l.Output("", Lpanic, 2, s)
   317  	panic(s)
   318  }
   319  
   320  // -----------------------------------------
   321  
   322  // Stack prints a stack trace of all goroutines.
   323  func (l *Logger) Stack(v ...interface{}) {
   324  	s := fmt.Sprint(v...)
   325  	s += "\n"
   326  	buf := make([]byte, 1024*1024)
   327  	n := runtime.Stack(buf, true)
   328  	s += string(buf[:n])
   329  	s += "\n"
   330  	l.Output("", Lerror, 2, s)
   331  }
   332  
   333  // SingleStack prints a stack trace of the calling goroutines.
   334  func (l *Logger) SingleStack(v ...interface{}) {
   335  	s := fmt.Sprint(v...)
   336  	s += "\n"
   337  	buf := make([]byte, 1024*1024)
   338  	n := runtime.Stack(buf, false)
   339  	s += string(buf[:n])
   340  	s += "\n"
   341  	l.Output("", Lerror, 2, s)
   342  }
   343  
   344  // -----------------------------------------
   345  
   346  // Stat func.
   347  func (l *Logger) Stat() (stats []int64) {
   348  	l.mu.Lock()
   349  	v := l.levelStats
   350  	l.mu.Unlock()
   351  	return v[:]
   352  }
   353  
   354  // Flags returns the output flags for the logger.
   355  func (l *Logger) Flags() int {
   356  	l.mu.Lock()
   357  	defer l.mu.Unlock()
   358  	return l.flag
   359  }
   360  
   361  // SetFlags sets the output flags for the logger.
   362  func (l *Logger) SetFlags(flag int) {
   363  	l.mu.Lock()
   364  	defer l.mu.Unlock()
   365  	l.flag = flag
   366  }
   367  
   368  // Prefix returns the output prefix for the logger.
   369  func (l *Logger) Prefix() string {
   370  	l.mu.Lock()
   371  	defer l.mu.Unlock()
   372  	return l.prefix
   373  }
   374  
   375  // SetPrefix sets the output prefix for the logger.
   376  func (l *Logger) SetPrefix(prefix string) {
   377  	l.mu.Lock()
   378  	defer l.mu.Unlock()
   379  	l.prefix = prefix
   380  }
   381  
   382  // SetOutputLevel sets the output level for the logger.
   383  func (l *Logger) SetOutputLevel(lvl int) {
   384  	l.mu.Lock()
   385  	defer l.mu.Unlock()
   386  	l.Level = lvl
   387  }
   388  
   389  // SetOutput sets the output destination for the standard logger.
   390  func SetOutput(w io.Writer) {
   391  	Std.mu.Lock()
   392  	defer Std.mu.Unlock()
   393  	Std.out = w
   394  }
   395  
   396  // Flags returns the output flags for the standard logger.
   397  func Flags() int {
   398  	return Std.Flags()
   399  }
   400  
   401  // SetFlags sets the output flags for the standard logger.
   402  func SetFlags(flag int) {
   403  	Std.SetFlags(flag)
   404  }
   405  
   406  // Prefix returns the output prefix for the standard logger.
   407  func Prefix() string {
   408  	return Std.Prefix()
   409  }
   410  
   411  // SetPrefix sets the output prefix for the standard logger.
   412  func SetPrefix(prefix string) {
   413  	Std.SetPrefix(prefix)
   414  }
   415  
   416  // SetOutputLevel sets output level.
   417  func SetOutputLevel(lvl int) {
   418  	Std.SetOutputLevel(lvl)
   419  }
   420  
   421  // GetOutputLevel returns output level.
   422  func GetOutputLevel() int {
   423  	return Std.Level
   424  }
   425  
   426  // CanOutput returns to output a message or not.
   427  func CanOutput(lvl int) bool {
   428  	return lvl >= Std.Level
   429  }
   430  
   431  // -----------------------------------------
   432  
   433  // Print calls Output to print to the standard logger.
   434  // Arguments are handled in the manner of fmt.Print.
   435  func Print(v ...interface{}) {
   436  	Std.Output("", Linfo, 2, fmt.Sprint(v...))
   437  }
   438  
   439  // Printf calls Output to print to the standard logger.
   440  // Arguments are handled in the manner of fmt.Printf.
   441  func Printf(format string, v ...interface{}) {
   442  	Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
   443  }
   444  
   445  // Println calls Output to print to the standard logger.
   446  // Arguments are handled in the manner of fmt.Println.
   447  func Println(v ...interface{}) {
   448  	Std.Output("", Linfo, 2, fmt.Sprintln(v...))
   449  }
   450  
   451  // -----------------------------------------
   452  
   453  // Debugf prints a debug information.
   454  func Debugf(format string, v ...interface{}) {
   455  	if Ldebug < Std.Level {
   456  		return
   457  	}
   458  	Std.Output("", Ldebug, 2, fmt.Sprintf(format, v...))
   459  }
   460  
   461  // Debug prints a debug information.
   462  func Debug(v ...interface{}) {
   463  	if Ldebug < Std.Level {
   464  		return
   465  	}
   466  	Std.Output("", Ldebug, 2, fmt.Sprintln(v...))
   467  }
   468  
   469  // -----------------------------------------
   470  
   471  // Infof prints a prompting information.
   472  func Infof(format string, v ...interface{}) {
   473  	if Linfo < Std.Level {
   474  		return
   475  	}
   476  	Std.Output("", Linfo, 2, fmt.Sprintf(format, v...))
   477  }
   478  
   479  // Info prints a prompting information.
   480  func Info(v ...interface{}) {
   481  	if Linfo < Std.Level {
   482  		return
   483  	}
   484  	Std.Output("", Linfo, 2, fmt.Sprintln(v...))
   485  }
   486  
   487  // -----------------------------------------
   488  
   489  // Warnf prints a warning information.
   490  func Warnf(format string, v ...interface{}) {
   491  	Std.Output("", Lwarn, 2, fmt.Sprintf(format, v...))
   492  }
   493  
   494  // Warn prints a warning information.
   495  func Warn(v ...interface{}) { Std.Output("", Lwarn, 2, fmt.Sprintln(v...)) }
   496  
   497  // -----------------------------------------
   498  
   499  // Errorf prints an error information.
   500  func Errorf(format string, v ...interface{}) {
   501  	Std.Output("", Lerror, 2, fmt.Sprintf(format, v...))
   502  }
   503  
   504  // Error prints an error information.
   505  func Error(v ...interface{}) { Std.Output("", Lerror, 2, fmt.Sprintln(v...)) }
   506  
   507  // -----------------------------------------
   508  
   509  // Fatal is equivalent to Print() followed by a call to os.Exit(1).
   510  func Fatal(v ...interface{}) {
   511  	Std.Output("", Lfatal, 2, fmt.Sprint(v...))
   512  	os.Exit(1)
   513  }
   514  
   515  // Fatalf is equivalent to Printf() followed by a call to os.Exit(1).
   516  func Fatalf(format string, v ...interface{}) {
   517  	Std.Output("", Lfatal, 2, fmt.Sprintf(format, v...))
   518  	os.Exit(1)
   519  }
   520  
   521  // Fatalln is equivalent to Println() followed by a call to os.Exit(1).
   522  func Fatalln(v ...interface{}) {
   523  	Std.Output("", Lfatal, 2, fmt.Sprintln(v...))
   524  	os.Exit(1)
   525  }
   526  
   527  // -----------------------------------------
   528  
   529  // Panic is equivalent to Print() followed by a call to panic().
   530  func Panic(v ...interface{}) {
   531  	s := fmt.Sprint(v...)
   532  	Std.Output("", Lpanic, 2, s)
   533  	panic(s)
   534  }
   535  
   536  // Panicf is equivalent to Printf() followed by a call to panic().
   537  func Panicf(format string, v ...interface{}) {
   538  	s := fmt.Sprintf(format, v...)
   539  	Std.Output("", Lpanic, 2, s)
   540  	panic(s)
   541  }
   542  
   543  // Panicln is equivalent to Println() followed by a call to panic().
   544  func Panicln(v ...interface{}) {
   545  	s := fmt.Sprintln(v...)
   546  	Std.Output("", Lpanic, 2, s)
   547  	panic(s)
   548  }
   549  
   550  // -----------------------------------------
   551  
   552  // Stack prints a stack trace of all goroutines.
   553  func Stack(v ...interface{}) {
   554  	Std.Stack(v...)
   555  }
   556  
   557  // SingleStack prints a stack trace of the calling goroutines.
   558  func SingleStack(v ...interface{}) {
   559  	Std.SingleStack(v...)
   560  }