gitee.com/quant1x/gox@v1.7.6/logger/logger.go (about)

     1  package logger
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"gitee.com/quant1x/gox/api"
     8  	"gitee.com/quant1x/gox/exception"
     9  	"gitee.com/quant1x/gox/mdc"
    10  	"gitee.com/quant1x/gox/signal"
    11  	"os"
    12  	"path/filepath"
    13  	"reflect"
    14  	"runtime"
    15  	"time"
    16  )
    17  
    18  const (
    19  	DEBUG LogLevel = iota
    20  	INFO
    21  	WARN
    22  	ERROR
    23  	OFF
    24  	FATAL
    25  )
    26  
    27  // 日志默认以天为单位
    28  const (
    29  	// 保持7天 [wangfeng on 2018/12/25 12:38]
    30  	__logger_roller_days int = 7
    31  	//__logget_global_skip = 3
    32  	__logger_local_skip = 2
    33  	// 时间戳 - 毫秒
    34  	Timestamp = "2006-01-02T15:04:05.000"
    35  	//traceID
    36  	__logger_traceId = mdc.APP_TRACEID
    37  )
    38  
    39  var (
    40  	__logger_path string
    41  )
    42  
    43  var (
    44  	logLevel LogLevel = DEBUG
    45  
    46  	logQueue  = make(chan *logValue, 10000)
    47  	loggerMap = make(map[string]*Logger)
    48  	writeDone = make(chan bool)
    49  
    50  	currUnixTime int64
    51  	currDateTime string
    52  	currDateHour string
    53  	currDateDay  string
    54  )
    55  
    56  type Logger struct {
    57  	name   string
    58  	writer LogWriter
    59  }
    60  type LogLevel uint8
    61  
    62  type logValue struct {
    63  	level  LogLevel
    64  	value  []byte
    65  	fileNo string
    66  	writer LogWriter
    67  }
    68  
    69  func init() {
    70  	now := time.Now()
    71  	currUnixTime = now.Unix()
    72  	currDateTime = now.Format(Timestamp)
    73  	currDateHour = now.Format("2006010215")
    74  	currDateDay = now.Format("20060102")
    75  	go func() {
    76  		tm := time.NewTimer(time.Millisecond)
    77  		if err := recover(); err != nil { // avoid timer panic
    78  		}
    79  		for {
    80  			now := time.Now()
    81  			d := time.Second - time.Duration(now.Nanosecond())
    82  			tm.Reset(d)
    83  			<-tm.C
    84  			now = time.Now()
    85  			currUnixTime = now.Unix()
    86  			currDateTime = now.Format(Timestamp)
    87  			currDateHour = now.Format("2006010215")
    88  			currDateDay = now.Format("20060102")
    89  		}
    90  	}()
    91  	go flushLog(true)
    92  
    93  	//创建监听退出chan
    94  	sigs := signal.Notify()
    95  
    96  	_, cancel := context.WithCancel(context.Background())
    97  
    98  	go func() {
    99  		s := <-sigs
   100  		Infof("exit sign, [%+v]", s)
   101  		FlushLogger()
   102  		fmt.Println("exit", s)
   103  		cancel()
   104  		os.Exit(0)
   105  	}()
   106  
   107  }
   108  
   109  func (lv *LogLevel) String() string {
   110  	switch *lv {
   111  	case DEBUG:
   112  		return "DEBUG"
   113  	case INFO:
   114  		return "INFO"
   115  	case WARN:
   116  		return "WARN"
   117  	case ERROR:
   118  		return "ERROR"
   119  	case FATAL:
   120  		return "FATAL"
   121  	default:
   122  		return "UNKNOWN"
   123  	}
   124  }
   125  
   126  // SetLogPath 设置日志路径, 默认是INFO级别日志
   127  //
   128  //	Deprecated: 推荐使用 InitLogger
   129  func SetLogPath(path string) {
   130  	InitLogger(path, INFO)
   131  }
   132  
   133  // InitLogger 初始化
   134  func InitLogger(path string, level ...LogLevel) {
   135  	// 日志路径非空, 赋值
   136  	if !api.IsEmpty(path) {
   137  		__logger_path = path
   138  	}
   139  
   140  	// 日志级别默认是INFO
   141  	__opt_level := INFO
   142  	if len(level) > 0 {
   143  		__opt_level = level[0]
   144  	}
   145  	SetLevel(__opt_level)
   146  }
   147  
   148  // GetLogger return an logger instance
   149  func GetLogger(name string) *Logger {
   150  	if lg, ok := loggerMap[name]; ok {
   151  		return lg
   152  	}
   153  	lg := &Logger{
   154  		name:   name,
   155  		writer: &ConsoleWriter{},
   156  	}
   157  	_ = lg.SetDayRoller(__logger_path, __logger_roller_days)
   158  	loggerMap[name] = lg
   159  	return lg
   160  }
   161  
   162  func SetLevel(level LogLevel) {
   163  	logLevel = level
   164  }
   165  
   166  // IsDebug 是否DEBUG模式
   167  func IsDebug() bool {
   168  	if DEBUG < logLevel {
   169  		return false
   170  	}
   171  	return true
   172  }
   173  
   174  func StringToLevel(level string) LogLevel {
   175  	switch level {
   176  	case "DEBUG":
   177  		return DEBUG
   178  	case "INFO":
   179  		return INFO
   180  	case "WARN":
   181  		return WARN
   182  	case "ERROR":
   183  		return ERROR
   184  	case "FATAL":
   185  		return FATAL
   186  	default:
   187  		return DEBUG
   188  	}
   189  }
   190  
   191  func (l *Logger) SetLogName(name string) {
   192  	l.name = name
   193  }
   194  
   195  func (l *Logger) SetFileRoller(logpath string, num int, sizeMB int) error {
   196  	if err := os.MkdirAll(logpath, 0755); err != nil {
   197  		panic(err)
   198  	}
   199  	w := NewRollFileWriter(logpath, l.name, num, sizeMB)
   200  	l.writer = w
   201  	return nil
   202  }
   203  
   204  func (l *Logger) IsConsoleWriter() bool {
   205  	if reflect.TypeOf(l.writer) == reflect.TypeOf(&ConsoleWriter{}) {
   206  		return true
   207  	}
   208  	return false
   209  }
   210  
   211  func (l *Logger) SetWriter(w LogWriter) {
   212  	l.writer = w
   213  }
   214  
   215  func (l *Logger) SetDayRoller(logpath string, num int) error {
   216  	if err := os.MkdirAll(logpath, 0755); err != nil {
   217  		return err
   218  	}
   219  	w := NewDateWriter(logpath, l.name, DAY, num)
   220  	l.writer = w
   221  	return nil
   222  }
   223  
   224  func (l *Logger) SetHourRoller(logpath string, num int) error {
   225  	if err := os.MkdirAll(logpath, 0755); err != nil {
   226  		return err
   227  	}
   228  	w := NewDateWriter(logpath, l.name, HOUR, num)
   229  	l.writer = w
   230  	return nil
   231  }
   232  
   233  func (l *Logger) SetConsole() {
   234  	l.writer = &ConsoleWriter{}
   235  }
   236  
   237  func (l *Logger) Debug(v ...interface{}) {
   238  	l.writef(__logger_local_skip, DEBUG, "", v)
   239  }
   240  
   241  func (l *Logger) Info(v ...interface{}) {
   242  	l.writef(__logger_local_skip, INFO, "", v)
   243  }
   244  
   245  func (l *Logger) Warn(v ...interface{}) {
   246  	l.writef(__logger_local_skip, WARN, "", v)
   247  }
   248  
   249  func (l *Logger) Error(v ...interface{}) {
   250  	l.writef(__logger_local_skip, ERROR, "", v)
   251  }
   252  
   253  func (l *Logger) Debugf(format string, v ...interface{}) {
   254  	l.writef(__logger_local_skip, DEBUG, format, v)
   255  }
   256  
   257  func (l *Logger) Infof(format string, v ...interface{}) {
   258  	l.writef(__logger_local_skip, INFO, format, v)
   259  }
   260  
   261  func (l *Logger) Warnf(format string, v ...interface{}) {
   262  	l.writef(__logger_local_skip, WARN, format, v)
   263  }
   264  
   265  func (l *Logger) Errorf(format string, v ...interface{}) {
   266  	l.writef(__logger_local_skip, ERROR, format, v)
   267  }
   268  
   269  func (l *Logger) Fatal(v ...interface{}) {
   270  	l.writef(__logger_local_skip, FATAL, "", v)
   271  	os.Exit(-1)
   272  }
   273  
   274  func (l *Logger) Fatalf(format string, v ...interface{}) {
   275  	l.writef(__logger_local_skip, FATAL, format, v)
   276  	os.Exit(-1)
   277  }
   278  
   279  func getTraceId() string {
   280  	traceId := mdc.Get(__logger_traceId)
   281  	t := reflect.ValueOf(traceId)
   282  	if t.Kind() == reflect.String {
   283  		return t.String()
   284  	}
   285  	return ""
   286  }
   287  
   288  func (l *Logger) writef(skip int, level LogLevel, format string, v []interface{}) {
   289  	if level < logLevel {
   290  		return
   291  	}
   292  
   293  	t := time.Now()
   294  	//ms := (t.UnixNano() / int64(time.Millisecond)) % 1000
   295  	buf := bytes.NewBuffer(nil)
   296  	if l.writer.NeedPrefix() {
   297  		traceId := getTraceId()
   298  		_, _ = fmt.Fprintf(buf, "%s|%s|", t.Format(Timestamp), traceId)
   299  		if logLevel == DEBUG {
   300  			_, file, line, ok := runtime.Caller(skip)
   301  			if !ok {
   302  				file = "???"
   303  				line = 0
   304  			} else {
   305  				file = filepath.Base(file)
   306  			}
   307  			_, _ = fmt.Fprintf(buf, "%s:%d|", file, line)
   308  		}
   309  	}
   310  	buf.WriteString(level.String())
   311  	buf.WriteByte('|')
   312  
   313  	if format == "" {
   314  		_, _ = fmt.Fprint(buf, v...)
   315  	} else {
   316  		_, _ = fmt.Fprintf(buf, format, v...)
   317  	}
   318  	if l.writer.NeedPrefix() {
   319  		buf.WriteByte('\n')
   320  	}
   321  	logQueue <- &logValue{value: buf.Bytes(), writer: l.writer}
   322  }
   323  
   324  func FlushLogger() {
   325  	flushLog(false)
   326  }
   327  
   328  func flushLog(sync bool) {
   329  	defer exception.PanicIgnore()
   330  	if sync {
   331  		for v := range logQueue {
   332  			v.writer.Write(v.value)
   333  		}
   334  	} else {
   335  		for {
   336  			select {
   337  			case v := <-logQueue:
   338  				v.writer.Write(v.value)
   339  				continue
   340  			default:
   341  				return
   342  			}
   343  		}
   344  	}
   345  }
   346  
   347  func Info(v ...interface{}) {
   348  	logger := GetLogger("runtime")
   349  	logger.writef(__logger_local_skip, INFO, "", v)
   350  }
   351  
   352  func Infof(format string, v ...interface{}) {
   353  	logger := GetLogger("runtime")
   354  	logger.writef(__logger_local_skip, INFO, format, v)
   355  }
   356  
   357  func Debug(v ...interface{}) {
   358  	logger := GetLogger("debug")
   359  	logger.writef(__logger_local_skip, DEBUG, "", v)
   360  }
   361  
   362  func Debugf(format string, v ...interface{}) {
   363  	logger := GetLogger("debug")
   364  	logger.writef(__logger_local_skip, DEBUG, format, v)
   365  }
   366  
   367  func Warn(v ...interface{}) {
   368  	logger := GetLogger("warn")
   369  	logger.writef(__logger_local_skip, WARN, "", v)
   370  }
   371  
   372  func Warnf(format string, v ...interface{}) {
   373  	logger := GetLogger("warn")
   374  	logger.writef(__logger_local_skip, WARN, format, v)
   375  }
   376  
   377  func Error(v ...interface{}) {
   378  	logger := GetLogger("error")
   379  	logger.writef(__logger_local_skip, ERROR, "", v)
   380  }
   381  
   382  func Errorf(format string, v ...interface{}) {
   383  	logger := GetLogger("error")
   384  	logger.writef(__logger_local_skip, ERROR, format, v)
   385  }
   386  
   387  func Fatal(v ...interface{}) {
   388  	logger := GetLogger("error")
   389  	logger.writef(__logger_local_skip, FATAL, "", v)
   390  	os.Exit(-1)
   391  }
   392  
   393  func Fatalf(format string, v ...interface{}) {
   394  	logger := GetLogger("error")
   395  	logger.writef(__logger_local_skip, FATAL, format, v)
   396  	os.Exit(-1)
   397  }