Zap日志库指南
Zap是由Uber开发的高性能Go日志库,特别适合后端服务。
入门:
第一目:为什么要选择Zap?
在Go语言的日志库中,流行的有 zap、logrus...甚至还有Go自带的原生的log。
zap:极致性能(低延迟、低内存占用)、支持多种日志级别、偏底层、Uber官方维护并持续更新
Logrus:灵活易用、支持多种日志级别、高层封装支持全局调用、基本停滞更新
原生log包:简单易用的基础工具、学习成本低。高并发场景下性能也较低(文末有解释)
第二目:安装Zap
go get -u go.uber.org/zap
第三目:go语言简答的启动
package mainimport (\"go.uber.org/zap\"\"time\")func main() {// 创建生产环境使用的Logger(JSON格式)logger, _ := zap.NewProduction()defer logger.Sync() // 刷新缓冲区 // Sync的作用,就是强制输出还在缓存区的内容// 记录不同级别的日志logger.Info(\"服务启动\",zap.String(\"service\", \"user-api\"),zap.Time(\"start_time\", time.Now()),) // 打印logger.Warn(\"数据库连接缓慢\",zap.Duration(\"duration\", 150*time.Millisecond),)logger.Error(\"无法连接Redis\",zap.String(\"host\", \"redis:6379\"),zap.Error(err), // 假设有err变量)}
输出示例
{\"level\":\"info\",\"ts\":1690000000.1234567,\"msg\":\"服务启动\",\"service\":\"user-api\",\"start_time\":\"2023-07-22T10:00:00Z\"}{\"level\":\"warn\",\"ts\":1690000001.2345678,\"msg\":\"数据库连接缓慢\",\"duration\":0.15}{\"level\":\"error\",\"ts\":1690000002.3456789,\"msg\":\"无法连接Redis\",\"host\":\"redis:6379\",\"error\":\"connection refused\"}
进阶:
第一目:自定义Logger配置:
func main() {// 创建自定义配置config := zap.NewProductionConfig()// 修改配置config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) // 设置日志级别config.OutputPaths = []string{\"stdout\", \"logs/app.log\"} // 输出到控制台和文件config.EncoderConfig.TimeKey = \"timestamp\" // 自定义时间字段名config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // ISO时间格式// 构建Loggerlogger, err := config.Build()if err != nil {panic(err)}defer logger.Sync()// 使用Loggerlogger.Debug(\"调试信息\", zap.String(\"module\", \"authentication\"))}
第二目:创建开发环境Logger(易读格式)
func main() {// 开发环境使用更易读的控制台输出logger, _ := zap.NewDevelopment()defer logger.Sync()logger.Info(\"开发模式日志\",zap.String(\"url\", \"/api/users\"),zap.Int(\"status\", 200),)}// 2023-07-22T10:00:00.123ZINFO开发模式日志{\"url\": \"/api/users\", \"status\": 200}
第三目:使用Sugar Logger(简化语法)
Sugar是zap提供的一种更灵活,更易用的日志记录接口。
格式化字符串与结构字段,语法更接近传统日志库,缺点就是性能略低。
func main() {logger, _ := zap.NewProduction()defer logger.Sync()// 创建Sugar Loggersugar := logger.Sugar()// 简化语法(性能略低于标准Logger)sugar.Infow(\"用户注册成功\",\"user_id\", 12345,\"email\", \"user@example.com\",\"registration_time\", time.Now(),)// 格式化日志sugar.Infof(\"新请求: %s %s\", \"GET\", \"/api/users\")}{\"level\":\"info\",\"ts\":1753187495.5488393,\"caller\":\"zap/main.go:92\",\"msg\":\"用户注册成功\",\"user_id\":12345,\"email\":\"user@example.com\",\"registration_time\":1753187495.5488393}
第四目:封装Logger(推荐)
对zap,封装成Init与Sync两个函数,需要时,调用即可。
// logger/logger.gopackage loggerimport (\"go.uber.org/zap\")var Log *zap.Loggerfunc Init(debug bool) {var err errorif debug {Log, err = zap.NewDevelopment()} else {Log, err = zap.NewProduction()}if err != nil {panic(err)}// 添加全局字段(服务名、版本等)Log = Log.With(zap.String(\"service\", \"user-service\"),zap.String(\"version\", \"1.0.0\"),)}func Sync() {_ = Log.Sync()}
第五目:在项目中如何调用
// main.gopackage mainimport (\"your-project/logger\"\"net/http\")func main() {// 初始化Loggerlogger.Init(true) // 开发模式defer logger.Sync()http.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {logger.Log.Info(\"处理请求\",zap.String(\"path\", r.URL.Path),zap.String(\"method\", r.Method),)w.Write([]byte(\"Hello, World!\"))})logger.Log.Info(\"启动HTTP服务\", zap.String(\"port\", \"8080\"))http.ListenAndServe(\":8080\", nil)}
第六目:日志切割
一、安装Lumberjack:
go get gopkg.in/natefinch/lumberjack.v2
二、配置日志切割
import (\"go.uber.org/zap\"\"go.uber.org/zap/zapcore\"\"gopkg.in/natefinch/lumberjack.v2\")func getLogWriter() zapcore.WriteSyncer {lumberJackLogger := &lumberjack.Logger{Filename: \"logs/app.log\", // 日志文件路径MaxSize: 100, // 单个文件最大大小(MB)MaxBackups: 5, // 保留旧文件的最大个数MaxAge: 30, // 保留旧文件的最大天数Compress: true, // 是否压缩/归档旧文件}return zapcore.AddSync(lumberJackLogger)}func main() {encoder := getEncoder()writer := getLogWriter()core := zapcore.NewCore(encoder, writer, zapcore.DebugLevel)logger := zap.New(core)defer logger.Sync()// 使用logger...}func getEncoder() zapcore.Encoder {encoderConfig := zap.NewProductionEncoderConfig()encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderreturn zapcore.NewJSONEncoder(encoderConfig)}
项目中,常用的就这些。
后续会补充。
日志级别的合理使用:
-
DEBUG:调试信息
-
INFO:重要流程信息
-
WARN:预期之外但可恢复的情况
-
ERROR:需要立即关注的错误
-
DPANIC/ PANIC/FATAL:严重错误(谨慎使用)
注:
- Zap 使用 无反射设计(通过预定义字段类型避免运行时反射),且 内存预分配 减少 GC 压力。
- 原生 log 依赖
fmt.Sprintf()
进行字符串拼接,在高并发下性能损耗显著。