日志库Zap
1、介绍
Zap提供了两种类型的日志记录器—Sugared Logger和Logger。
在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快4-10倍,并且支持结构化和printf风格的日志记录。
在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
2、logger的使用-使用默认方法
通过调用zap.NewProduction()/zap.NewDevelopment()或者zap.Example()创建一个Logger。它们的区别在于记录的信息不同。production logger默认记录调用函数信息、日期和时间等。
var logger *zap.Logger
func main() {
InitLogger()
defer logger.Sync()
simpleHttpGet("www.google.com")
simpleHttpGet("http://www.google.com")
}
func InitLogger() {
logger, _ = zap.NewProduction()
}
func simpleHttpGet(url string) {
resp, err := http.Get(url)
if err != nil {
logger.Error(
"Error fetching url..",
zap.String("url", url),
zap.Error(err))
} else {
logger.Info("Success..",
zap.String("statusCode", resp.Status),
zap.String("url", url))
resp.Body.Close()
}
}
3、Sugared Logger的使用-使用默认方法
与logger的区别是,SugaredLogger以printf格式记录语句。
var sugarLogger *zap.SugaredLogger
func main() {
InitLogger()
defer sugarLogger.Sync()
simpleHttpGet("www.google.com")
simpleHttpGet("http://www.google.com")
}
func InitLogger() {
logger, _ := zap.NewProduction()
sugarLogger = logger.Sugar()
}
func simpleHttpGet(url string) {
sugarLogger.Debugf("Trying to hit GET request for %s", url)
resp, err := http.Get(url)
if err != nil {
sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, err)
} else {
sugarLogger.Infof("Success! statusCode = %s for URL %s", resp.Status, url)
resp.Body.Close()
}
}
4、自定义logger的输出
1)将日志写入文件而不是终端
只需要修改上面代码的InitLogger()函数:
func InitLogger() {
writeSyncer := getLogWriter()
encoder := getEncoder()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
logger := zap.New(core)
sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
}
func getLogWriter() zapcore.WriteSyncer {
file, _ := os.Create("./test.log")
return zapcore.AddSync(file)
}
2)将JSON Encoder更改为普通的Log Encoder
将NewJSONEncoder()更改为NewConsoleEncoder()。
3)更改时间编码并添加调用者详细信息
修改时间编码器:
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
return zapcore.NewConsoleEncoder(encoderConfig)
}
4)添加将调用函数信息记录到日志中的功能,在zap.New(..)函数中添加一个Option:
logger := zap.New(core, zap.AddCaller())
5)AddCallerSkip:
logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
6)将日志输出到多个位置:
func getLogWriter() zapcore.WriteSyncer {
file, _ := os.Create("./test.log")
// 利用io.MultiWriter支持文件和终端两个输出目标
ws := io.MultiWriter(file, os.Stdout)
return zapcore.AddSync(ws)
}
7)将err日志单独输出到文件:
func InitLogger() {
encoder := getEncoder()
// test.log记录全量日志
logF, _ := os.Create("./test.log")
c1 := zapcore.NewCore(encoder, zapcore.AddSync(logF), zapcore.DebugLevel)
// test.err.log记录ERROR级别的日志
errF, _ := os.Create("./test.err.log")
c2 := zapcore.NewCore(encoder, zapcore.AddSync(errF), zap.ErrorLevel)
// 使用NewTee将c1和c2合并到core
core := zapcore.NewTee(c1, c2)
logger = zap.New(core, zap.AddCaller())
}
完整代码:
package main
import (
"go.uber.org/zap/zapcore"
"io"
"net/http"
"os"
)
import (
"go.uber.org/zap"
)
var sugarLogger *zap.SugaredLogger
func main() {
InitLogger()
defer sugarLogger.Sync()
simpleHttpGet("www.google.com")
simpleHttpGet("http://www.google.com")
}
func InitLogger() {
writeSyncer := getLogWriter()
encoder := getEncoder()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))
sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
file, _ := os.Create("./test.log")
// 利用io.MultiWriter支持文件和终端两个输出目标
ws := io.MultiWriter(file, os.Stdout)
return zapcore.AddSync(ws)
}
func simpleHttpGet(url string) {
resp, err := http.Get(url)
if err != nil {
sugarLogger.Error(
"Error fetching url..",
zap.String("url", url),
zap.Error(err))
} else {
sugarLogger.Info("Success..",
zap.String("statusCode", resp.Status),
zap.String("url", url))
resp.Body.Close()
}
}
参考:在Go语言项目中使用Zap日志库 | 李文周的博客 (liwenzhou.com)

浙公网安备 33010602011771号