uber-go/zap、lumberjack
zap是uber开源的go语言高性能日志库,
lumberjack是zap官方推荐的日志分割库,
结合这两个库我们可以在项目中实现完整的日志机制,
例如:输出日志到文件、根据文件大小或日期分割等。
uber-go/zap
安装
在项目目录下命令行执行
go get -u go.uber.org/zap
Logger
通过zap.NewDevelopment()或zap.NewProduction()都可以创建一个Logger,
它们的主要区别在于NewDevelopment会输出时间和包/文件/代码行信息,
而NewProduction不会,并且NewProduction不记录debug日志,
我们看一下例子:
zap.NewDevelopment()
package main
import "go.uber.org/zap"
func main() {
log, _ := zap.NewDevelopment()
log.Debug("这是debug日志")
log.Info("***************************")
log.Info("这是info日志")
log.Info("***************************")
log.Warn("这是warn日志")
log.Info("***************************")
log.Error("这是error日志")
log.Info("***************************")
log.Panic("这是panic日志")
}
输出
GOROOT=D:\Program Files\Go #gosetup
GOPATH=D:\work\goWorkspace;D:\work\goPath #gosetup
"D:\Program Files\Go\bin\go.exe" build -o C:\Users\smart\AppData\Local\Temp\___go_build_main_go__1_.exe D:/work/goWorkspace/src/helloGoMod/log/main.go #gosetup
C:\Users\smart\AppData\Local\Temp\___go_build_main_go__1_.exe #gosetup
2021-04-26T14:19:13.059+0800 DEBUG log/main.go:7 这是debug日志
2021-04-26T14:19:13.090+0800 INFO log/main.go:8 ***************************
2021-04-26T14:19:13.090+0800 INFO log/main.go:9 这是info日志
2021-04-26T14:19:13.090+0800 INFO log/main.go:10 ***************************
2021-04-26T14:19:13.090+0800 WARN log/main.go:11 这是warn日志
main.main
D:/work/goWorkspace/src/helloGoMod/log/main.go:11
runtime.main
D:/Program Files/Go/src/runtime/proc.go:225
2021-04-26T14:19:13.090+0800 INFO log/main.go:12 ***************************
2021-04-26T14:19:13.090+0800 ERROR log/main.go:13 这是error日志
main.main
D:/work/goWorkspace/src/helloGoMod/log/main.go:13
runtime.main
D:/Program Files/Go/src/runtime/proc.go:225
2021-04-26T14:19:13.090+0800 INFO log/main.go:14 ***************************
2021-04-26T14:19:13.090+0800 PANIC log/main.go:15 这是panic日志
main.main
D:/work/goWorkspace/src/helloGoMod/log/main.go:15
runtime.main
D:/Program Files/Go/src/runtime/proc.go:225
panic: 这是panic日志
goroutine 1 [running]:
go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc00013c0c0, 0x0, 0x0, 0x0)
D:/work/goWorkspace/pkg/mod/go.uber.org/zap@v1.16.0/zapcore/entry.go:234 +0x58d
go.uber.org/zap.(*Logger).Panic(0xc0000482a0, 0x5b9d71, 0x11, 0x0, 0x0, 0x0)
D:/work/goWorkspace/pkg/mod/go.uber.org/zap@v1.16.0/logger.go:226 +0x86
main.main()
D:/work/goWorkspace/src/helloGoMod/log/main.go:15 +0x219
Process finished with exit code 2
zap.NewProduction()
package main
import "go.uber.org/zap"
func main() {
log, _ := zap.NewProduction()
log.Debug("这是debug日志")
log.Info("***************************")
log.Info("这是info日志")
log.Info("***************************")
log.Warn("这是warn日志")
log.Info("***************************")
log.Error("这是error日志")
log.Info("***************************")
log.Panic("这是panic日志")
}
输出
GOROOT=D:\Program Files\Go #gosetup
GOPATH=D:\work\goWorkspace;D:\work\goPath #gosetup
"D:\Program Files\Go\bin\go.exe" build -o C:\Users\smart\AppData\Local\Temp\___go_build_main_go__1_.exe D:/work/goWorkspace/src/helloGoMod/log/main.go #gosetup
C:\Users\smart\AppData\Local\Temp\___go_build_main_go__1_.exe #gosetup
{"level":"info","ts":1619418048.7640002,"caller":"log/main.go:8","msg":"***************************"}
{"level":"info","ts":1619418048.7640002,"caller":"log/main.go:9","msg":"这是info日志"}
{"level":"info","ts":1619418048.7640002,"caller":"log/main.go:10","msg":"***************************"}
{"level":"warn","ts":1619418048.7640002,"caller":"log/main.go:11","msg":"这是warn日志"}
{"level":"info","ts":1619418048.7640002,"caller":"log/main.go:12","msg":"***************************"}
{"level":"error","ts":1619418048.7640002,"caller":"log/main.go:13","msg":"这是error日志","stacktrace":"main.main\n\tD:/work/goWorkspace/src/helloGoMod/log/main.go:13\nruntime.main\n\tD:/Program Files/Go/src/runtime/proc.go:225"}
{"level":"info","ts":1619418048.7640002,"caller":"log/main.go:14","msg":"***************************"}
{"level":"panic","ts":1619418048.7640002,"caller":"log/main.go:15","msg":"这是panic日志","stacktrace":"main.main\n\tD:/work/goWorkspace/src/helloGoMod/log/main.go:15\nruntime.main\n\tD:/Program Files/Go/src/runtime/proc.go:225"}
panic: 这是panic日志
goroutine 1 [running]:
go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc00013c0c0, 0x0, 0x0, 0x0)
D:/work/goWorkspace/pkg/mod/go.uber.org/zap@v1.16.0/zapcore/entry.go:234 +0x58d
go.uber.org/zap.(*Logger).Panic(0xc0000482a0, 0x5b9c50, 0x11, 0x0, 0x0, 0x0)
D:/work/goWorkspace/pkg/mod/go.uber.org/zap@v1.16.0/logger.go:226 +0x86
main.main()
D:/work/goWorkspace/src/helloGoMod/log/main.go:15 +0x219
Process finished with exit code 2
SugaredLogger
如果我们需要像使用fmt.Printf一样输出,可以使用SugaredLogger,
通过log.Sugar()/Desugar()切换,
例子:
package main
import (
"fmt"
"go.uber.org/zap"
)
func main() {
fmt.Printf("hello %v, helloZap\n", "yw") // hello yw, helloZap
log, _ := zap.NewDevelopment()
log.Info("hello " + "yw" + ", helloZap") // 2021-04-26T14:35:32.531+0800 INFO log/main.go:11 hello yw, helloZap
// SugaredLogger
sLog := log.Sugar()
// 类似fmt.Println
sLog.Info("hello ", "yw, ", "helloZap") // 2021-04-26T14:35:32.559+0800 INFO log/main.go:15 hello yw, helloZap
// 类似fmt.Printf
sLog.Infof("hello %v, helloZap", "yw") // 2021-04-26T14:35:32.559+0800 INFO log/main.go:17 hello yw, helloZap
// 切换到标准Logger
log = sLog.Desugar()
}
输出
日志输出到文件
创建Logger的方式和之前略有不同
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
)
func main() {
// 编码器配置
config := zap.NewProductionEncoderConfig()
// 指定时间编码器
config.EncodeTime = zapcore.ISO8601TimeEncoder
// 日志级别用大写
config.EncodeLevel = zapcore.CapitalLevelEncoder
// 编码器
encoder := zapcore.NewConsoleEncoder(config)
// 日志文件
file, _ := os.Create("./test.log")
// 写日志
sync := zapcore.AddSync(file)
// 创建Logger
core := zapcore.NewCore(encoder, sync, zapcore.DebugLevel)
logger := zap.New(core, zap.AddCaller())
// 打印日志
logger.Info("hello " + "yw" + ", helloZap")
// SugaredLogger
sLog := logger.Sugar()
// 类似fmt.Println
sLog.Info("hello ", "yw, ", "helloZap")
// 类似fmt.Printf
sLog.Infof("hello %v, helloZap", "yw")
}
运行
lumberjack
因为zap不支持日志分割,这里引入lumberjack
安装
在项目目录下命令行执行
go get -u github.com/natefinch/lumberjack
整合lumberjack
在WriteSyncer中添加lumberjack支持
package main
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
// 编码器配置
config := zap.NewProductionEncoderConfig()
// 指定时间编码器
config.EncodeTime = zapcore.ISO8601TimeEncoder
// 日志级别用大写
config.EncodeLevel = zapcore.CapitalLevelEncoder
// 编码器
encoder := zapcore.NewConsoleEncoder(config)
/*// 日志文件
file, _ := os.Create("./test.log")
// 写日志
sync := zapcore.AddSync(file)*/
// 修改为添加lumberjack支持
lj := &lumberjack.Logger{
Filename: "./test.log",
MaxSize: 1, // 日志文件最大1M
MaxBackups: 5,
MaxAge: 7, // 日志保留最长时间7天
Compress: false,
}
sync := zapcore.AddSync(lj)
// 创建Logger
core := zapcore.NewCore(encoder, sync, zapcore.DebugLevel)
logger := zap.New(core, zap.AddCaller())
// 打印日志
logger.Info("hello " + "yw" + ", helloZap")
// SugaredLogger
sLog := logger.Sugar()
// 类似fmt.Println
sLog.Info("hello ", "yw, ", "helloZap")
// 类似fmt.Printf
sLog.Infof("hello %v, helloZap", "yw")
}
我首先修改test.log文件内容超过1M,然后再运行代码
可以看到lumberjack已为我们生成了一个新的日志文件