1.简介
zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分割,结合这两个库我们就可以实现以下功能的日志机制:
- 能够将事件记录到文件中,而不是应用程序控制台;
- 日志切割能够根据文件大小、时间或间隔等来切割日志文件;
- 支持不同的日志级别,例如 DEBUG , INFO , WARN , ERROR 等;
- 能够打印基本信息,如调用文件、函数名和行号,日志时间等;
2.下载安装使用
使用如下命令进行安装
go get -u go.uber.org/zap
或
go get github.com/uber-go/zap
注意:导入的时候得这样导入
import(
"go.uber.org/zap"
)
3.zap looger使用
zap 提供了两种类型的日志记录器—和 Logger 和 Sugared Logger 。之间的区别是:
- 在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
- 在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快 4-10 倍,并且支持结构化和 printf 风格的日志记录。
一般场景使用 Sugared Logger 就足够了
3.1 Logger
- 创建logger(zap提供了三种方式来创建logger)(zap.NewProduction()/zap.NewDevelopment或za)
- 通过创建的logger调用INFO,ERROR等进行日志输出
3.1.1NewExample
代码示例:
package main
import "go.uber.org/zap"
func main() {
log := zap.NewExample()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("error message")
log.Panic("panic message")
}
输出结果:
{"level":"debug","msg":"this is debug message"}
{"level":"info","msg":"this is info message"}
{"level":"info","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","msg":"this is warn message"}
{"level":"error","msg":"error message"}
{"level":"panic","msg":"panic message"}
panic: panic message
3.1.2 NewDevelopment
代码示例:
package main
import "go.uber.org/zap"
func main() {
log, _ := zap.NewDevelopment()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("error message")
log.Panic("panic message")
}
输出结果:
2021-12-31T14:23:54.919+0800 DEBUG jwtGoTest/logT.go:7 this is debug message
2021-12-31T14:23:54.928+0800 INFO jwtGoTest/logT.go:8 this is info message
2021-12-31T14:23:54.929+0800 INFO jwtGoTest/logT.go:9 this is info message with fileds {"age": 24, "agender": "man"}
2021-12-31T14:23:54.929+0800 WARN jwtGoTest/logT.go:11 this is warn message
main.main
E:/Test/Test/myGitTest/gittest/jwtGoTest/logT.go:11
runtime.main
C:/Program Files/Go/src/runtime/proc.go:255
2021-12-31T14:23:54.929+0800 ERROR jwtGoTest/logT.go:12 error message
main.main
E:/Test/Test/myGitTest/gittest/jwtGoTest/logT.go:12
runtime.main
C:/Program Files/Go/src/runtime/proc.go:255
2021-12-31T14:23:54.929+0800 PANIC jwtGoTest/logT.go:13 panic message
main.main
E:/Test/Test/myGitTest/gittest/jwtGoTest/logT.go:13
runtime.main
C:/Program Files/Go/src/runtime/proc.go:255
panic: panic message
3.1.3 NewProduction
代码示例:
package main
import "go.uber.org/zap"
func main() {
log, _ := zap.NewProduction()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("error message")
log.Panic("panic message")
}
输出结果:
{"level":"info","ts":1640931968.8371582,"caller":"jwtGoTest/logT.go:8","msg":"this is info message"}
{"level":"info","ts":1640931968.8371582,"caller":"jwtGoTest/logT.go:9","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","ts":1640931968.8377013,"caller":"jwtGoTest/logT.go:11","msg":"this is warn message"}
{"level":"error","ts":1640931968.8377013,"caller":"jwtGoTest/logT.go:12","msg":"error message","stacktrace":"main.main\n\tE:/Test/Test/myGitTest/gittest/jwtGoTest/logT.go:12\nruntime.main\n\tC:/Program Files/Go/src/runtime/proc.go:255"}
{"level":"panic","ts":1640931968.8377013,"caller":"jwtGoTest/logT.go:13","msg":"panic message","stacktrace":"main.main\n\tE:/Test/Test/myGitTest/gittest/jwtGoTest/logT.go:13\nruntime.main\n\tC:/Program Files/Go/src/runtime/proc.go:255"}
panic: panic message
总结
- Example和Production都是以json形式输出,Develpoment使用行的形式输出
- Develpoment打印包/文件/行,以大写形式打印级别名称,以毫秒为单位打印时间戳、
- 调试级别不记录,始终将调用者添加到文件中,以时间戳格式打印日期,以小写形式打印级别名称
3.2 Sugared Logger
使用:
通过主logger的Sugar()方法来获取一个SugaredLogger
示例:
package main
import "go.uber.org/zap"
func main() {
log, _ := zap.NewDevelopment()
sugarLog := log.Sugar()
sugarLog.Debugf("debug message age is %d, agender is %s", 19, "man")
sugarLog.Info("Info() uses sprint")
sugarLog.Infof("Infof() uses %s", "sprintf")
sugarLog.Infow("Infow() allows tags", "name", "Legolas", "type", 1)
}
输出结果:
2021-12-31T14:47:43.705+0800 DEBUG jwtGoTest/logT.go:8 debug message age is 19, agender is man
2021-12-31T14:47:43.714+0800 INFO jwtGoTest/logT.go:9 Info() uses sprint
2021-12-31T14:47:43.714+0800 INFO jwtGoTest/logT.go:10 Infof() uses sprintf
2021-12-31T14:47:43.714+0800 INFO jwtGoTest/logT.go:11 Infow() allows tags {"name": "Legolas", "type": 1}
如果需要,可以调用 Desugar() 方法从 sugar logger 切回到标准记录器
4.将日志写入文件
要将日志写入文件,就必须用zap.New()方法来传递配置,而不能像前面那样用预置方法创建logger
func zap.New(core zapcore.Core, options ...zap.Option) *zap.Logger
zapcore需要三个配置----Encoder,WriteSyncer,LogLevel
Encoder:编码器(如何写入日志)
encoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
WriterSyncer:指定日志将写到哪去。使用zapcore.Addsync()函数将打开的文件句柄传进去
file, _ := os.Create("./test.log")
writeSyncer := zapcore.AddSync(file)
或输出到控制台
consoleSyncer := zapcore.AddSync(os.Stdout)
LogLevel:哪种级别的日志将被写入
代码示例:
package main
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
encoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
file, _ := os.Create("./test.log")
writeSync := zapcore.AddSync(file)
core := zapcore.NewCore(encoder, writeSync, zap.DebugLevel)
sugarLogger := zap.New(core, zap.AddCaller()).Sugar()
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")
}
输出日志文件:
2021-12-31T15:05:14.810+0800 INFO jwtGoTest/logT.go:16 this is info message
2021-12-31T15:05:14.818+0800 INFO jwtGoTest/logT.go:17 this is aaa, 1234
2021-12-31T15:05:14.818+0800 ERROR jwtGoTest/logT.go:18 this is error message
2021-12-31T15:05:14.818+0800 INFO jwtGoTest/logT.go:19 this is info message
5.使用lumberjack进行日志切割归档
zap本身不支持切割归档日志文件,为了添加日志切割归档功能,使用lumberjack库来完成
5.1 安装lumberjak
go get github.com/natefinch/lumberjack
5.2 使用
要在zap中加入lumberjack支持,需要修改wrierSync代码
lumberJackLogger := &lumberjack.Logger{
Filename: "./lumber.log",
MaxSize: 10,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
}
writerSyncer := zapcore.AddSync(lumberJackLogger)
lumberjack logger属性:
- Filename:日志文件的位置
- Maxsize:在进行切割之前,日志文件的最大大小
- MaxBackups:保留旧文件的最大个数
- MaxAges:保留旧文件的最大天数
- Compress:是否压缩/归档旧文件
代码示例:
package main
import (
"os"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
encoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
// file, _ := os.Create("./test.log")
lumberJackLogger := &lumberjack.Logger{
Filename: "./lumber.log",
MaxSize: 10,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
}
writerSyncer := zapcore.AddSync(lumberJackLogger)
consoleSyncer := zapcore.AddSync(os.Stdout)
core := zapcore.NewTee(
zapcore.NewCore(encoder, writerSyncer, zapcore.DebugLevel),
zapcore.NewCore(encoder, consoleSyncer, zapcore.DebugLevel),
)
log := zap.New(core, zap.AddCaller())
sugarLogger := log.Sugar()
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")
}
日志文件输出结果:
2021-12-31T15:12:29.885+0800 INFO gittest/logTest.go:29 this is info message
2021-12-31T15:12:29.899+0800 INFO gittest/logTest.go:30 this is aaa, 1234
2021-12-31T15:12:29.899+0800 ERROR gittest/logTest.go:31 this is error message
2021-12-31T15:12:29.899+0800 INFO gittest/logTest.go:32 this is info message
评论区