golang基于zap的高开发者体验日志记录插件库zl的使用

golang基于zap的高开发者体验日志记录插件库zl的使用

zl是一个基于zap的日志记录库,专为提升开发者体验而设计。它可以根据不同环境选择最适合的输出格式,在本地开发环境提供易读的控制台输出,在生产环境输出结构化详细日志。

主要特性

可选择的输出格式

  1. PrettyOutput (默认) 🧑‍💻
    • 高开发者体验
    • 开发环境最佳设置
    • 控制台输出彩色简化日志
    • 日志文件输出详细JSON日志
    • 易读的错误报告和堆栈跟踪
    • 可直接跳转到控制台日志输出的文件行(使用Goland或VSCode时)

PrettyOutput示例

  1. ConsoleOutput

    • 高性能
    • 生产环境最佳设置
    • 控制台输出详细JSON日志
    • 特别适合Google Cloud Logging或Datadog等云环境
    • 仅使用zap提供的功能,不执行额外处理,速度很快
  2. FileOutput

    • 生产环境最佳设置
    • 特别适合命令行工具或本地环境
    • 支持日志文件轮转
  3. ConsoleAndFileOutput

    • 开发环境设置
    • 控制台和日志文件都输出详细JSON日志
    • 建议配合jq命令使用以避免信息过载
    • 更推荐使用PrettyOutput替代

安装

go get -u github.com/nkmr-jp/zl

快速开始

package main

import (
	"encoding/json"
	"os"
	"strconv"

	"github.com/nkmr-jp/zl"
	"go.uber.org/zap"
)

func main() {
	// 设置选项
	zl.SetLevel(zl.DebugLevel)
	zl.SetOmitKeys(zl.HostnameKey)

	// 初始化
	zl.Init()
	defer zl.Sync() // 刷新日志缓冲区

	// 写入日志
	zl.Info("USER_INFO", zap.String("user_name", "Alice"), zap.Int("user_age", 20)) // 可以使用zap字段
	zl.Info("DISPLAY_TO_CONSOLE", zl.Console("The message you want to display to console"))
	zl.Warn("WARN_MESSAGE")
	zl.Debug("DEBUG_MESSAGE")
	_, err := os.ReadFile("test")
	zl.Err("READ_FILE_ERROR", err)
	
	// 如果在同一位置多次出现相同错误,错误报告会将它们全部显示在一起
	for i := 0; i < 2; i++ {
		_, err = strconv.Atoi("one")
		zl.Err("A_TO_I_ERROR", err)
	}
	for i := 0; i < 3; i++ {
		v := ""
		err = json.Unmarshal([]byte("test"), &v)
		zl.Err("JSON_UNMARSHAL_ERROR", err)
	}
}

控制台输出

控制台显示最简信息,出现错误时显示堆栈跟踪。

控制台输出示例

文件输出

日志文件中包含详细信息,可以使用jq提取所需信息。

$ cat log/app.jsonl | jq 'select(.message | startswith("USER_")) | select(.pid==921)'
{
  "severity": "INFO",
  "timestamp": "2022-08-22T10:30:39.154575+09:00",
  "caller": "basic/main.go:22",
  "function": "main.main",
  "message": "USER_INFO",
  "version": "fc43f68",
  "pid": 921,
  "user_name": "Alice",
  "user_age": 20
}

更多示例

  • 基础示例: examples/basic/main.go
  • 测试示例: example_test.go

更多关于golang基于zap的高开发者体验日志记录插件库zl的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于zap的高开发者体验日志记录插件库zl的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用 zl - 基于 Zap 的高开发者体验日志库

zl 是一个基于 Uber 的 Zap 日志库构建的 Go 日志插件库,旨在提供更好的开发者体验和更简洁的 API。下面我将介绍如何使用 zl 进行日志记录。

安装

首先安装 zl 库:

go get github.com/go-zing/gozz-kit/zlog

基本使用

初始化日志器

package main

import (
	"github.com/go-zing/gozz-kit/zlog"
	"go.uber.org/zap"
)

func main() {
	// 使用默认配置初始化
	logger := zlog.Default()

	// 或者自定义配置
	customLogger, err := zlog.New(
		zlog.WithLevel(zap.DebugLevel),
		zlog.WithOutputPaths([]string{"stdout", "app.log"}),
		zlog.WithErrorOutputPaths([]string{"stderr"}),
	)
	if err != nil {
		panic(err)
	}
	defer customLogger.Sync()
}

记录日志

func logExample() {
	logger := zlog.Default()

	// 不同级别日志
	logger.Debug("这是一条调试信息")
	logger.Info("这是一条普通信息")
	logger.Warn("这是一条警告信息")
	logger.Error("这是一条错误信息")
	// logger.Fatal("致命错误,会调用os.Exit(1)")
	// logger.Panic("恐慌错误,会引发panic")

	// 带结构化字段的日志
	logger.Info("用户登录",
		zap.String("username", "john"),
		zap.Int("attempt", 3),
		zap.Duration("elapsed", time.Second),
	)

	// 使用Sugar()简化日志记录
	sugar := logger.Sugar()
	sugar.Infow("用户登录",
		"username", "john",
		"attempt", 3,
		"elapsed", time.Second,
	)
	sugar.Infof("用户 %s 登录,尝试次数 %d", "john", 3)
}

高级特性

日志采样

func samplingExample() {
	logger, err := zlog.New(
		zlog.WithSampling(&zap.SamplingConfig{
			Initial:    100,
			Thereafter: 100,
		}),
	)
	if err != nil {
		panic(err)
	}
	defer logger.Sync()

	// 当日志量很大时,采样配置可以帮助减少日志量
	for i := 0; i < 1000; i++ {
		logger.Info("高频率日志消息", zap.Int("count", i))
	}
}

自定义编码器

func encoderExample() {
	logger, err := zlog.New(
		zlog.WithEncoderConfig(zapcore.EncoderConfig{
			TimeKey:        "ts",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller",
			FunctionKey:    zapcore.OmitKey,
			MessageKey:     "msg",
			StacktraceKey:  "stacktrace",
			LineEnding:     zapcore.DefaultLineEnding,
			EncodeLevel:    zapcore.LowercaseLevelEncoder,
			EncodeTime:     zapcore.ISO8601TimeEncoder,
			EncodeDuration: zapcore.StringDurationEncoder,
			EncodeCaller:   zapcore.ShortCallerEncoder,
		}),
	)
	if err != nil {
		panic(err)
	}
	defer logger.Sync()
}

上下文日志

func contextExample() {
	logger := zlog.Default()

	// 创建带有固定字段的派生logger
	userLogger := logger.With(
		zap.String("userID", "12345"),
		zap.String("traceID", "abcde"),
	)

	// 这些日志都会自动带上userID和traceID字段
	userLogger.Info("用户操作1")
	userLogger.Warn("用户操作2")
}

性能优化

func performanceExample() {
	logger := zlog.Default()

	// 对于性能敏感的场景,可以使用Check+Write组合避免不必要的字段计算
	if ce := logger.Check(zap.InfoLevel, "性能敏感日志"); ce != nil {
		ce.Write(
			zap.String("key", "value"),
			zap.Int("count", 42),
		)
	}
}

最佳实践

  1. 合理使用日志级别

    • Debug: 调试信息
    • Info: 重要业务流程
    • Warn: 预期外的异常但不影响程序运行
    • Error: 影响程序运行的错误
  2. 结构化日志:尽量使用结构化字段而非字符串拼接

  3. 避免频繁Sync:Sync操作会刷新缓冲区的日志到磁盘,频繁调用会影响性能

  4. 生产环境配置

    func productionConfig() {
        logger, err := zlog.New(
            zlog.WithLevel(zap.InfoLevel), // 生产环境通常用Info级别
            zlog.WithOutputPaths([]string{"stdout"}), // 配合日志收集系统
            zlog.WithDevelopment(false), // 关闭开发模式
        )
        if err != nil {
            panic(err)
        }
        defer logger.Sync()
    }
    

zl 通过封装 Zap 提供了更简洁的 API 和更好的默认配置,同时保留了 Zap 的高性能和灵活性,是 Go 项目中日志记录的一个优秀选择。

回到顶部