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())
}
}