Go使用zap+ratatelogs實現日誌文件輸出與分割

需求:將日誌文件統一輸出到D:/bian/logs/dspcollect.log文件中,go程序重啓後日志累加寫入文件,每24小時分割一次日誌,保存30天內的日誌文件。

對比了幾款go 日誌框架:zap , logrus ,seelog等。其中logrus是目前Github上star數量最多的日誌庫,能強大,性能高效,而且具有高度靈活性,提供了自定義插件的功能。zap是Uber推出的一個快速、結構化的分級日誌庫.具有強大的ad-hoc分析功能,並且具有靈活的儀表盤。seelog提供了靈活的異步調度、格式化和過濾功能。

關於logrus的使用可以參考這篇博客:https://mojotv.cn/2018/12/27/golang-logrus-tutorial

本文主要使用zap,涉及到的go包如下:

github.com/lestrrat/go-file-rotatelogs  //由於zap,logrus都不支持日誌分割,所有依賴rotate進行日誌分割

go.uber.org/zap

package main

import (
	"github.com/lestrrat/go-file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"io"
	"time"
)

var Logger *zap.SugaredLogger

func main() {
	Logger.Error("error....")
	Logger.Info("info....")
	Logger.Warn("warn....")

}

func init() {
	initLogger()
}

func initLogger() {
    logPath := "D:/bian/logs/dspcollect.log"
	if !Exists(logPath) {
		file, err := os.Create(logPath)
		defer file.Close()
		if err != nil{
			fmt.Println("mkdir logPath err!")
			return
		}
	}
	encoder := initEncoder()

	// 想要將日常文件區分開來,可以實現多個日誌等級接口
	/*infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl < zapcore.WarnLevel
	})*/
	debugLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.DebugLevel
	})

	// 獲取 info、warn日誌文件的io.Writer
	//infoIoWriter := getWriter("D:/bian/logs/dspcollect.log")
	warnIoWriter := getWriter("D:/bian/logs/dspcollect.log")

	// 創建Logger
	core := zapcore.NewTee(
		//zapcore.NewCore(encoder, zapcore.AddSync(infoIoWriter), infoLevel),
		zapcore.NewCore(encoder, zapcore.AddSync(warnIoWriter), debugLevel),
	)
	logger := zap.New(core, zap.AddCaller()) // 需要傳入 zap.AddCaller() 纔會顯示打日誌點的文件名和行數
	Logger = logger.Sugar()
}

//初始化Encoder
func initEncoder() zapcore.Encoder {
	return zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
		MessageKey:  "msg",
		LevelKey:    "level",
		TimeKey:     "time",
		CallerKey:   "file",
		EncodeLevel: zapcore.CapitalLevelEncoder, //基本zapcore.LowercaseLevelEncoder。將日誌級別字符串轉化爲小寫
		EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.Format("2006-01-02 15:04:05"))
		},
		EncodeCaller: zapcore.ShortCallerEncoder, //一般zapcore.ShortCallerEncoder,以包/文件:行號 格式化調用堆棧
		EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { //一般zapcore.SecondsDurationEncoder,執行消耗的時間轉化成浮點型的秒
			enc.AppendInt64(int64(d) / 1000000)
		},
	})
}

//日誌文件切割
func getWriter(filename string) io.Writer {
	// 保存30天內的日誌,每24小時(整點)分割一次日誌
	hook, err := rotatelogs.New(
		filename+".%Y%m%d",
		rotatelogs.WithLinkName(filename),
		rotatelogs.WithMaxAge(time.Hour*24*30),
		rotatelogs.WithRotationTime(time.Hour*24),
	)

	if err != nil {
		panic(err)
	}
	return hook
}

//查看文件/文件夾是否存在
func Exists(path string) bool {
	_, err := os.Stat(path)
	if err != nil{
		if os.IsExist(err){
			return true
		}
		return false
	}
	return true
}

日誌效果:

分割效果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章