
golang-samber-slog
热门使用 samber/slog-**** 包的 Golang 结构化日志扩展——多处理器管道(slog-multi)、日志采样(slog-sampling)、属性格式化(slog-formatter)、HTTP 中间件(slog-fiber、slog-gin、slog-chi、slog-echo)以及后端路由(slog-datadog、slog-sentry、slog-loki、slog-syslog、slog-logstash、slog-graylog...)。适用于正在使用或采用 slog 的项目,或代码库已导入任何 github.com/samber/slog-* 包的项目。
使用 samber/slog-**** 包的 Golang 结构化日志扩展——多处理器管道(slog-multi)、日志采样(slog-sampling)、属性格式化(slog-formatter)、HTTP 中间件(slog-fiber、slog-gin、slog-chi、slog-echo)以及后端路由(slog-datadog、slog-sentry、slog-loki、slog-syslog、slog-logstash、slog-graylog...)。适用于正在使用或采用 slog 的项目,或代码库已导入任何 github.com/samber/slog-* 包的项目。
角色: 你是一位 Go 日志架构师。你设计的日志管道中,每条记录都流经正确的处理器——采样在早期丢弃噪声,格式化器在记录离开进程前剥离 PII,路由器将错误发送到 Sentry 而信息发送到 Loki。
samber/slog-**** — Go 结构化日志管道
20 多个可组合的 slog.Handler 包,适用于 Go 1.21+。三个核心管道库以及 HTTP 中间件和后端接收器,均实现标准 slog.Handler 接口。
官方资源:
- github.com/samber/slog-multi — 处理器组合
- github.com/samber/slog-sampling — 吞吐量控制
- github.com/samber/slog-formatter — 属性转换
此技能并非详尽无遗。请参考库文档和代码示例以获取更多信息。Context7 可作为发现平台提供帮助。有关 Go 包文档、版本、符号和已知漏洞,→ 参见 samber/cc-skills-golang@golang-pkg-go-dev 技能。
管道模型
每个 samber/slog 管道都遵循规范顺序。记录从左到右流动——将采样放在前面以尽早丢弃,避免浪费 CPU 处理永远不会到达接收器的记录。
record → [Sampling] → [Pipe: trace/PII] → [Router] → [Sinks]
顺序很重要:采样在格式化之前节省 CPU。格式化在路由之前确保所有接收器收到干净的属性。颠倒顺序会浪费工作在被丢弃的记录上。
核心库
| 库 | 用途 | 关键构造函数 |
|---|---|---|
slog-multi |
处理器组合 | Fanout, Router, FirstMatch, Failover, Pool, Pipe |
slog-sampling |
吞吐量控制 | UniformSamplingOption, ThresholdSamplingOption, AbsoluteSamplingOption, CustomSamplingOption |
slog-formatter |
属性转换 | PIIFormatter, ErrorFormatter, FormatByType[T], FormatByKey, FlattenFormatterMiddleware |
slog-multi — 处理器组合
六种组合模式,每种满足不同的路由需求:
| 模式 | 行为 | 延迟影响 |
|---|---|---|
Fanout(handlers...) |
广播到所有处理器(顺序) | 所有处理器延迟之和 |
Router().Add(h, predicate).Handler() |
路由到所有匹配的处理器 | 匹配处理器延迟之和 |
Router().Add(...).FirstMatch().Handler() |
仅路由到第一个匹配 | 单个处理器延迟 |
Failover()(handlers...) |
顺序尝试直到一个成功 | 主处理器延迟(正常路径) |
Pool()(handlers...) |
负载均衡:每条记录发送到一个处理器 | 单个处理器延迟 |
Pipe(middlewares...).Handler(sink) |
接收器前的中间件链 | 中间件开销 + 接收器 |
// 将错误路由到 Sentry,所有日志路由到 stdout
logger := slog.New(
slogmulti.Router().
Add(sentryHandler, slogmulti.LevelIs(slog.LevelError)).
Add(slog.NewJSONHandler(os.Stdout, nil)).
Handler(),
)
内置谓词:LevelIs, LevelIsNot, MessageIs, MessageIsNot, MessageContains, MessageNotContains, AttrValueIs, AttrKindIs。
有关每种模式的完整代码示例,请参见 管道模式。
slog-sampling — 吞吐量控制
| 策略 | 行为 | 最佳用途 |
|---|---|---|
| Uniform | 丢弃所有记录的固定百分比 | 开发/测试环境噪声减少 |
| Threshold | 每个间隔记录前 N 条,然后以速率 R 采样 | 生产环境——保留初始可见性 |
| Absolute | 全局每个间隔最多 N 条记录 | 硬成本控制 |
| Custom | 用户函数返回每条记录的采样率 | 级别感知或时间感知规则 |
采样必须是管道中最外层的处理器——将其放在格式化之后会浪费 CPU 在被丢弃的记录上。
// Threshold:每 5 秒记录前 10 条,然后 10%——错误始终通过 Router 传递
logger := slog.New(
slogmulti.
Pipe(slogsampling.ThresholdSamplingOption{
Tick: 5 * time.Second, Threshold: 10, Rate: 0.1,
}.NewMiddleware()).
Handler(innerHandler),
)
匹配器将相似记录分组以进行去重:MatchByLevel(), MatchByMessage(), MatchByLevelAndMessage()(默认), MatchBySource(), MatchByAttribute(groups, key)。
有关策略比较和配置细节,请参见 采样策略。
slog-formatter — 属性转换
作为 Pipe 中间件应用,以便所有下游处理器接收干净的属性。
logger := slog.New(
slogmulti.Pipe(slogformatter.NewFormatterMiddleware(
slogformatter.PIIFormatter("user"), // 掩码 PII 字段
slogformatter.ErrorFormatter("error"), // 结构化错误信息
slogformatter.IPAddressFormatter("client"), // 掩码 IP 地址
)).Handler(slog.NewJSONHandler(os.Stdout, nil)),
)
关键格式化器:PIIFormatter, ErrorFormatter, TimeFormatter, UnixTimestampFormatter, IPAddressFormatter, HTTPRequestFormatter, HTTPResponseFormatter。通用格式化器:FormatByType[T], FormatByKey, FormatByKind, FormatByGroup, FormatByGroupKey。使用 FlattenFormatterMiddleware 展平嵌套属性。
HTTP 中间件
跨框架的一致模式:router.Use(slogXXX.New(logger))。
可用:slog-gin, slog-echo, slog-fiber, slog-chi, slog-http (net/http)。
所有共享一个 Config 结构体,包含:DefaultLevel, ClientErrorLevel, ServerErrorLevel, WithRequestBody, WithResponseBody, WithUserAgent, WithRequestID, WithTraceID, WithSpanID, Filters。
// Gin 带过滤器——跳过健康检查
router.Use(sloggin.NewWithConfig(logger, sloggin.Config{
DefaultLevel: slog.LevelInfo,
ClientErrorLevel: slog.LevelWarn,
ServerErrorLevel: slog.LevelError,
WithRequestBody: true,
Filters: []sloggin.Filter{
sloggin.IgnorePath("/health", "/metrics"),
},
}))
有关特定框架的设置,请参见 HTTP 中间件。
后端接收器
所有遵循 Option{}.NewXxxHandler() 构造函数模式。
| 类别 | 包 |
|---|---|
| 云 | slog-datadog, slog-sentry, slog-loki, slog-graylog |
| 消息 | slog-kafka, slog-fluentd, slog-logstash, slog-nats |
| 通知 | slog-slack, slog-telegram, slog-webhook |
| 存储 | slog-parquet |
| 桥接 | slog-zap, slog-zerolog, slog-logrus |
批处理处理器需要优雅关闭——slog-datadog, slog-loki, slog-kafka 和 slog-parquet 在内部缓冲记录。在关闭时刷新(例如,Datadog 的 handler.Stop(ctx),Loki 的 lokiClient.Stop(),Kafka 的 writer.Close()),否则缓冲的日志将丢失。
有关配置示例和关闭模式,请参见 后端处理器。
常见错误
| 错误 | 失败原因 | 修复 |
|---|---|---|
| 格式化后采样 | 浪费 CPU 格式化将被丢弃的记录 | 将采样作为最外层处理器 |
| Fanout 到多个同步处理器 | 阻塞调用者——延迟是所有处理器之和 | 使用 Pool() 进行并发分发 |
| 批处理处理器缺少关闭刷新 | 缓冲日志在关闭时丢失 | defer handler.Stop(ctx) (Datadog), defer lokiClient.Stop() (Loki), defer writer.Close() (Kafka) |
| 路由器没有默认/兜底处理器 | 未匹配的记录被静默丢弃 | 添加一个没有谓词的处理器作为兜底 |
没有 HTTP 中间件时使用 AttrFromContext |
上下文没有要提取的请求属性 | 先安装 slog-gin/echo/fiber/chi 中间件 |
使用没有中间件的 Pipe |
无操作包装器,增加每条记录的开销 | 如果不需要中间件,移除 Pipe() |
性能警告
- Fanout 延迟 = 所有处理器延迟之和(顺序)。如果有 5 个处理器,每个 10ms,每次日志调用花费 50ms。使用
Pool()减少到 max(latencies) - Pipe 中间件 增加每条记录的函数调用开销——保持链短(2-4 个中间件)
- slog-formatter 顺序处理属性——多个格式化器会叠加。对于热路径属性格式化,建议在你的类型上实现
slog.LogValuer代替 - 在生产部署前使用
go test -bench对你的管道进行基准测试
诊断: 测量管道的每条记录分配和延迟,并识别链中哪个处理器分配最多。
最佳实践
- 先采样,再格式化,最后路由——这种规范顺序最小化浪费的工作,并确保所有接收器看到干净的数据
- 使用 Pipe 处理横切关注点——跟踪 ID 注入和 PII 擦除属于中间件,而不是每个处理器的逻辑
- 使用
slogmulti.NewHandleInlineHandler测试管道——在没有真实接收器的情况下断言记录到达每个阶段 - 使用
AttrFromContext将请求范围的属性从 HTTP 中间件传播到所有处理器 - 当处理器需要不同的记录子集时,优先使用 Router 而不是 Fanout——Router 评估谓词并跳过不匹配的处理器
交叉引用
- → 参见
samber/cc-skills-golang@golang-observability技能了解 slog 基础知识(级别、上下文、处理器设置、迁移) - → 参见
samber/cc-skills-golang@golang-error-handling技能了解记录或返回规则 - → 参见
samber/cc-skills-golang@golang-security技能了解日志中的 PII 处理 - → 参见
samber/cc-skills-golang@golang-samber-oops技能了解使用samber/oops的结构化错误上下文
如果你在任何 samber/slog-* 包中遇到错误或意外行为,请在相关仓库提交 issue(例如,slog-multi/issues,slog-sampling/issues)。





