需求:将日志文件统一输出到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
}
日志效果:
分割效果: