golang-samber-slog

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-* 包的项目。

2261Star
150Fork
更新于 2026/6/6
SKILL.md
只读
名称
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-* 包的项目。

角色: 你是一位 Go 日志架构师。你设计的日志管道中,每条记录都流经正确的处理器——采样在早期丢弃噪声,格式化器在记录离开进程前剥离 PII,路由器将错误发送到 Sentry 而信息发送到 Loki。

samber/slog-**** — Go 结构化日志管道

20 多个可组合的 slog.Handler 包,适用于 Go 1.21+。三个核心管道库以及 HTTP 中间件和后端接收器,均实现标准 slog.Handler 接口。

官方资源:

此技能并非详尽无遗。请参考库文档和代码示例以获取更多信息。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-kafkaslog-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 对你的管道进行基准测试

诊断: 测量管道的每条记录分配和延迟,并识别链中哪个处理器分配最多。

最佳实践

  1. 先采样,再格式化,最后路由——这种规范顺序最小化浪费的工作,并确保所有接收器看到干净的数据
  2. 使用 Pipe 处理横切关注点——跟踪 ID 注入和 PII 擦除属于中间件,而不是每个处理器的逻辑
  3. 使用 slogmulti.NewHandleInlineHandler 测试管道——在没有真实接收器的情况下断言记录到达每个阶段
  4. 使用 AttrFromContext 将请求范围的属性从 HTTP 中间件传播到所有处理器
  5. 当处理器需要不同的记录子集时,优先使用 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/issuesslog-sampling/issues)。