golang简单可配置的Go结构化日志记录插件库log的使用

Golang 简单可配置的 Go 结构化日志记录插件库 log 的使用

简介

log 是一个简单、高度可配置的结构化日志记录库,具有以下特点:

  • 日志记录器简单,只负责创建日志条目并发送给处理程序
  • 处理程序易于编写、注册和移除
  • 能够指定哪些日志级别发送到每个处理程序
  • 处理程序和日志级别可在运行时配置
  • WithError 自动提取并添加错误输出中的文件、行和包信息
  • 方便的上下文辅助函数 GetContextSetContext
  • 与 go-playground/errors 配合使用,提取包装错误、类型和标签

安装

使用 go get 安装:

go get github.com/go-playground/log/v8@latest

基本使用

package main

import (
	"io"
	stdlog "log"

	"github.com/go-playground/errors/v5"
	"github.com/go-playground/log/v8"
)

func main() {
	// 重定向标准日志
	log.RedirectGoStdLog(true)

	// Trace 示例 (会记录函数执行时间)
	defer log.WithTrace().Info("time to run")

	// 不同级别日志记录
	log.Debug("debug")
	log.Info("info")
	log.Notice("notice")
	log.Warn("warn")
	log.Error("error")
	// log.Panic("panic") // 这会引发 panic
	log.Alert("alert")
	// log.Fatal("fatal") // 这会调用 os.Exit(1)

	// 带错误的日志记录
	err := errors.New("this is the inner error").AddTags(errors.T("inner", "tag"))
	err = errors.Wrap(err, "this is the wrapping error").AddTags(errors.T("outer", "tag"))
	log.WithError(err).WithFields(log.F("key", "value")).Info("test info")

	// 记录未包装的错误
	log.WithError(io.EOF).Error("unwrapped error")

	// 预定义全局字段
	log.WithDefaultFields(log.Fields{
		log.F("program", "test"),
		log.F("version", "0.1.3"),
	}...)

	log.WithField("key", "value").Info("testing default fields")

	// 请求范围内的默认字段
	logger := log.WithFields(
		log.F("request", "req"),
		log.F("scoped", "sco"),
	)
	logger.WithField("key", "value").Info("test")

	// 标准日志重定向测试
	stdlog.Println("This was redirected from Go STD output!")
	log.RedirectGoStdLog(false)
	stdlog.Println("This was NOT redirected from Go STD output!")
}

自定义处理程序

package main

import (
	"bytes"
	"fmt"

	"github.com/go-playground/log/v8"
)

// CustomHandler 是自定义处理程序
type CustomHandler struct {
	// 这里可以添加需要的属性
}

// Log 处理日志条目
func (c *CustomHandler) Log(e log.Entry) {
	// 这里可以打印到 os.Stderr,也可以序列化为 JSON 发送到中央日志服务器
	b := new(bytes.Buffer)
	b.Reset()
	b.WriteString(e.Message)

	for _, f := range e.Fields {
		_, _ = fmt.Fprintf(b, " %s=%v", f.Key, f.Value)
	}
	fmt.Println(b.String())
}

func main() {
	// 创建并注册自定义处理程序
	cLog := new(CustomHandler)
	log.AddHandler(cLog, log.AllLevels...)

	// Trace 示例
	defer log.WithTrace().Info("took this long")

	// 记录不同级别日志
	log.Debug("debug")
	log.Info("info")
	log.Notice("notice")
	log.Warn("warn")
	log.Error("error")
	// log.Panic("panic") // 这会引发 panic
	log.Alert("alert")
	// log.Fatal("fatal") // 这会调用 os.Exit(1)

	// 带字段的日志记录
	log.WithField("key", "value").Info("test info")
}

日志级别定义

级别 描述
Debug 对开发人员调试应用程序有用的信息,在正常操作期间无用
Info 正常的操作消息,可用于报告、测量吞吐量等,不需要采取行动
Notice 正常但重要的条件。不寻常但不是错误条件的事件
Warn 警告消息,不是错误,但表示如果不采取行动将发生错误
Error 非紧急故障,应转发给开发人员或管理员
Panic 通常影响多个应用/服务器/站点的"panic"条件
Alert 必须立即采取行动。应立即纠正
Fatal 应立即纠正,但表示主要系统故障

特点

  • 日志记录器简单,只负责创建日志条目并发送给处理程序
  • 处理程序易于编写、注册和移除
  • 能够指定哪些日志级别发送到每个处理程序
  • 处理程序和日志级别可在运行时配置
  • WithError 自动提取并添加错误输出中的文件、行和包信息
  • 方便的上下文辅助函数 GetContextSetContext
  • 与 go-playground/errors 配合使用,提取包装错误、类型和标签

更多关于golang简单可配置的Go结构化日志记录插件库log的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang简单可配置的Go结构化日志记录插件库log的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go结构化日志记录库log使用指南

Go标准库中的log包虽然简单易用,但功能有限。下面我将介绍几种更强大的结构化日志记录方案,包括标准库log、第三方库logrus和zap的使用方法。

1. 标准库log包基础使用

Go标准库中的log包提供了最基本的日志功能:

package main

import (
	"log"
	"os"
)

func main() {
	// 基本日志输出
	log.Println("这是一条普通日志")
	
	// 设置日志前缀
	log.SetPrefix("MyApp: ")
	
	// 设置日志标志(日期、时间、文件名等)
	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
	
	// 输出到文件
	file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Fatal("无法打开日志文件:", err)
	}
	defer file.Close()
	
	log.SetOutput(file)
	log.Println("这条日志会写入文件")
	
	// 致命错误日志(会调用os.Exit(1))
	// log.Fatal("致命错误")
	
	// 恐慌日志(会抛出panic)
	// log.Panic("恐慌错误")
}

2. 使用logrus进行结构化日志记录

logrus是Go中最流行的日志库之一,支持结构化日志和多种日志级别:

package main

import (
	"github.com/sirupsen/logrus"
	"os"
)

func main() {
	// 创建logrus实例
	log := logrus.New()
	
	// 设置日志级别
	log.SetLevel(logrus.DebugLevel)
	
	// 设置输出格式为JSON
	log.SetFormatter(&logrus.JSONFormatter{})
	
	// 输出到文件
	file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err == nil {
		log.SetOutput(file)
	} else {
		log.Info("无法写入日志文件,使用标准错误输出")
	}
	
	// 带字段的结构化日志
	log.WithFields(logrus.Fields{
		"event": "user_login",
		"user_id": 12345,
	}).Info("用户登录")
	
	// 不同级别的日志
	log.Debug("调试信息")
	log.Info("普通信息")
	log.Warn("警告信息")
	log.Error("错误信息")
	// log.Fatal("致命错误") // 会退出程序
	// log.Panic("恐慌错误") // 会抛出panic
	
	// 使用预定义字段
	contextLogger := log.WithFields(logrus.Fields{
		"app": "myapp",
		"env": "production",
	})
	contextLogger.Info("带上下文的日志")
}

3. 使用zap进行高性能日志记录

Uber开发的zap库是性能最高的Go日志库之一,特别适合高性能应用:

package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

func main() {
	// 配置zap日志编码器
	encoderCfg := zapcore.EncoderConfig{
		TimeKey:        "time",
		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,
	}

	// 创建核心
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderCfg),
		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), // 输出到控制台
		zapcore.InfoLevel, // 日志级别
	)

	// 创建日志记录器
	logger := zap.New(core, zap.AddCaller())
	defer logger.Sync() // 刷新缓冲区

	// 结构化日志
	logger.Info("用户操作",
		zap.String("action", "login"),
		zap.Int("user_id", 12345),
		zap.String("ip", "192.168.1.1"),
	)

	// 不同级别的日志
	logger.Debug("调试信息") // 不会输出,因为设置了InfoLevel
	logger.Info("普通信息")
	logger.Warn("警告信息")
	logger.Error("错误信息")
	// logger.Fatal("致命错误") // 会退出程序
	// logger.Panic("恐慌错误") // 会抛出panic

	// 性能优化的日志方法
	logger.Sugar().Infow("带结构化字段的日志",
		"url", "https://example.com",
		"attempt", 3,
		"backoff", 1.5,
	)
}

4. 日志库选择建议

  1. 标准库log:适合简单应用,无结构化日志需求
  2. logrus:适合大多数应用,API友好,功能丰富
  3. zap:适合高性能应用,对性能要求苛刻的场景

5. 日志最佳实践

  1. 根据环境设置不同日志级别(开发环境用Debug,生产环境用Info或更高)
  2. 使用结构化日志便于后续分析处理
  3. 敏感信息不要记录在日志中
  4. 合理控制日志量,避免日志爆炸
  5. 考虑日志轮转,避免单个日志文件过大

希望这些示例能帮助你更好地在Go项目中实现结构化日志记录!

回到顶部