go微服務框架Kratos筆記(二)引入zap日志庫


介紹

zap日志庫是一款高性能的開源日志庫,提供了結構化日志記錄和printf風格的日志記錄

安裝

go get -u go.uber.org/zap

如何在kratos框架中使用

參考官方文檔中描述,為了方便業務自適配不同的 log 接入使用,Logger 只包含了最簡單的 Log 接口。當業務需要在 Kratos 框架內部使用自定義的 log 的時候,只需要簡單實現 Log 方法即可。

日志庫較為公用建議放在kit基礎庫中方便其他微服務引用,可參考Go工程化最佳實踐

實現log接口並配置zap日志庫編碼

package pkg

import (
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

var _ log.Logger = (*ZapLogger)(nil)

type ZapLogger struct {
	log  *zap.Logger
	Sync func() error
}

// Logger 配置zap日志,將zap日志庫引入
func Logger() log.Logger {
	//配置zap日志庫的編碼器
	encoder := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stack",
		EncodeTime:     zapcore.ISO8601TimeEncoder,
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalLevelEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.FullCallerEncoder,
	}
	return NewZapLogger(
		encoder,
		zap.NewAtomicLevelAt(zapcore.DebugLevel),
		zap.AddStacktrace(
			zap.NewAtomicLevelAt(zapcore.ErrorLevel)),
		zap.AddCaller(),
		zap.AddCallerSkip(2),
		zap.Development(),
	)
}

// 日志自動切割,采用 lumberjack 實現的
func getLogWriter() zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   "../../zap.log", //指定日志存儲位置
		MaxSize:    10, //日志的最大大小(M)
		MaxBackups: 5, //日志的最大保存數量
		MaxAge:     30, //日志文件存儲最大天數
		Compress:   false, //是否執行壓縮
	}
	return zapcore.AddSync(lumberJackLogger)
}

// NewZapLogger return a zap logger.
func NewZapLogger(encoder zapcore.EncoderConfig, level zap.AtomicLevel, opts ...zap.Option) *ZapLogger {
	//日志切割
	writeSyncer := getLogWriter()
	//設置日志級別
	level.SetLevel(zap.InfoLevel)
	var core zapcore.Core
	//開發模式下打印到標准輸出
	// --根據配置文件判斷輸出到控制台還是日志文件--
	if conf.GetConfig().GetString("project.mode") == "dev" {
		core = zapcore.NewCore(
			zapcore.NewConsoleEncoder(encoder),                      // 編碼器配置
			zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), // 打印到控制台
			level, // 日志級別
		)
	} else {
		core = zapcore.NewCore(
			zapcore.NewJSONEncoder(encoder), // 編碼器配置
			zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(writeSyncer)), // 打印到控制台和文件
			level, // 日志級別
		)
	}
	zapLogger := zap.New(core, opts...)
	return &ZapLogger{log: zapLogger, Sync: zapLogger.Sync}
}

// Log 實現log接口
func (l *ZapLogger) Log(level log.Level, keyvals ...interface{}) error {
	if len(keyvals) == 0 || len(keyvals)%2 != 0 {
		l.log.Warn(fmt.Sprint("Keyvalues must appear in pairs: ", keyvals))
		return nil
	}

	var data []zap.Field
	for i := 0; i < len(keyvals); i += 2 {
		data = append(data, zap.Any(fmt.Sprint(keyvals[i]), keyvals[i+1]))
	}

	switch level {
	case log.LevelDebug:
		l.log.Debug("", data...)
	case log.LevelInfo:
		l.log.Info("", data...)
	case log.LevelWarn:
		l.log.Warn("", data...)
	case log.LevelError:
		l.log.Error("", data...)
	case log.LevelFatal:
		l.log.Fatal("", data...)
	}
	return nil
}

替換為zap日志庫

在main函數中將元日志替換為zap日志

app, cleanup, err := initApp(bc.Server, bc.Data, zaoLog.Logger())

添加日志中間件

在 grpc.ServerOption和http.ServerOption 中引入 logging.Server(), 則會在每次收到 gRPC 請求的時候打印詳細請求信息。

var opts = []grpc.ServerOption{
		grpc.Middleware(
			recovery.Recovery(),
			logging.Server(logger),//日志中間件
		),
	}
//=======================================
var opts = []http.ServerOption{
		http.Middleware(
			recovery.Recovery(),
			logging.Server(logger),//日志中間件
		),
	}

在 grpc.WithMiddleware和http.WithMiddleware 中引入 logging.Client(), 則會在每次發起 grpc 請求的時候打印詳細請求信息。

logger := log.DefaultLogger
conn, err := transgrpc.DialInsecure(
    context.Background(),
    grpc.WithEndpoint("127.0.0.1:9000"),
     grpc.WithMiddleware(
        logging.Client(logger),
    ),
)
//=======================================
logger := log.DefaultLogger
conn, err := http.NewClient(
    context.Background(),
    http.WithMiddleware(
        logging.Client(logger),
    ),
    http.WithEndpoint("127.0.0.1:8000"),
)

如有錯誤請留言反饋


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM