123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package log
- import (
- "fmt"
- "os"
- "sync"
- "time"
- "go.uber.org/zap"
- "go.uber.org/zap/buffer"
- "go.uber.org/zap/zapcore"
- "gopkg.in/natefinch/lumberjack.v2"
- )
- // func InitLogger() {
- // writeSyncer := getLogWriter()
- // encoder := getEncoder()
- // core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
- // logger := zap.New(core) //, zap.AddCaller(), zap.AddCallerSkip(1)
- // sugarLogger = logger.Sugar()
- // }
- // var l = new(zapcore.Level)
- // err = l.UnmarshalText([]byte(cfg.Level))
- // if err != nil {
- // return
- // }
- func InitLogger(appName string, isDisplayConsole bool) (*zap.SugaredLogger, *asyncWriter) {
- encoder := getEncoder()
- // test.log记录全量日志
- filePath1 := fmt.Sprintf("%s.log", appName)
- writeSyncer1, lumberJackLogger1 := getLogWriter(filePath1, 1024*1024*1024, 7, 7)
- filePath2 := fmt.Sprintf("%s.err.log", appName)
- writeSyncer2, lumberJackLogger2 := getLogWriter(filePath2, 1024*1024*1024, 7, 7)
- // c1 := zapcore.NewCore(encoder, writeSyncer1, zapcore.DebugLevel)
- // 异步写入器
- asyncWriter := NewAsyncWriter(writeSyncer1)
- asyncWriter.StartRunningAndRotate(func() {
- lumberJackLogger1.Rotate()
- lumberJackLogger2.Rotate()
- })
- asyncCore := zapcore.NewCore(encoder, zapcore.AddSync(asyncWriter), zapcore.InfoLevel)
- // test.err.log记录ERROR级别的日志
- // filePath2 := fmt.Sprintf("%s.err.log", appName)
- // writeSyncer2, lumberJackLogger2 := getLogWriter(filePath2, 1024*1024*1024, 7, 7)
- c2 := zapcore.NewCore(encoder, writeSyncer2, zap.ErrorLevel)
- // 使用NewTee将c1和c2合并到core
- var core zapcore.Core
- if isDisplayConsole {
- consoleWriter := zapcore.AddSync(os.Stdout)
- c3 := zapcore.NewCore(encoder, consoleWriter, zap.DebugLevel)
- core = zapcore.NewTee(asyncCore, c2, c3)
- } else {
- core = zapcore.NewTee(asyncCore, c2)
- }
- logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(2)) //, zap.AddCaller(), zap.AddCallerSkip(1)
- sugarLogger := logger.Sugar()
- return sugarLogger, asyncWriter
- }
- func getEncoder() zapcore.Encoder {
- encoderConfig := zap.NewProductionEncoderConfig()
- encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout(time.DateTime) //ISO8601TimeEncoder //
- encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
- return zapcore.NewJSONEncoder(encoderConfig)
- // NewJSONEncoder
- // NewConsoleEncoder
- }
- // func getLogWriter() zapcore.WriteSyncer {
- // file, _ := os.Create("./test.log")
- // // 利用io.MultiWriter支持文件和终端两个输出目标
- // ws := io.MultiWriter(file, os.Stdout)
- // return zapcore.AddSync(ws)
- // }
- func getLogWriter(filename string, maxSize, maxBackup, maxAge int) (zapcore.WriteSyncer, *lumberjack.Logger) {
- lumberJackLogger := &lumberjack.Logger{
- Filename: filename,
- MaxSize: maxSize,
- MaxBackups: maxBackup,
- MaxAge: maxAge,
- LocalTime: true,
- }
- return zapcore.AddSync(lumberJackLogger), lumberJackLogger
- }
- // 异步写入器
- type asyncWriter struct {
- entryChan chan *buffer.Buffer
- wg sync.WaitGroup
- writer zapcore.WriteSyncer
- pool buffer.Pool
- }
- func NewAsyncWriter(writeSyncer1 zapcore.WriteSyncer) *asyncWriter {
- entryChan := make(chan *buffer.Buffer, 1000) // 缓冲区大小可以根据实际需求调整
- asyncWriter := new(asyncWriter)
- asyncWriter.entryChan = entryChan
- asyncWriter.writer = writeSyncer1
- asyncWriter.pool = buffer.NewPool()
- return asyncWriter
- }
- func (w *asyncWriter) Write(p []byte) (n int, err error) {
- buffer := w.pool.Get()
- buffer.Write(p)
- w.entryChan <- buffer
- return len(p), nil
- }
- func (w *asyncWriter) Sync() error {
- buffer := w.pool.Get()
- w.entryChan <- buffer
- return nil
- // return w.writer.Sync()
- }
- func (w *asyncWriter) StartRunningAndRotate(rotateFunc func()) {
- w.wg.Add(1)
- go func() {
- defer w.wg.Done()
- safeWrite := func(entry *buffer.Buffer) {
- defer func() {
- if err := recover(); err != nil {
- fmt.Fprintln(os.Stderr, "panic writing to log file:", err)
- }
- }()
- var err error
- if entry.Len() == 0 {
- err = w.writer.Sync()
- } else {
- _, err = w.writer.Write(entry.Bytes())
- }
- if err != nil {
- fmt.Fprintln(os.Stderr, "Error writing to log file:", err)
- }
- }
- safeRote := func() {
- defer func() {
- if err := recover(); err != nil {
- fmt.Fprintln(os.Stderr, "panic writing to log file:", err)
- }
- }()
- rotateFunc()
- }
- lastRoteTime := time.Now()
- ticker := time.NewTicker(time.Minute)
- for {
- select {
- case ct := <-ticker.C:
- if ct.YearDay() != lastRoteTime.YearDay() {
- lastRoteTime = ct
- safeRote()
- }
- case entry, ok := <-w.entryChan:
- if !ok {
- return
- }
- safeWrite(entry)
- entry.Free()
- }
- }
- }()
- }
- func testzaplog() {
- log, w := InitLogger("test", false)
- defer func() {
- log.Sync()
- close(w.entryChan)
- w.wg.Wait()
- }()
- log.Info("info")
- log.Error("error")
- log.Debug("debug")
- log.Warn("warn")
- // log.Panic("panic")
- log.Fatal("fatal")
- // time.Sleep(time.Second * 1000)
- // defer sugarLogger.Sync()
- }
|