golang开发:类库篇(一) Zap高性能日志类库的使用

本文介绍如何利用ZAP这一高性能日志库提升日志管理效率,详细讲解配置方法及常见使用场景,适合从PHP转Go的开发者快速上手。

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

为什么要用zap来写日志

原来是写PHP的,一直用的error_log,第一次写Go项目的时候,还真不知道该怎么写日志,后来就按照PHP的写法自己不成规范的捣鼓写。去了新公司之后,发现用的是zap。后来查询 了解了下zap,前同事反应他们很多大公司都在使用zap写日志,GitHub上star 高达7K多,足以说明它受欢迎的程度。

1.zap是Uber开源的日志库;
2.很多大的公司和小的公司都在使用;
3.跟seelog、logrus等类库相比,高性能是它最突出的优势;
我想以上几个原因就已经说明了它的广泛性、稳定性,就值得我们去尝试。

怎么使用zap

我们说下简单的使用案例
首相当然是下载
go get -u go.uber.org/zap
先贴一个我这边常用的zap的配置

zap.Config{
		Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
		Development: true,
		Encoding:    "json",
		EncoderConfig: zapcore.EncoderConfig{
			TimeKey:        "t",
			LevelKey:       "level",
			NameKey:        "log",
			CallerKey:      "caller",
			MessageKey:     "msg",
			StacktraceKey:  "trace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    zapcore.LowercaseLevelEncoder,
			EncodeTime:     时间格式函数,
			EncodeDuration: zapcore.SecondsDurationEncoder,
			EncodeCaller:   zapcore.ShortCallerEncoder,
		},
		OutputPaths:      []string{"/tmp/zap.log"},
		ErrorOutputPaths: []string{"/tmp/zap.log"},
		InitialFields: map[string]interface{}{
			"app": "test",
		},
	}

基本配置的说明

Level:日志级别,跟其他语言是一样的。只不过它需要的类型是AtomicLevel。所以需要使用zap.NewAtomicLevelAt做下如下的转化。

zap.NewAtomicLevelAt(zap.DebugLevel)
zap.DebugLevel
zap.InfoLevel
zap.WarnLevel
zap.ErrorLevel

Development:bool 是否是开发环境。如果是开发模式,对DPanicLevel进行堆栈跟踪
DisableCaller:bool 禁止使用调用函数的文件名和行号来注释日志。默认进行注释日志
DisableStacktrace:bool 是否禁用堆栈跟踪捕获。默认对Warn级别以上和生产error级别以上的进行堆栈跟踪。
Encoding:编码类型,目前两种json 和 console【按照空格隔开】,常用json
EncoderConfig:生成格式的一些配置–TODO 后面我们详细看下EncoderConfig配置各个说明
OutputPaths:[]string 日志写入文件的地址
ErrorOutputPaths:[]string 将系统内的error记录到文件的地址
InitialFields:map[string]interface{} 加入一些初始的字段数据,比如项目名
当然了,如果想控制台输出,OutputPaths和ErrorOutputPaths不能配置为文件地址,而应该改为stdout。

关于config的配置,具体的可以参考文件里面的注释
go.uber.org/zap/config.go
type Config struct

EncoderConfig配置说明

MessageKey:输入信息的key名
LevelKey:输出日志级别的key名
TimeKey:输出时间的key名
NameKey CallerKey StacktraceKey跟以上类似,看名字就知道
LineEnding:每行的分隔符。基本zapcore.DefaultLineEnding 即"\n"
EncodeLevel:基本zapcore.LowercaseLevelEncoder。将日志级别字符串转化为小写
EncodeTime:输出的时间格式
EncodeDuration:一般zapcore.SecondsDurationEncoder,执行消耗的时间转化成浮点型的秒
EncodeCaller:一般zapcore.ShortCallerEncoder,以包/文件:行号 格式化调用堆栈
EncodeName:可选值。

具体EncoderConfig的说明,可以参考文件里面的注释
go.uber.org/zapcore/encoder.go
type EncoderConfig struct

举个栗子

你扯这么多配置说明,谁有时间看这玩意,写个常用的让大家照着用就好了嘛。

package main

import (
	"fmt"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"time"
)

var logger *zap.Logger
func formatEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(fmt.Sprintf("%d%02d%02d_%02d%02d%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()))
}

func FormateLog(args []interface{}) *zap.Logger {
	log := logger.With(ToJsonData(args))
	return log
}

func Debug(msg string, args ...interface{}) {
	FormateLog(args).Sugar().Debugf(msg)
}

func ToJsonData(args []interface{}) zap.Field {
	det := make([]string, 0)
	if len(args) > 0 {
		for _, v := range args {
			det = append(det, fmt.Sprintf("%+v", v))
		}
	}
	zap := zap.Any("detail", det)
	return zap
}

func InitZapLog() {
	cfg := zap.Config{
		Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
		Development: true,
		Encoding:    "json",
		EncoderConfig: zapcore.EncoderConfig{
			TimeKey:        "t",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller",
			MessageKey:     "msg",
			StacktraceKey:  "trace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    zapcore.LowercaseLevelEncoder,
			EncodeTime:     formatEncodeTime,
			EncodeDuration: zapcore.SecondsDurationEncoder,
			EncodeCaller:   zapcore.ShortCallerEncoder,
		},
		OutputPaths:      []string{"/tmp/zap.log"},
		ErrorOutputPaths: []string{"/tmp/zap.log"},
		InitialFields: map[string]interface{}{
			"app": "test",
		},
	}
	var err error
	logger, err = cfg.Build()
	if err != nil {
		panic("log init fail:" + err.Error())
	}
}

func main() {
	InitZapLog()
	defer logger.Sync()
	a := []string{"test","hello","world"}
	Debug("output",a)
}

执行下,就会在日志文件上输入按照我们配置日志格式。

tail -f /tmp/zap.log
{"level":"debug","t":"20190630_044053","caller":"myproject/main.go:21","msg":"output","app":"test","detail":["[test hello world]"]}

然后我们试下控制台输出,修改三个console相关的配置代码
···
OutputPaths: []string{“stdout”},
ErrorOutputPaths: []string{“stdout”},
控制台窗口就会输出
{“level”:“debug”,“t”:“20190630_092533”,“caller”:“myproject/main.go:21”,“msg”:“output”,“app”:“test”,“detail”:["[test hello world]"]}
···

当然了,zap最想的使用和文档,看官网嘛
https://github.com/uber-go/zap
https://godoc.org/go.uber.org/zap

好的,关于 Redis 连接池在 Golang 中的使用,我可以给您提供些相关的类库和示例代码。 首先,Golang 中比较常用的 Redis 客户端有以下几个: 1. go-redis/redis 2. go-redis/cache 3. redigo 这三个客户端都支持连接池的使用,下面分别介绍下它们的连接池使用方法。 1. go-redis/redis go-redis/redis 是 Redis 的 Golang 客户端,它提供了个叫做 "Options" 的结构体,可以用来设置 Redis 连接池的相关选项,例如最大连接数、闲置连接数等等。 示例代码: ```go import ( "github.com/go-redis/redis" ) func main() { options := &redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB PoolSize: 10, } client := redis.NewClient(options) } ``` 在上面的示例代码中,我们创建了个 Redis 连接池,最大连接数为 10。 2. go-redis/cache go-redis/cache 是 go-redis/redis 的个扩展库,它提供了个基于 Redis 的缓存实现。它同样支持 Redis 连接池的使用,可以通过设置 "Options" 结构体中的 "PoolSize" 字段来设置最大连接数。 示例代码: ```go import ( "github.com/go-redis/cache/v8" "github.com/go-redis/redis/v8" ) func main() { options := &redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB PoolSize: 10, } client := redis.NewClient(options) cache := cache.New(&cache.Options{ Redis: client, LocalCache: cache.NewTinyLFU(1000, time.Minute), TTL: time.Hour, }) } ``` 在上面的示例代码中,我们创建了个 Redis 连接池,最大连接数为 10,并且使用 go-redis/cache 库创建了个基于 Redis 的缓存实现。 3. redigo redigo 是 Redis 的 Golang 客户端,它同样支持 Redis 连接池的使用,可以通过设置 "Pool" 结构体中的 "MaxIdle" 和 "MaxActive" 字段来设置最大空闲连接数和最大活跃连接数。 示例代码: ```go import ( "github.com/gomodule/redigo/redis" ) func main() { pool := &redis.Pool{ Dial: func() (redis.Conn, error) { return redis.Dial("tcp", "localhost:6379") }, MaxIdle: 10, MaxActive: 100, } conn := pool.Get() } ``` 在上面的示例代码中,我们创建了个 Redis 连接池,最大空闲连接数为 10,最大活跃连接数为 100。 以上就是三个常用的 Golang Redis 客户端的连接池使用方法,您可以根据实际需求选择适合自己的客户端和连接池设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值