Persona: You are a Go logging architect. You design log pipelines where every record flows through the right handlers — sampling drops noise early, formatters strip PII before records leave the process, and routers send errors to Sentry while info goes to Loki.
samber/slog-\\\\ — Structured Logging Pipeline for Go
20+ composable slog.Handler packages for Go 1.21+. Three core pipeline libraries plus HTTP middlewares and backend sinks that all implement the standard slog.Handler interface.
Official resources:
This skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform.
The Pipeline Model
Every samber/slog pipeline follows a canonical ordering. Records flow left to right — place sampling first to drop early and avoid wasting CPU on records that never reach a sink.
CODEBLOCK0
Order matters: sampling before formatting saves CPU. Formatting before routing ensures all sinks receive clean attributes. Reversing this wastes work on records that get dropped.
Core Libraries
| Library | Purpose | Key constructors |
|---|
| INLINECODE2 | Handler composition | INLINECODE3 , Router, FirstMatch, Failover, Pool, INLINECODE8 |
| INLINECODE9 |
Throughput control |
UniformSamplingOption,
ThresholdSamplingOption,
AbsoluteSamplingOption,
CustomSamplingOption |
|
slog-formatter | Attribute transforms |
PIIFormatter,
ErrorFormatter,
FormatByType[T],
FormatByKey,
FlattenFormatterMiddleware |
slog-multi — Handler Composition
Six composition patterns, each for a different routing need:
| Pattern | Behavior | Latency impact |
|---|
| INLINECODE20 | Broadcast to all handlers sequentially | Sum of all handler latencies |
| INLINECODE21 |
Route to ALL matching handlers | Sum of matching handlers |
|
Router().Add(...).FirstMatch().Handler() | Route to FIRST match only | Single handler latency |
|
Failover()(handlers...) | Try sequentially until one succeeds | Primary handler latency (happy path) |
|
Pool()(handlers...) | Concurrent broadcast to all handlers | Max of all handler latencies |
|
Pipe(middlewares...).Handler(sink) | Middleware chain before sink | Middleware overhead + sink |
CODEBLOCK1
Built-in predicates: LevelIs, LevelIsNot, MessageIs, MessageIsNot, MessageContains, MessageNotContains, AttrValueIs, AttrKindIs.
For full code examples of every pattern, see Pipeline Patterns.
slog-sampling — Throughput Control
| Strategy | Behavior | Best for |
|---|
| Uniform | Drop fixed % of all records | Dev/staging noise reduction |
| Threshold |
Log first N per interval, then sample at rate R | Production — preserves initial visibility |
| Absolute | Cap at N records per interval globally | Hard cost control |
| Custom | User function returns sample rate per record | Level-aware or time-aware rules |
Sampling MUST be the outermost handler in the pipeline — placing it after formatting wastes CPU on records that get dropped.
CODEBLOCK2
Matchers group similar records for deduplication: MatchByLevel(), MatchByMessage(), MatchByLevelAndMessage() (default), MatchBySource(), MatchByAttribute(groups, key).
For strategy comparison and configuration details, see Sampling Strategies.
slog-formatter — Attribute Transformation
Apply as a Pipe middleware so all downstream handlers receive clean attributes.
CODEBLOCK3
Key formatters: PIIFormatter, ErrorFormatter, TimeFormatter, UnixTimestampFormatter, IPAddressFormatter, HTTPRequestFormatter, HTTPResponseFormatter. Generic formatters: FormatByType[T], FormatByKey, FormatByKind, FormatByGroup, FormatByGroupKey. Flatten nested attributes with FlattenFormatterMiddleware.
HTTP Middlewares
Consistent pattern across frameworks: router.Use(slogXXX.New(logger)).
Available: slog-gin, slog-echo, slog-fiber, slog-chi, slog-http (net/http).
All share a Config struct with: DefaultLevel, ClientErrorLevel, ServerErrorLevel, WithRequestBody, WithResponseBody, WithUserAgent, WithRequestID, WithTraceID, WithSpanID, Filters.
CODEBLOCK4
For framework-specific setup, see HTTP Middlewares.
Backend Sinks
All follow the Option{}.NewXxxHandler() constructor pattern.
| Category | Packages |
|---|
| Cloud | INLINECODE71 , slog-sentry, slog-loki, INLINECODE74 |
| Messaging |
slog-kafka,
slog-fluentd,
slog-logstash,
slog-nats |
| Notification |
slog-slack,
slog-telegram,
slog-webhook |
| Storage |
slog-parquet |
| Bridges |
slog-zap,
slog-zerolog,
slog-logrus |
Batch handlers require graceful shutdown — slog-datadog, slog-loki, slog-kafka, and slog-parquet buffer records internally. Flush on shutdown (e.g., handler.Stop(ctx) for Datadog, lokiClient.Stop() for Loki, writer.Close() for Kafka) or buffered logs are lost.
For configuration examples and shutdown patterns, see Backend Handlers.
Common Mistakes
| Mistake | Why it fails | Fix |
|---|
| Sampling after formatting | Wastes CPU formatting records that get dropped | Place sampling as outermost handler |
| Fanout to many synchronous handlers |
Blocks caller — latency is sum of all handlers | Use
Pool() for concurrent dispatch |
| Missing shutdown flush on batch handlers | Buffered logs lost on shutdown |
defer handler.Stop(ctx) (Datadog),
defer lokiClient.Stop() (Loki),
defer writer.Close() (Kafka) |
| Router without default/catch-all handler | Unmatched records silently dropped | Add a handler with no predicate as catch-all |
|
AttrFromContext without HTTP middleware | Context has no request attributes to extract | Install
slog-gin/
echo/
fiber/
chi middleware first |
| Using
Pipe with no middleware | No-op wrapper adding per-record overhead | Remove
Pipe() if no middleware needed |
Performance Warnings
- - Fanout latency = sum of all handler latencies (sequential). With 5 handlers at 10ms each, every log call costs 50ms. Use
Pool() to reduce to max(latencies) - Pipe middleware adds per-record function call overhead — keep chains short (2-4 middlewares)
- slog-formatter processes attributes sequentially — many formatters compound. For hot-path attribute formatting, prefer implementing
slog.LogValuer on your types instead - Benchmark your pipeline with
go test -bench before production deployment
Diagnose: measure per-record allocation and latency of your pipeline and identify which handler in the chain allocates most.
Best Practices
- 1. Sample first, format second, route last — this canonical ordering minimizes wasted work and ensures all sinks see clean data
- Use Pipe for cross-cutting concerns — trace ID injection and PII scrubbing belong in middleware, not per-handler logic
- Test pipelines with
slogmulti.NewHandleInlineHandler — assert on records reaching each stage without real sinks - Use
AttrFromContext to propagate request-scoped attributes from HTTP middleware to all handlers - Prefer Router over Fanout when handlers need different record subsets — Router evaluates predicates and skips non-matching handlers
Cross-References
- - → See
samber/cc-skills-golang@golang-observability skill for slog fundamentals (levels, context, handler setup, migration) - → See
samber/cc-skills-golang@golang-error-handling skill for the log-or-return rule - → See
samber/cc-skills-golang@golang-security skill for PII handling in logs - → See
samber/cc-skills-golang@golang-samber-oops skill for structured error context with INLINECODE113
If you encounter a bug or unexpected behavior in any samber/slog-\* package, open an issue at the relevant repository (e.g., slog-multi/issues, slog-sampling/issues).
角色定位: 你是一位 Go 语言日志架构师。你设计的日志管道中,每条记录都能流经正确的处理器——采样环节提前丢弃噪声,格式化器在记录离开进程前剥离 PII,路由器将错误发送至 Sentry,而信息日志则流向 Loki。
samber/slog-\\\\ — Go 结构化日志管道
20+ 个可组合的 slog.Handler 包,适用于 Go 1.21+。包含三个核心管道库,以及 HTTP 中间件和后端接收器,均实现了标准 slog.Handler 接口。
官方资源:
本技能并非详尽无遗。更多信息请参考库文档和代码示例。Context7 可作为发现平台提供帮助。
管道模型
每个 samber/slog 管道都遵循一个规范的顺序。记录从左向右流动——首先放置采样环节以提前丢弃记录,避免在永远不会到达接收器的记录上浪费 CPU。
记录 → [采样] → [管道:追踪/PII] → [路由器] → [接收器]
顺序很重要:在格式化之前采样可以节省 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) | 接收器前的中间件链 | 中间件开销 + 接收器 |
go
// 将错误路由到 Sentry,所有日志输出到标准输出
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。
go
// 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 中间件应用,以便所有下游处理器都能接收到干净的属性。
go
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。
go
// 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 | 上下文中没有可