golang简单可配置的Go结构化日志记录插件库log的使用
Golang 简单可配置的 Go 结构化日志记录插件库 log 的使用
简介
log 是一个简单、高度可配置的结构化日志记录库,具有以下特点:
- 日志记录器简单,只负责创建日志条目并发送给处理程序
- 处理程序易于编写、注册和移除
- 能够指定哪些日志级别发送到每个处理程序
- 处理程序和日志级别可在运行时配置
WithError
自动提取并添加错误输出中的文件、行和包信息- 方便的上下文辅助函数
GetContext
和SetContext
- 与 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
自动提取并添加错误输出中的文件、行和包信息- 方便的上下文辅助函数
GetContext
和SetContext
- 与 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. 日志库选择建议
- 标准库log:适合简单应用,无结构化日志需求
- logrus:适合大多数应用,API友好,功能丰富
- zap:适合高性能应用,对性能要求苛刻的场景
5. 日志最佳实践
- 根据环境设置不同日志级别(开发环境用Debug,生产环境用Info或更高)
- 使用结构化日志便于后续分析处理
- 敏感信息不要记录在日志中
- 合理控制日志量,避免日志爆炸
- 考虑日志轮转,避免单个日志文件过大
希望这些示例能帮助你更好地在Go项目中实现结构化日志记录!