golang中使用zap日志库
1. 快速使用
package main
import (
"go.uber.org/zap"
"time"
)
func main() {
// 1. sugar日志
//logger, _ := zap.NewProduction()
//logger, _ := zap.NewDevelopment()
//defer logger.Sync() // 刷新缓冲区,存盘
//sugar := logger.Sugar()
//sugar.Infow("first logger",
// 结构化上下文为松散类型的键值对。
// "url", "https://sankuanedu.com",
// "name", "三宽教育",
//)
//sugar.Errorf("url: %s", "http://www.mayanan.cn")
// 测试环境
// 输出:2022-01-17T15:36:40.833+0800 INFO zapTest/main.go:11 first logger {"url": "https://sankuanedu.com", "name": "三宽教育"}
// 输出:2022-01-17T15:51:18.915+0800 ERROR zapTest/main.go:16 url: http://www.mayanan.cn
//main.main
// C:/Users/mayanan/Desktop/pro_go/zapTest/main.go:16
//runtime.main
// D:/go_1_17_1/src/runtime/proc.go:255
// 正式环境
// {"level":"info","ts":1642405507.5565631,"caller":"zapTest/main.go:11","msg":"first logger","url":"https://sankuanedu.com","name":"三宽教育"}
// {"level":"error","ts":1642405507.5565631,"caller":"zapTest/main.go:16","msg":"url: http://www.mayanan.cn","stacktrace":"main.main\n\tC:/Users/mayanan/Desktop/pro_go/zapTest/main.go:16\nruntime.main\n\tD:/go_1_17_1/src/runtime/proc.go:255"}
// 2. 高性能日志
// 当性能和类型安全至关重要时,请使用记录器。它甚至比 SugaredLogger 更快,分配也更少,但它只支持结构化日志记录。
logger, _ := zap.NewProduction()
//logger, _ := zap.NewDevelopment()
defer logger.Sync() // 刷新缓冲区,存盘
logger.Debug("faild to fetch url",
// 作为强类型字段值的结构化上下文.
zap.String("url", "https://www.mayanan.cn"),
zap.Int("age", 28),
zap.Duration("duration", time.Second),
)
// 输出结构跟sugar一致
}
由于zap日志zap.NewProduction()和zap.NewDevelopment()默认是将日志输出到控制台,我们生产中需要将日志写入到文件
定义logger,将日志写入文件而不是终端(zap.SugaredLogger)
package main
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var sugarLogger *zap.SugaredLogger
func main() {
InitLogger()
defer sugarLogger.Sync()
for i := 0; i < 10000; i++ {
simpleHttpGet("www.sogo.com")
simpleHttpGet("http://www.sogo.com")
}
}
func InitLogger() {
writeSyncer := getLogWriter()
encoder := getEncoder()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
logger := zap.New(core, zap.AddCaller())
sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
//return zapcore.NewJSONEncoder(encoderConfig)
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: "./test.log",
MaxSize: 1,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
LocalTime: true,
}
return zapcore.AddSync(lumberJackLogger)
}
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()
//}
sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, "这是一个错误")
sugarLogger.Infof("Success! statusCode = %d for URL %s", 200, url)
}
日志输出结果图:
参考文档:zap+Lumberjack 记录日志同时实现日志切割归档
高性能日志输出到(zap.Logger)
点击查看代码
package main
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"time"
)
//var sugarLogger *zap.SugaredLogger
var logger *zap.Logger
func main() {
InitLogger()
defer logger.Sync()
for i := 0; i < 10000; i++ {
simpleHttpGet("www.sogo.com")
simpleHttpGet("http://www.sogo.com")
}
}
func InitLogger() {
writeSyncer := getLogWriter()
encoder := getEncoder()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
logger = zap.New(core, zap.AddCaller())
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
return zapcore.NewJSONEncoder(encoderConfig)
//return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: "./test.log",
MaxSize: 1,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
LocalTime: true,
}
return zapcore.AddSync(lumberJackLogger)
}
func simpleHttpGet(url string) {
logger.Debug("这是一条DEBUG的信息:",
zap.String("name", "sankaun"),
zap.Int("age", 18),
)
//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()
//}
logger.Error("这是一条Error的信息",
zap.Time("now", time.Now()),
zap.Bool("bool", false),
)
logger.Info("这是一条Info的信息",
zap.Duration("now", time.Second * 3),
zap.Bool("bool", true),
)
}
高性能日志输出到(zap.Logger),不同日志类型存储到不同目录文件
结构图:
点击查看代码
package main
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"time"
)
var infoLogger *zap.Logger
var errLogger *zap.Logger
var otherLogger *zap.Logger
func main() {
InitLogger()
defer infoLogger.Sync()
defer errLogger.Sync()
defer otherLogger.Sync()
for i := 0; i < 10000; i++ {
simpleHttpGet("www.sogo.com")
simpleHttpGet("http://www.sogo.com")
}
}
func InitLogger() {
infoWriteSyncer := getLogWriter("info")
errWriteSyncer := getLogWriter("error")
otherWriteSyncer := getLogWriter("other")
encoder := getEncoder()
infoCore := zapcore.NewCore(encoder, infoWriteSyncer, zapcore.InfoLevel)
errCore := zapcore.NewCore(encoder, errWriteSyncer, zapcore.ErrorLevel)
otherCore := zapcore.NewCore(encoder, otherWriteSyncer, zapcore.DebugLevel)
infoLogger = zap.New(infoCore, zap.AddCaller())
errLogger = zap.New(errCore, zap.AddCaller())
otherLogger = zap.New(otherCore, zap.AddCaller())
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
return zapcore.NewJSONEncoder(encoderConfig)
//return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter(infoOrErr string) zapcore.WriteSyncer {
var lumberJackLogger *lumberjack.Logger
if infoOrErr == "info" {
lumberJackLogger = &lumberjack.Logger{
Filename: "./info/info.log",
MaxSize: 1,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
LocalTime: true,
}
} else if infoOrErr == "error"{
lumberJackLogger = &lumberjack.Logger{
Filename: "./error/error.log",
MaxSize: 1,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
LocalTime: true,
}
} else {
lumberJackLogger = &lumberjack.Logger{
Filename: "./other/other.log",
MaxSize: 1,
MaxBackups: 5,
MaxAge: 30,
Compress: false,
LocalTime: true,
}
}
return zapcore.AddSync(lumberJackLogger)
}
func simpleHttpGet(url string) {
otherLogger.Debug("这是一条DEBUG的信息:",
zap.String("name", "sankaun"),
zap.Int("age", 18),
)
//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()
//}
errLogger.Error("这是一条Error的信息",
zap.Time("now", time.Now()),
zap.Bool("bool", false),
)
infoLogger.Info("这是一条Info的信息",
zap.Duration("now", time.Second * 3),
zap.Bool("bool", true),
)
}
补充-日志输出到文件和stderr-简单方法
func NewLogger() (*zap.Logger, error) {
// 日志输出到文件配置
cfg := zap.NewProductionConfig()
cfg.OutputPaths = []string{
"stderr",
"./myproject.log",
}
return cfg.Build()
}
func main() {
//logger, _ := zap.NewProduction()
logger, err := NewLogger()
if err != nil {
// 初始化logger失败
panic(err)
}
sugar := logger.Sugar()
defer sugar.Sync() // 刷新缓冲区,存盘
sugar.Infow("这是第一条日志消息", "name", "三三", "age", 99)
}
zap.S()函数和zap.L()函数
zap.S()函数和zap.L()函数很有用: 提供了一个全局的安全访问logger的途径
func InitLogger() {
//logger, _ := zap.NewProduction() // 生产日志
logger, _ := zap.NewDevelopment() // 开发日志
zap.ReplaceGlobals(logger)
// zap.S()可以获取一个全局的sugar, 可以让我们自己设置一个全局的logger
// 日志是分级别的:debug info warning error fatal
// zap.S()函数和zap.L()函数很有用: 提供了一个全局的安全访问logger的途径
}
func main() {
port := 8021
// 初始化日志
initialize.InitLogger()
// 初始化routers
router := initialize.Routers()
zap.S().Debugf("开启服务,端口:%d", port)
if err := router.Run(fmt.Sprintf(":%d", port)); err != nil {
zap.S().Panic("服务启动失败", err.Error())
}
}
分类:
golang第三方库
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析