Go 第三方库之 uber-go/zap(记录日志到文件、支持自动分割日志、支持日志级别、打印调用文件、函数和行号)

本文介绍了Uber的Go日志库zap的使用,包括Logger和SugaredLogger的创建及不同模式的输出。同时,讲解了如何利用lumberjack进行日志文件的切割和归档,确保日志管理的有效性和高效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.简介

2.下载安装使用

注意:导入的时候得这样导入

3.zap looger使用

3.1 Logger

3.1.1NewExample

 3.1.2 NewDevelopment

 3.1.3 NewProduction

 总结

3.2 Sugared Logger

4.将日志写入文件

5.使用lumberjack进行日志切割归档

5.1 安装lumberjak 

5.2 使用


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

<think>好的,用户想了解Go语言中比较好的日志库。首先,我需要回忆一下常见的Go日志库,然后整理它们的特点适用场景。 首先,标准库的log包是基础,适合简单需求,但功能有限。用户可能需要更强大的库,比如日志分级、结构化日志或者异步处理。接下来,流行的第三方库包括: 1. ZapUber):高性能,适合高并发场景,结构化日志,但不太易用。 2. Logrus:功能丰富,插件化,适合需要灵活扩展的用户,不过现在维护状态可能有问题。 3. Zerolog:同样高性能,API设计简洁,支持结构化日志。 4. Glog:分级别日志,适合需要细粒度控制的场景,但Google维护可能更新不频繁。 5. Lumberjack:日志轮转,常与其他库配合使用。 6. slog(标准库新加入):Go 1.21引入,结构化日志,未来可能成为主流。 用户可能需要根据项目需求选择,比如是否需要高性能、是否想要结构化日志、是否需要与现有系统集成等。还要考虑库的维护状态社区支持。此外,可以建议组合使用,比如Zap+Lumberjack实现高性能日志轮转。最后,提醒用户如果是新项目,可以考虑slog,因为它可能成为标准。</think>在 Go 语言生态中,以下几个日志库因其性能、灵活性易用性广受好评。我将从基础到进阶分层说明: --- ### 一、标准库 `log` ```go import "log" ``` - **特点**:轻量级、无依赖、无日志分级 - **适用场景**:小型项目或快速原型开发 - **示例**: ```go log.Println("标准库日志示例") // 输出格式:2023/10/01 10:00:00 标准库日志示例 ``` --- ### 二、主流第三方库 #### 1. **Zap** ([github.com/uber-go/zap](https://github.com/uber-go/zap)) $$ \text{性能基准:比标准库快 } 4\text{-}10\text{ 倍} $$ - **核心优势**: - 高性能(零内存分配设计) - 结构化日志输出(JSON 格式) - 支持日志分级(Debug/Info/Warn/Error) - **示例**: ```go logger, _ := zap.NewProduction() logger.Info("用户登录成功", zap.String("username", "john"), zap.Int("attempt", 3)) // 输出:{"level":"info","ts":1696132800,"msg":"用户登录成功","username":"john","attempt":3} ``` #### 2. **Logrus** ([github.com/sirupsen/logrus](https://github.com/sirupsen/logrus)) $$ \text{设计特点:插件化架构} $$ - **核心优势**: - 丰富的钩子机制(可扩展邮件、数据库等输出方式) - 支持文本/JSON 格式切换 - 社区生态完善(有 Elasticsearch、Graylog 等插件) - **示例**: ```go logrus.SetFormatter(&logrus.JSONFormatter{}) logrus.WithFields(logrus.Fields{ "ip": "192.168.1.1", "status": 200, }).Warn("API响应异常") ``` #### 3. **Zerolog** ([github.com/rs/zerolog](https://github.com/rs/zerolog)) $$ \text{API 设计:链式调用 } \rightarrow \text{Logger.Info().Str("key","value").Msg("")} $$ - **核心优势**: - 类似 Zap 的高性能 - 更符合 Go 习惯的 API 设计 - 支持上下文传递(With() 方法) - **示例**: ```go zerolog.TimeFieldFormat = time.RFC3339 log := zerolog.New(os.Stdout).With().Timestamp().Logger() log.Info().Str("path", "/api/v1").Int("count", 42).Msg("请求统计") ``` --- ### 三、特殊场景方案 #### 1. **分布式系统** - **推荐组合**:Zap + Lumberjack - Zap 处理日志生成 - Lumberjack 实现日志轮转(按大小/时间分割) ```go import "gopkg.in/natefinch/lumberjack.v2" writer := &lumberjack.Logger{ Filename: "/var/log/app.log", MaxSize: 100, // MB MaxBackups: 5, } logger := zap.New(zapcore.NewCore(..., writer)) ``` #### 2. **云原生场景** - **推荐方案**:使用 slog(Go 1.21+ 标准库) ```go import "log/slog" logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)) logger.Info("新标准库日志", "k8s_pod", "app-123x") ``` --- ### 四、选型建议 1. **性能敏感型系统**:优先选择 Zap 或 Zerolog 2. **需要深度定制**:Logrus + 插件生态 3. **长期维护项目**:关注 slog 标准库的发展 4. **微服务架构**:建议统一日志格式(如 JSON),配合 EFK 等日志系统 实际选择时需结合以下维度评估: $$ \text{评估维度} = \text{性能} \times \text{可维护性} \times \text{团队熟悉度} \times \text{扩展需求} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值