go 日志 异步+集中写+滚动 实现

异步和集中写采用 time.NewTicker + chan 的方式。
滚动部分采用第三方库(gopkg.in/natefinch/lumberjack.v2)。
对 slog 实现了异步+集中写+滚动。

核心代码在下方

package asyncwrite

import (
    "gopkg.in/natefinch/lumberjack.v2"
    "time"
)

type AsyncW struct {
    io       *lumberjack.Logger
    dataChan chan *[]byte
    done     chan bool
}

func AsyncLumberjack(io *lumberjack.Logger) *AsyncW {
    r := AsyncW{
        io:       io,
        dataChan: make(chan *[]byte, 1024),
        done:     make(chan bool),
    }
    go func() {
        ticker := time.NewTicker(time.Millisecond * 333) // 每0.333秒执行一次批量写入
        defer ticker.Stop()
        var data []byte
        for {
            select {
            case val := <-r.dataChan:
                data = append(data, *val...)
                if len(data) >= 100 {
                    r.io.Write(data)
                    data = []byte{}
                }
            case <-ticker.C:
                if len(data) > 0 {
                    r.io.Write(data)
                    data = []byte{}
                }
            case <-r.done:
                if len(data) > 0 {
                    r.io.Write(data)
                    data = []byte{}
                }
                return
            }
        }
    }()
    return &r
}

func (itself *AsyncW) Write(p []byte) (n int, err error) {
    data := make([]byte, len(p))
    copy(data, p)
    itself.dataChan <- &data
    return 0, nil
}

func (itself *AsyncW) Stop() {
    itself.done <- true
    itself.io.Close()
    close(itself.dataChan)
    close(itself.done)
}
func init() {
    once.Do(func() {
       var logOut io.Writer
  logOut = os.Stdout
  switch logType {
       default:
          slog.Info("Unknown Log Output Type")
       case LogTypeStdout:
       case LogTypeFile:
          if rolling {
             logOut = getAsyncFileIoRolling()
          } else {
             logOut = getFileIo()
          }
       }
       logLevel := slog.LevelInfo
  if debug {
          logLevel = slog.LevelDebug
  }
       slog.SetDefault(slog.New(slog.NewJSONHandler(logOut, &slog.HandlerOptions{
          AddSource:   true,
          ReplaceAttr: replace,
          Level:       logLevel,
       })))
    })
}

func getAsyncFileIoRolling() *asyncwrite.AsyncW {
    aw = asyncwrite.AsyncLumberjack(&lumberjack.Logger{
        Filename:   logPath,
        MaxSize:    maxSize,    // megabytes
        MaxBackups: maxBackUps, // maxBackUps
        MaxAge:     maxAge,     //days
        LocalTime:  true,
        Compress:   false, // disabled by default
    })
    return aw
}

func Shutdown() {
    aw.Stop()
    slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
       AddSource:   true,
       ReplaceAttr: replace,
    })))
    slog.Info("logging 👋")
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
文章
51
粉丝
16
喜欢
57
收藏
43
排名:519
访问:1.6 万
私信
所有博文
社区赞助商