github.com/bibaroc/wingman@v0.0.2-0.20200911182922-33c2085136b1/pkg/logger/logger.go (about)

     1  package logger
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"sync"
     9  
    10  	"github.com/bibaroc/wingman/pkg"
    11  )
    12  
    13  type LogLevel int
    14  
    15  const (
    16  	FATAL   LogLevel = iota // [FATA]
    17  	ERROR                   // [ERRO]
    18  	WARNING                 // [WARN]
    19  	INFO                    // [INFO]
    20  	DEBUG                   // [DEBU]
    21  	TRACE                   // [TRAC]
    22  )
    23  
    24  const (
    25  	WithCallerInfo = 1 << iota
    26  )
    27  
    28  var (
    29  	_ pkg.Logger = (*Log)(nil)
    30  )
    31  
    32  type Log struct {
    33  	level LogLevel
    34  	out   io.Writer
    35  	flags int
    36  	buff  cbuff
    37  	b     sync.Pool
    38  	sync.Mutex
    39  }
    40  
    41  func (l *Log) Panic(v ...interface{}) {
    42  	panic(l.write(ERROR, v...))
    43  }
    44  func (l *Log) Panicf(format string, v ...interface{}) {
    45  	panic(l.writef(ERROR, format, v...))
    46  }
    47  func (l *Log) Panicln(v ...interface{}) {
    48  	panic(l.writeln(ERROR, v...))
    49  }
    50  
    51  func (l *Log) Fatal(v ...interface{}) {
    52  	if err := l.write(ERROR, v...); err != nil {
    53  		fmt.Println(err)
    54  	}
    55  	os.Exit(1)
    56  }
    57  func (l *Log) Fatalf(format string, v ...interface{}) {
    58  	if err := l.writef(ERROR, format, v...); err != nil {
    59  		fmt.Println(err)
    60  	}
    61  	os.Exit(1)
    62  }
    63  func (l *Log) Fatalln(v ...interface{}) {
    64  	if err := l.writeln(ERROR, v...); err != nil {
    65  		fmt.Println(err)
    66  	}
    67  	os.Exit(1)
    68  }
    69  
    70  func (l *Log) Error(v ...interface{}) {
    71  	if l.level < ERROR {
    72  		return
    73  	}
    74  	if err := l.write(ERROR, v...); err != nil {
    75  		fmt.Println(err)
    76  	}
    77  }
    78  func (l *Log) Errorf(format string, v ...interface{}) {
    79  	if l.level < ERROR {
    80  		return
    81  	}
    82  	if err := l.writef(ERROR, format, v...); err != nil {
    83  		fmt.Println(err)
    84  	}
    85  }
    86  func (l *Log) Errorln(v ...interface{}) {
    87  	if l.level < ERROR {
    88  		return
    89  	}
    90  	if err := l.writeln(ERROR, v...); err != nil {
    91  		fmt.Println(err)
    92  	}
    93  }
    94  
    95  func (l *Log) Warn(v ...interface{}) {
    96  	if l.level < WARNING {
    97  		return
    98  	}
    99  	if err := l.write(WARNING, v...); err != nil {
   100  		fmt.Println(err)
   101  	}
   102  }
   103  func (l *Log) Warnf(format string, v ...interface{}) {
   104  	if l.level < WARNING {
   105  		return
   106  	}
   107  	if err := l.writef(WARNING, format, v...); err != nil {
   108  		fmt.Println(err)
   109  	}
   110  }
   111  func (l *Log) Warnln(v ...interface{}) {
   112  	if l.level < WARNING {
   113  		return
   114  	}
   115  	if err := l.writeln(WARNING, v...); err != nil {
   116  		fmt.Println(err)
   117  	}
   118  }
   119  
   120  func (l *Log) Info(v ...interface{}) {
   121  	if l.level < INFO {
   122  		return
   123  	}
   124  	if err := l.write(INFO, v...); err != nil {
   125  		fmt.Println(err)
   126  	}
   127  }
   128  func (l *Log) Infof(format string, v ...interface{}) {
   129  	if l.level < INFO {
   130  		return
   131  	}
   132  	if err := l.writef(INFO, format, v...); err != nil {
   133  		fmt.Println(err)
   134  	}
   135  }
   136  func (l *Log) Infoln(v ...interface{}) {
   137  	if l.level < INFO {
   138  		return
   139  	}
   140  	if err := l.writeln(INFO, v...); err != nil {
   141  		fmt.Println(err)
   142  	}
   143  }
   144  
   145  func (l *Log) Debug(v ...interface{}) {
   146  	if l.level < DEBUG {
   147  		return
   148  	}
   149  	if err := l.write(DEBUG, v...); err != nil {
   150  		fmt.Println(err)
   151  	}
   152  }
   153  func (l *Log) Debugf(format string, v ...interface{}) {
   154  	if l.level < DEBUG {
   155  		return
   156  	}
   157  	if err := l.writef(DEBUG, format, v...); err != nil {
   158  		fmt.Println(err)
   159  	}
   160  }
   161  func (l *Log) Debugln(v ...interface{}) {
   162  	if l.level < DEBUG {
   163  		return
   164  	}
   165  	if err := l.writeln(DEBUG, v...); err != nil {
   166  		fmt.Println(err)
   167  	}
   168  }
   169  
   170  func (l *Log) Trace(v ...interface{}) {
   171  	if l.level < TRACE {
   172  		return
   173  	}
   174  	if err := l.write(TRACE, v...); err != nil {
   175  		fmt.Println(err)
   176  	}
   177  }
   178  func (l *Log) Tracef(format string, v ...interface{}) {
   179  	if l.level < TRACE {
   180  		return
   181  	}
   182  	if err := l.writef(TRACE, format, v...); err != nil {
   183  		fmt.Println(err)
   184  	}
   185  }
   186  func (l *Log) Traceln(v ...interface{}) {
   187  	if l.level < TRACE {
   188  		return
   189  	}
   190  	if err := l.writeln(TRACE, v...); err != nil {
   191  		fmt.Println(err)
   192  	}
   193  }
   194  
   195  func (l *Log) Print(v ...interface{}) {
   196  	if err := l.write(ERROR, v...); err != nil {
   197  		fmt.Println(err)
   198  	}
   199  }
   200  func (l *Log) Printf(format string, v ...interface{}) {
   201  	if err := l.writef(ERROR, format, v...); err != nil {
   202  		fmt.Println(err)
   203  	}
   204  }
   205  func (l *Log) Println(v ...interface{}) {
   206  	if err := l.writeln(ERROR, v...); err != nil {
   207  		fmt.Println(err)
   208  	}
   209  }
   210  func (l *Log) caller() string {
   211  	if l.flags&WithCallerInfo == 0 {
   212  		return "-"
   213  	}
   214  	const SKIPCALLERS = 3
   215  	const NOTFOUND = "n/a"
   216  
   217  	c := []uintptr{0}
   218  	if callers(SKIPCALLERS, c) == 0 {
   219  		return NOTFOUND
   220  	}
   221  
   222  	fnc := findfunc(c[0])
   223  	if !fnc.valid() {
   224  		return NOTFOUND
   225  	}
   226  
   227  	fnName := funcname(fnc)
   228  	for i := len(fnName) - 1; i >= 0; i-- {
   229  		if os.IsPathSeparator(fnName[i]) {
   230  			return fnName[i+1:]
   231  		}
   232  	}
   233  	return fnName
   234  }
   235  
   236  func (l *Log) write(level LogLevel, args ...interface{}) error {
   237  	callerInfo := l.caller()
   238  
   239  	buff := l.b.Get().(*bytes.Buffer)
   240  	buff.Reset()
   241  
   242  	buff.WriteString(level.String())
   243  	buff.WriteByte(' ')
   244  	buff.WriteString(callerInfo)
   245  	buff.WriteByte(' ')
   246  
   247  	fmt.Fprint(buff, args...)
   248  
   249  	l.Lock()
   250  	_, err := l.out.Write(buff.Bytes())
   251  	l.Unlock()
   252  
   253  	l.b.Put(buff)
   254  	return err
   255  }
   256  func (l *Log) writeln(level LogLevel, args ...interface{}) error {
   257  	callerInfo := l.caller()
   258  
   259  	buff := l.b.Get().(*bytes.Buffer)
   260  	buff.Reset()
   261  
   262  	buff.WriteString(level.String())
   263  	buff.WriteByte(' ')
   264  	buff.WriteString(callerInfo)
   265  	buff.WriteByte(' ')
   266  
   267  	fmt.Fprintln(buff, args...)
   268  
   269  	l.Lock()
   270  	_, err := l.out.Write(buff.Bytes())
   271  	l.Unlock()
   272  
   273  	l.b.Put(buff)
   274  
   275  	return err
   276  }
   277  func (l *Log) writef(level LogLevel, format string, args ...interface{}) error {
   278  	callerInfo := l.caller()
   279  
   280  	buff := l.b.Get().(*bytes.Buffer)
   281  	buff.Reset()
   282  
   283  	buff.WriteString(level.String())
   284  	buff.WriteByte(' ')
   285  	buff.WriteString(callerInfo)
   286  	buff.WriteByte(' ')
   287  
   288  	fmt.Fprintf(buff, format, args...)
   289  	l.Lock()
   290  	_, err := l.out.Write(buff.Bytes())
   291  	l.Unlock()
   292  
   293  	l.b.Put(buff)
   294  	return err
   295  }
   296  
   297  func NewLogger(
   298  	level LogLevel,
   299  	writer io.Writer,
   300  	flags int,
   301  ) *Log {
   302  	return &Log{
   303  		level: level,
   304  		out:   writer,
   305  		flags: flags,
   306  		b: sync.Pool{
   307  			New: func() interface{} {
   308  				return bytes.NewBuffer(make([]byte, 0, 10*1<<10))
   309  			},
   310  		},
   311  	}
   312  }
   313  
   314  func NewDebugLogger() *Log {
   315  	return NewLogger(
   316  		DEBUG,
   317  		os.Stdout,
   318  		WithCallerInfo,
   319  	)
   320  }