---
id: daily-golang-samber-slog
name: "golang-samber-slog"
url: https://skills.yangsir.net/skill/daily-golang-samber-slog
author: samber
domain: ai-system-observability-sre
tags: ["logging", "observability", "security", "data-privacy", "backend-development"]
install_count: 2500
rating: 4.30 (34 reviews)
github: https://github.com/samber/cc-skills-golang
---

# golang-samber-slog

> Go 结构化日志架构设计，自动配置采样、敏感信息脱敏和路由分发，错误日志发送至 Sentry，信息日志存入 Loki

**Stats**: 2,500 installs · 4.3/5 (34 reviews)

## Before / After 对比

### 日志管道配置

**Before**:

手动配置每个日志级别和输出目标，容易遗漏敏感信息脱敏导致泄露，需要多次调整采样率和路由规则，配置一次需要 2 小时

**After**:

声明式定义日志处理管道，自动应用脱敏规则和智能路由，采样策略根据日志量自动调整，15 分钟完成生产级配置

| Metric | Before | After | Change |
|---|---|---|---|
| 配置时间 | 120分钟 | 15分钟 | -87% |
| 敏感信息泄露率 | 15% | 0% | -100% |

## Readme

# golang-samber-slog

**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:**

- [github.com/samber/slog-multi](https://github.com/samber/slog-multi) — handler composition

- [github.com/samber/slog-sampling](https://github.com/samber/slog-sampling) — throughput control

- [github.com/samber/slog-formatter](https://github.com/samber/slog-formatter) — attribute transformation

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.

```
record → [Sampling] → [Pipe: trace/PII] → [Router] → [Sinks]

```

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

`slog-multi`
Handler composition
`Fanout`, `Router`, `FirstMatch`, `Failover`, `Pool`, `Pipe`

`slog-sampling`
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

`Fanout(handlers...)`
Broadcast to all handlers sequentially
Sum of all handler latencies

`Router().Add(h, predicate).Handler()`
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

```
// 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(),
)

```

Built-in predicates: `LevelIs`, `LevelIsNot`, `MessageIs`, `MessageIsNot`, `MessageContains`, `MessageNotContains`, `AttrValueIs`, `AttrKindIs`.

For full code examples of every pattern, see [Pipeline Patterns](https://github.com/samber/cc-skills-golang/blob/HEAD/skills/golang-samber-slog/references/pipeline-patterns.md).

## 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.

```
// 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),
)

```

Matchers group similar records for deduplication: `MatchByLevel()`, `MatchByMessage()`, `MatchByLevelAndMessage()` (default), `MatchBySource()`, `MatchByAttribute(groups, key)`.

For strategy comparison and configuration details, see [Sampling Strategies](https://github.com/samber/cc-skills-golang/blob/HEAD/skills/golang-samber-slog/references/sampling-strategies.md).

## slog-formatter — Attribute Transformation

Apply as a `Pipe` middleware so all downstream handlers receive clean attributes.

```
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)),
)

```

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`.

```
// 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"),
    },
}))

```

For framework-specific setup, see [HTTP Middlewares](https://github.com/samber/cc-skills-golang/blob/HEAD/skills/golang-samber-slog/references/http-middlewares.md).

## Backend Sinks

All follow the `Option{}.NewXxxHandler()` constructor pattern.

Category
Packages

Cloud
`slog-datadog`, `slog-sentry`, `slog-loki`, `slog-graylog`

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](https://github.com/samber/cc-skills-golang/blob/HEAD/skills/golang-samber-slog/references/backend-handlers.md).

## 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

- **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 `samber/oops`

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](https://github.com/samber/slog-multi/issues), [slog-sampling/issues](https://github.com/samber/slog-sampling/issues)).
Weekly Installs665Repository[samber/cc-skills-golang](https://github.com/samber/cc-skills-golang)GitHub Stars1.1KFirst SeenMar 22, 2026Security Audits[Gen Agent Trust HubPass](/samber/cc-skills-golang/golang-samber-slog/security/agent-trust-hub)[SocketPass](/samber/cc-skills-golang/golang-samber-slog/security/socket)[SnykPass](/samber/cc-skills-golang/golang-samber-slog/security/snyk)Installed onopencode648cursor641codex639gemini-cli637github-copilot636amp635

---
*Source: https://skills.yangsir.net/skill/daily-golang-samber-slog*
*Markdown mirror: https://skills.yangsir.net/api/skill/daily-golang-samber-slog/markdown*