golang扩展 日志库ZAP[uber-go zap]切割 natefinch-lumberjack
1. 使用 lumberjack 进行日志切割归档
因为 zap 本身不支持切割归档日志文件,为了添加日志切割归档功能,我们将使用第三方库 lumberjack 来实现。
福利彩蛋:没有好玩的 API 接口?上百款免费接口等你来,免费 API,免费 API 大全
1.1 安装 lumberjack
执行下面的命令安装 lumberjack
go
go get -uv github.com/natefinch/lumberjack
1.2 将 lumberjack 加入 zap logger
要在 zap 中加入 lumberjack 支持,我们需要修改 WriteSyncer 代码。我们将按照下面的代码修改 getLogWriter() 函数:
go
func getLogWriter() zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: "./test.log",
MaxSize: 10,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
}
return zapcore.AddSync(lumberJackLogger)
}
Lumberjack Logger 采用以下属性作为输入:
- Filename : 日志文件的位置;
- MaxSize :在进行切割之前,日志文件的最大大小(以MB为单位);
- MaxBackups :保留旧文件的最大个数;
- MaxAges :保留旧文件的最大天数;
- Compress :是否压缩/归档旧文件;
go
// 完整代码:
package main
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var sugarLogger *zap.SugaredLogger
func InitLogger() {
encoder := getEncoder()
writeSyncer := getLogWriter()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
// zap.AddCaller() 添加将调用函数信息记录到日志中的功能。
logger := zap.New(core, zap.AddCaller())
sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 修改时间编码器
// 在日志文件中使用大写字母记录日志级别
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
// NewConsoleEncoder 打印更符合人们观察的方式
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: "./test.log",
MaxSize: 10,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
}
return zapcore.AddSync(lumberJackLogger)
}
func main() {
InitLogger()
sugarLogger.Info("this is info message")
sugarLogger.Infof("this is %s, %d", "aaa", 1234)
sugarLogger.Error("this is error message")
sugarLogger.Info("this is info message")
}
2. Log 第三方库 uber-zap 使用
go
package main
import (
"time"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var logger *zap.Logger
// logpath 日志文件路径
// loglevel 日志级别
func InitLogger(logpath string, loglevel string) {
// 日志分割
hook := lumberjack.Logger{
Filename: logpath, // 日志文件路径,默认 os.TempDir()
MaxSize: 10, // 每个日志文件保存10M,默认 100M
MaxBackups: 30, // 保留30个备份,默认不限
MaxAge: 7, // 保留7天,默认不限
Compress: true, // 是否压缩,默认不压缩
}
write := zapcore.AddSync(&hook)
// 设置日志级别
// debug 可以打印出 info debug warn
// info 级别可以打印 warn info
// warn 只能打印 warn
// debug->info->warn->error
var level zapcore.Level
switch loglevel {
case "debug":
level = zap.DebugLevel
case "info":
level = zap.InfoLevel
case "error":
level = zap.ErrorLevel
default:
level = zap.InfoLevel
}
encoderConfig := zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "linenum",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
EncodeTime: zapcore.ISO8601TimeEncoder, // ISO8601 UTC 时间格式
EncodeDuration: zapcore.SecondsDurationEncoder, //
EncodeCaller: zapcore.FullCallerEncoder, // 全路径编码器
EncodeName: zapcore.FullNameEncoder,
}
// 设置日志级别
atomicLevel := zap.NewAtomicLevel()
atomicLevel.SetLevel(level)
core := zapcore.NewCore(
// zapcore.NewConsoleEncoder(encoderConfig),
zapcore.NewJSONEncoder(encoderConfig),
// zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&write)), // 打印到控制台和文件
write,
level,
)
// 开启开发模式,堆栈跟踪
caller := zap.AddCaller()
// 开启文件及行号
development := zap.Development()
// 设置初始化字段,如:添加一个服务器名称
filed := zap.Fields(zap.String("serviceName", "serviceName"))
// 构造日志
logger = zap.New(core, caller, development, filed)
logger.Info("DefaultLogger init success")
}
func main() {
// 历史记录日志名字为:all.log,服务重新启动,日志会追加,不会删除
InitLogger("./all.log", "debug")
// 强结构形式
logger.Info("test",
zap.String("string", "string"),
zap.Int("int", 3),
zap.Duration("time", time.Second),
)
// 必须 key-value 结构形式 性能下降一点
logger.Sugar().Infow("test-",
"string", "string",
"int", 1,
"time", time.Second,
)
}
从例子看出:
- 它同时提供了结构化日志记录和 printf 风格的日志记录
- 先初始化 lumberjack 后初始化 zap