mcpField
G
golang-samber-slog

golang-samber-slog

github.com/samber开发3.7k38.7k 次安装5 天前更新
代码仓库

关于 golang-samber-slog

介绍 samber/slog 系列 Go 包的技能,使用标准 slog.Handler 接口构建结构化日志管道。涵盖处理器组合、采样、属性格式化、HTTP 中间件和后端接收器。

主要功能

  1. 01可组合的 slog 处理器
  2. 02路由、广播、故障转移与负载分配
  3. 03控制日志量的采样策略
  4. 04属性格式化与 PII 遮蔽
  5. 05HTTP 中间件和后端接收器

适用场景

  1. 01将错误日志路由到指定处理器
  2. 02通过采样减少重复日志
  3. 03导出前移除敏感属性
  4. 04为 HTTP 日志添加请求数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-slog

安装后在 Claude Code 中输入/golang-samber-slog确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
backend-handlers.md
http-middlewares.md
pipeline-patterns.md
sampling-strategies.md

详细介绍

**角色:**你是一名 Go 日志架构师。你设计的日志管道会让每条记录都流经合适的处理器——采样会尽早丢弃噪声,格式化器会在记录离开进程前剥离个人身份信息(PII),路由器则会将错误发送到 Sentry,并将信息级日志发送到 Loki。

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

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

官方资源:

本技能并未涵盖所有内容——更多信息请参阅库文档和代码示例:

  • 如需 Go 包文档、符号、版本、导入方和已知漏洞信息,→ 请参阅 samber/cc-skills-golang@golang-pkg-go-dev 技能(godig);查询 Go 包信息时优先于 Context7。
  • 如需在自己的代码中查看此库的用法(定义、调用点、诊断信息),→ 请参阅 samber/cc-skills-golang@golang-gopls 技能(gopls)。
  • 对于未被 pkg.go.dev 收录的文档,Context7 仍可作为备用方案。

管道模型

每个 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)在接收器之前执行中间件链中间件开销 + 接收器开销
// Route errors to Sentry, all logs to 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用户函数按记录返回采样率基于级别或时间的规则

采样 MUST 是管道中最外层的处理器——如果将其放在格式化之后,会浪费 CPU 来处理最终被丢弃的记录。

// Threshold: log first 10 per 5s, then 10% — errors always pass through via 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"),          // mask PII fields
        slogformatter.ErrorFormatter("error"),       // structured error info
        slogformatter.IPAddressFormatter("client"),  // mask IP addresses
    )).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 with filters — skip health checks
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将采样器置于最外层处理器
扇出到多个同步处理器会阻塞调用方——延迟是所有处理器延迟之和使用 Pool() 并发分发
批处理器关闭时未刷新缓冲区关闭时缓冲的日志会丢失使用 defer handler.Stop(ctx)(Datadog)、defer lokiClient.Stop()(Loki)、defer writer.Close()(Kafka)
路由器没有默认/兜底处理器未匹配的记录会被静默丢弃添加一个没有谓词的处理器作为兜底
使用 AttrFromContext,但未配置 HTTP 中间件上下文中没有可提取的请求属性先安装 slog-gin/echo/fiber/chi 中间件
使用 Pipe,但没有中间件空操作包装器会增加每条记录的开销如果不需要中间件,则移除 Pipe()

性能警告

  • Fanout 延迟 = 所有处理器延迟之和(顺序执行)。有 5 个处理器且每个耗时 10ms 时,每次日志调用都会耗时 50ms。使用 Pool() 将其降低至最大延迟
  • 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 会评估谓词并跳过不匹配的处理器

交叉引用

  • → 关于 slog 基础知识(级别、上下文、处理器设置、迁移),请参阅 samber/cc-skills-golang@golang-observability 技能
  • → 关于日志记录或返回规则,请参阅 samber/cc-skills-golang@golang-error-handling 技能
  • → 关于日志中的 PII 处理,请参阅 samber/cc-skills-golang@golang-security 技能
  • → 关于使用 samber/oops 提供结构化错误上下文,请参阅 samber/cc-skills-golang@golang-samber-oops 技能

如果你在任何 samber/slog-* 包中遇到错误或意外行为,请在相应的代码仓库中提交 issue(例如,slog-multi/issues、slog-sampling/issues)。

评论

支持 Markdown