123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- package log
- import (
- "encoding/json"
- "fmt"
- "os"
- "runtime"
- "strconv"
- "strings"
- "sync"
- "time"
- "github.com/siddontang/go-log/loggers"
- )
- const (
- timeFormat = "2006/01/02 15:04:05"
- maxBufPoolSize = 16
- )
- // Logger flag
- const (
- Ltime = 1 << iota // time format "2006/01/02 15:04:05"
- Lfile // file.go:123
- Llevel // [Trace|Debug|Info...]
- )
- // Level type
- type Level int
- // Log level, from low to high, more high means more serious
- const (
- LevelTrace Level = iota
- LevelDebug
- LevelInfo
- LevelWarn
- LevelError
- LevelFatal
- )
- // String returns level String
- func (l Level) String() string {
- switch l {
- case LevelTrace:
- return "trace"
- case LevelDebug:
- return "debug"
- case LevelInfo:
- return "info"
- case LevelWarn:
- return "warn"
- case LevelError:
- return "error"
- case LevelFatal:
- return "fatal"
- }
- // return default info
- return "info"
- }
- // Logger is the logger to record log
- type Logger struct {
- // TODO: support logger.Contextual
- loggers.Advanced
- level Level
- flag int
- hLock sync.Mutex
- handler Handler
- bufs sync.Pool
- }
- // New creates a logger with specified handler and flag
- func New(handler Handler, flag int) *Logger {
- var l = new(Logger)
- l.level = LevelInfo
- l.handler = handler
- l.flag = flag
- l.bufs = sync.Pool{
- New: func() interface{} {
- return make([]byte, 0, 1024)
- },
- }
- return l
- }
- // NewDefault creates default logger with specified handler and flag: Ltime|Lfile|Llevel
- func NewDefault(handler Handler) *Logger {
- return New(handler, Ltime|Lfile|Llevel)
- }
- func newStdHandler() *StreamHandler {
- h, _ := NewStreamHandler(os.Stdout)
- return h
- }
- // Close closes the logger
- func (l *Logger) Close() {
- l.hLock.Lock()
- defer l.hLock.Unlock()
- l.handler.Close()
- }
- // SetLevel sets log level, any log level less than it will not log
- func (l *Logger) SetLevel(level Level) {
- l.level = level
- }
- // SetLevelByName sets log level by name
- func (l *Logger) SetLevelByName(name string) {
- level := LevelInfo
- switch strings.ToLower(name) {
- case "trace":
- level = LevelTrace
- case "debug":
- level = LevelDebug
- case "warn", "warning":
- level = LevelWarn
- case "error":
- level = LevelError
- case "fatal":
- level = LevelFatal
- default:
- level = LevelInfo
- }
- l.SetLevel(level)
- }
- // Output records the log with special callstack depth and log level.
- func (l *Logger) Output(callDepth int, level Level, msg string) {
- if l.level > level {
- return
- }
- buf := l.bufs.Get().([]byte)
- buf = buf[0:0]
- defer l.bufs.Put(buf)
- if l.flag&Ltime > 0 {
- now := time.Now().Format(timeFormat)
- buf = append(buf, '[')
- buf = append(buf, now...)
- buf = append(buf, "] "...)
- }
- if l.flag&Llevel > 0 {
- buf = append(buf, '[')
- buf = append(buf, level.String()...)
- buf = append(buf, "] "...)
- }
- if l.flag&Lfile > 0 {
- _, file, line, ok := runtime.Caller(callDepth)
- if !ok {
- file = "???"
- line = 0
- } else {
- for i := len(file) - 1; i > 0; i-- {
- if file[i] == '/' {
- file = file[i+1:]
- break
- }
- }
- }
- buf = append(buf, file...)
- buf = append(buf, ':')
- buf = strconv.AppendInt(buf, int64(line), 10)
- buf = append(buf, ' ')
- }
- buf = append(buf, msg...)
- if len(msg) == 0 || msg[len(msg)-1] != '\n' {
- buf = append(buf, '\n')
- }
- l.hLock.Lock()
- l.handler.Write(buf)
- l.hLock.Unlock()
- }
- // Output json format records the log with special callstack depth and log level.
- func (l *Logger) OutputJson(callDepth int, level Level, body interface{}) {
- if l.level > level {
- return
- }
- buf := l.bufs.Get().([]byte)
- buf = buf[0:0]
- defer l.bufs.Put(buf)
- type JsonLog struct {
- Time string `json:"log_time"`
- Level string `json:"log_level"`
- File string `json:"log_file"`
- Line string `json:"log_line"`
- Body interface{} `json:"log_body"`
- }
- var jsonlog JsonLog
- if l.flag&Ltime > 0 {
- now := time.Now().Format(timeFormat)
- jsonlog.Time = now
- }
- if l.flag&Llevel > 0 {
- jsonlog.Level = level.String()
- }
- if l.flag&Lfile > 0 {
- _, file, line, ok := runtime.Caller(callDepth)
- if !ok {
- file = "???"
- line = 0
- } else {
- for i := len(file) - 1; i > 0; i-- {
- if file[i] == '/' {
- file = file[i+1:]
- break
- }
- }
- }
- jsonlog.File = file
- jsonlog.Line = string(strconv.AppendInt(buf, int64(line), 10))
- }
- jsonlog.Body = body
- msg, _ := json.Marshal(jsonlog)
- msg = append(msg, '\n')
- l.hLock.Lock()
- l.handler.Write(msg)
- l.hLock.Unlock()
- }
- // Fatal records the log with fatal level and exits
- func (l *Logger) Fatal(args ...interface{}) {
- l.Output(2, LevelFatal, fmt.Sprint(args...))
- os.Exit(1)
- }
- // Fatalf records the log with fatal level and exits
- func (l *Logger) Fatalf(format string, args ...interface{}) {
- l.Output(2, LevelFatal, fmt.Sprintf(format, args...))
- os.Exit(1)
- }
- // Fatalln records the log with fatal level and exits
- func (l *Logger) Fatalln(args ...interface{}) {
- l.Output(2, LevelFatal, fmt.Sprintln(args...))
- os.Exit(1)
- }
- // Panic records the log with fatal level and panics
- func (l *Logger) Panic(args ...interface{}) {
- msg := fmt.Sprint(args...)
- l.Output(2, LevelError, msg)
- panic(msg)
- }
- // Panicf records the log with fatal level and panics
- func (l *Logger) Panicf(format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- l.Output(2, LevelError, msg)
- panic(msg)
- }
- // Panicln records the log with fatal level and panics
- func (l *Logger) Panicln(args ...interface{}) {
- msg := fmt.Sprintln(args...)
- l.Output(2, LevelError, msg)
- panic(msg)
- }
- // Print records the log with trace level
- func (l *Logger) Print(args ...interface{}) {
- l.Output(2, LevelTrace, fmt.Sprint(args...))
- }
- // Printf records the log with trace level
- func (l *Logger) Printf(format string, args ...interface{}) {
- l.Output(2, LevelTrace, fmt.Sprintf(format, args...))
- }
- // Println records the log with trace level
- func (l *Logger) Println(args ...interface{}) {
- l.Output(2, LevelTrace, fmt.Sprintln(args...))
- }
- // Debug records the log with debug level
- func (l *Logger) Debug(args ...interface{}) {
- l.Output(2, LevelDebug, fmt.Sprint(args...))
- }
- // Debugf records the log with debug level
- func (l *Logger) Debugf(format string, args ...interface{}) {
- l.Output(2, LevelDebug, fmt.Sprintf(format, args...))
- }
- // Debugln records the log with debug level
- func (l *Logger) Debugln(args ...interface{}) {
- l.Output(2, LevelDebug, fmt.Sprintln(args...))
- }
- // Error records the log with error level
- func (l *Logger) Error(args ...interface{}) {
- l.Output(2, LevelError, fmt.Sprint(args...))
- }
- // Errorf records the log with error level
- func (l *Logger) Errorf(format string, args ...interface{}) {
- l.Output(2, LevelError, fmt.Sprintf(format, args...))
- }
- // Errorln records the log with error level
- func (l *Logger) Errorln(args ...interface{}) {
- l.Output(2, LevelError, fmt.Sprintln(args...))
- }
- // Info records the log with info level
- func (l *Logger) Info(args ...interface{}) {
- l.Output(2, LevelInfo, fmt.Sprint(args...))
- }
- // Infof records the log with info level
- func (l *Logger) Infof(format string, args ...interface{}) {
- l.Output(2, LevelInfo, fmt.Sprintf(format, args...))
- }
- // Infoln records the log with info level
- func (l *Logger) Infoln(args ...interface{}) {
- l.Output(2, LevelInfo, fmt.Sprintln(args...))
- }
- // Warn records the log with warn level
- func (l *Logger) Warn(args ...interface{}) {
- l.Output(2, LevelWarn, fmt.Sprint(args...))
- }
- // Warnf records the log with warn level
- func (l *Logger) Warnf(format string, args ...interface{}) {
- l.Output(2, LevelWarn, fmt.Sprintf(format, args...))
- }
- // Warnln records the log with warn level
- func (l *Logger) Warnln(args ...interface{}) {
- l.Output(2, LevelWarn, fmt.Sprintln(args...))
- }
|