常见问题
基础使用
全局日志记录器和自定义日志记录器有什么区别?
全局日志记录器通过 dd.Info() 等包级函数直接使用,适合简单场景。自定义日志记录器通过 dd.New() 创建,支持独立配置和生命周期管理。
go
// 全局日志记录器
dd.Info("全局日志")
// 自定义日志记录器
logger, _ := dd.New(dd.JSONConfig())
logger.Info("独立日志")如何在程序启动时初始化全局日志记录器?
go
func init() {
err := dd.InitDefault(dd.JSONConfig())
if err != nil {
log.Fatal(err)
}
}或通过 SetDefault:
go
logger, _ := dd.New(dd.Config{
Format: dd.FormatJSON,
Targets: []dd.OutputTarget{
dd.ConsoleOutput(),
dd.FileOutput("logs/app.json"),
},
})
dd.SetDefault(logger)Fatal 级别日志会怎样?
Fatal / Fatalf / FatalWith 在输出日志后调用 os.Exit(1)(defer 语句不会执行;内部会先尝试 Close() 刷新挂起日志,最多等待 5 秒)。可通过 FatalHandler 自定义退出行为;如需资源清理,请改用 ErrorWith + 显式 Shutdown(ctx)。
配置
如何同时输出到控制台和文件?
go
logger, _ := dd.New(dd.Config{
Targets: []dd.OutputTarget{
dd.ConsoleOutput(),
dd.FileOutput("logs/app.log"),
},
})
// 或 JSON 格式
logger, _ := dd.New(dd.Config{
Format: dd.FormatJSON,
Targets: []dd.OutputTarget{
dd.ConsoleOutput(),
dd.FileOutput("logs/app.json"),
},
})如何动态修改日志级别?
go
_ = logger.SetLevel(dd.LevelDebug) // 运行时修改(返回 error)
_ = dd.SetLevel(dd.LevelDebug) // 修改全局日志记录器级别如何配置文件轮换策略?
通过 FileWriter 配置:
go
fw, _ := dd.NewFileWriter("logs/app.log",
dd.DefaultFileWriterConfig(), // 100MB, 30 天,10 个备份
)性能
日志会影响程序性能吗?
DD 在设计上追求高性能:
- 热路径低分配优化
- 原子级别检查,无锁
- 大输入(≥10KB)的敏感数据过滤在独立 goroutine 中执行并带超时保护;小输入同步处理
- 可选缓冲写入减少 I/O
高吞吐场景如何优化?
- 使用
BufferedWriter减少 I/O - 先检查级别再构造字段
- 考虑启用日志采样
- 避免在高频路径使用
Any字段
详见 性能优化。
安全
敏感数据过滤是如何工作的?
SensitiveDataFilter 使用正则模式匹配,在日志写入前自动替换匹配的敏感值为 [REDACTED]。小输入同步处理,大输入在独立 goroutine 中执行并带超时保护,不阻塞日志写入。
如何自定义敏感数据模式?
go
filter, _ := dd.NewCustomSensitiveDataFilter(
`(?i)my_secret_field\s*[:=]\s*\S+`,
)如何确保日志不被篡改?
使用 IntegritySigner 对日志进行 HMAC 签名:
go
cfg, _ := dd.DefaultIntegrityConfigSafe()
signer, _ := dd.NewIntegritySigner(cfg)
sig := signer.Sign(logMessage)
// 验证:signer.Verify(signedEntry)错误处理
为什么 AddWriter 返回错误?
可能的原因:
ErrNilWriter-- 传入了 nil WriterErrLoggerClosed-- 日志记录器已关闭ErrMaxWritersExceeded-- Writer 数量超限
如何处理写入失败?
go
logger.SetWriteErrorHandler(func(w io.Writer, err error) {
// 自定义处理
metrics.WriteErrors.Inc()
})测试
如何在测试中捕获日志?
使用 LoggerRecorder:
go
rec := dd.NewLoggerRecorder()
logger, _ := rec.NewLogger()
logger.Info("test")
if !rec.ContainsMessage("test") {
t.Error("未找到预期日志")
}详见 测试辅助。