golang集成Context与Zap日志框架的灵活日志记录插件zax的使用

Golang集成Context与Zap日志框架的灵活日志记录插件zax的使用

Zax (zap with context)

Zax是一个为Zap Logger添加上下文支持的库,它让Gopher们能够避免生成logger样板代码。通过将logger作为参数传递给函数,它增强了参数功能,避免了需要多个具有显式依赖关系的方法。

安装

go get -u github.com/yuseferi/zax/v2

使用方法

添加上下文字段

要向上下文添加内容并携带它,只需使用zap.Set:

ctx = zax.Set(ctx, []zap.Field{zap.String("trace_id", "my-trace-id")})

获取上下文中的字段

要检索存储在上下文中的zap字段,使用zax.Get:

zax.Get(ctx)  // 这会检索存储在上下文中的zap字段

记录带上下文的日志

要检索存储在上下文中的zap字段并记录它们:

logger.With(zax.Get(ctx)...).Info("just a test record")

获取特定字段

要检索上下文中的特定字段,可以使用zax.GetField:

zax.GetField(ctx, "trace_id")

之后,你可以像使用常规logger一样使用输出并执行日志记录操作:

logger.With(zax.Get(ctx)...).Info("message")
logger.With(zax.Get(ctx)...).Debug("message")

完整示例

假设你想在系统入口点生成一个追踪器,并保持它直到进程完成:

func main() {
    logger, _ := zap.NewProduction()
    ctx := context.Background()
    s := NewServiceA(logger)
    ctx = zax.Set(ctx, zap.String("trace_id", "my-trace-id"))  
    // 如果你想一次添加多个字段
    //ctx = zax.Set(ctx, []zap.Field{zap.String("trace_id", "my-trace-id"),zap.String("span_id", "my-span-id")})
    s.funcA(ctx)
}

type ServiceA struct {
logger *zap.Logger
}

func NewServiceA(logger *zap.Logger) *ServiceA {
    return &ServiceA{
        logger: logger,
    }
}

func (s *ServiceA) funcA(ctx context.Context) {
    s.logger.Info("func A") // 它不包含trace_id,你需要手动添加
    s.logger.With(zax.Get(ctx)...).Info("func A") // 它将记录"trace_id" = "my-trace-id"
}

性能基准

我们对Zax V2、V1和Zap使用相同字段进行了基准测试。以下是基准测试结果: 如你所见,V2(在上下文中仅存储字段的方法)比V1(在上下文中存储整个logger对象)具有更好的性能。

pkg: github.com/yuseferi/zax/v2
BenchmarkLoggingWithOnlyZap-10          103801226               35.56 ns/op          112 B/op          1 allocs/op
BenchmarkLoggingWithOnlyZap-10          98576570                35.56 ns/op          112 B/op          1 allocs/op
BenchmarkLoggingWithOnlyZap-10          100000000               35.24 ns/op          112 B/op          1 allocs/op
BenchmarkLoggingWithOnlyZap-10          100000000               34.85 ns/op          112 B/op          1 allocs/op
BenchmarkLoggingWithOnlyZap-10          100000000               34.98 ns/op          112 B/op          1 allocs/op
BenchmarkLoggingWithZaxV2-10            64324434                56.02 ns/op           72 B/op          2 allocs/op
BenchmarkLoggingWithZaxV2-10            63939517                56.98 ns/op           72 B/op          2 allocs/op
BenchmarkLoggingWithZaxV2-10            63374052                57.60 ns/op           72 B/op          2 allocs/op
BenchmarkLoggingWithZaxV2-10            63417358                57.37 ns/op           72 B/op          2 allocs/op
BenchmarkLoggingWithZaxV2-10            57964246                57.97 ns/op           72 B/op          2 allocs/op
BenchmarkLoggingWithZaxV1-10            54062712                66.40 ns/op          160 B/op          2 allocs/op
BenchmarkLoggingWithZaxV1-10            53155524                65.61 ns/op          160 B/op          2 allocs/op
BenchmarkLoggingWithZaxV1-10            54428521                64.19 ns/op          160 B/op          2 allocs/op
BenchmarkLoggingWithZaxV1-10            55420744                64.28 ns/op          160 B/op          2 allocs/op
BenchmarkLoggingWithZaxV1-10            55199061                64.50 ns/op          160 B/op          2 allocs/op
PASS
ok      github.com/yuseferi/zax/v2      56.919s

贡献

我们坚信开源精神❤️😊。请随时通过提出问题并提交拉取请求来贡献,使Zax变得更好!


更多关于golang集成Context与Zap日志框架的灵活日志记录插件zax的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang集成Context与Zap日志框架的灵活日志记录插件zax的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang集成Context与Zap日志框架的zax插件使用指南

什么是zax

zax是一个基于Zap日志框架的插件,它提供了与Context集成的能力,使得日志记录更加灵活和上下文感知。zax的主要特点包括:

  1. 与标准库context.Context无缝集成
  2. 支持结构化日志记录
  3. 高性能,基于Zap的高效日志记录能力
  4. 支持日志字段的链式调用

安装zax

go get github.com/uber-go/zap
go get github.com/yourusername/zax

基本使用示例

package main

import (
	"context"
	"time"

	"go.uber.org/zap"
	"github.com/yourusername/zax"
)

func main() {
	// 创建基础logger
	logger, _ := zap.NewProduction()
	defer logger.Sync() // 确保日志被刷新

	// 创建zax logger
	zaxLogger := zax.New(logger)

	// 创建context
	ctx := context.Background()

	// 为context添加日志字段
	ctx = zax.WithFields(ctx, zap.String("request_id", "12345"), zap.String("user", "john"))

	// 记录日志
	zaxLogger.Info(ctx, "User logged in", zap.Duration("duration", 100*time.Millisecond))
}

高级功能

1. 上下文字段继承

func handleRequest(ctx context.Context, zaxLogger *zax.Logger) {
	// 添加更多上下文字段
	ctx = zax.WithFields(ctx, zap.String("handler", "user_profile"))
	
	// 所有日志都会自动包含request_id, user和handler字段
	zaxLogger.Info(ctx, "Processing request")
}

2. 动态字段添加

func processOrder(ctx context.Context, zaxLogger *zax.Logger, orderID string) {
	// 动态添加字段
	zaxLogger.With(zap.String("order_id", orderID)).Info(ctx, "Order processed")
}

3. 错误处理

func someOperation(ctx context.Context, zaxLogger *zax.Logger) error {
	err := doSomething()
	if err != nil {
		zaxLogger.Error(ctx, "Operation failed", zap.Error(err))
		return err
	}
	return nil
}

性能优化建议

  1. 复用Logger实例:避免在每次请求时创建新的Logger实例
  2. 预分配字段:对于高频日志,预先分配字段可以减少内存分配
  3. 使用zap的采样配置:在高负载环境下启用采样
func setupLogger() *zax.Logger {
	config := zap.NewProductionConfig()
	config.Sampling = &zap.SamplingConfig{
		Initial:    100,
		Thereafter: 100,
	}
	logger, _ := config.Build()
	return zax.New(logger)
}

自定义配置示例

func customLogger() *zax.Logger {
	// 自定义encoder配置
	encoderCfg := zapcore.EncoderConfig{
		TimeKey:        "timestamp",
		LevelKey:      "level",
		NameKey:       "logger",
		CallerKey:     "caller",
		FunctionKey:   zapcore.OmitKey,
		MessageKey:    "message",
		StacktraceKey: "stacktrace",
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeLevel:   zapcore.LowercaseLevelEncoder,
		EncodeTime:    zapcore.ISO8601TimeEncoder,
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller: zapcore.ShortCallerEncoder,
	}

	// 创建自定义core
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderCfg),
		zapcore.AddSync(os.Stdout),
		zap.InfoLevel,
	)

	// 创建logger
	logger := zap.New(core)
	return zax.New(logger)
}

最佳实践

  1. 合理使用日志级别

    • Debug: 开发调试信息
    • Info: 重要业务事件
    • Warn: 需要注意但不影响流程的问题
    • Error: 需要立即调查的错误
  2. 结构化日志:始终使用结构化字段而非字符串拼接

  3. 敏感信息过滤:不要在日志中记录密码、token等敏感信息

  4. 上下文传递:通过context传递请求级别的日志字段

zax通过将Zap的强大功能与Context的灵活性结合,为Golang应用提供了高效且易于使用的日志解决方案。

回到顶部