golang-samber-slog
samber/cc-skills-golang
Composable structured logging pipelines for Go using samber/slog handlers — sampling, formatting, routing, and backend sinks.
What is golang-samber-slog?
A collection of 20+ slog.Handler packages for Go 1.21+ that enable building production logging pipelines with sampling, PII masking, multi-handler routing, and integration with backends like Datadog, Sentry, Loki, and Kafka. Use this when adopting slog or extending existing samber/slog-* packages in your codebase.
- Compose multi-handler pipelines with Fanout, Router, FirstMatch, Failover, Pool, and Pipe patterns
- Control log throughput with uniform, threshold, absolute, and custom sampling strategies
- Transform attributes via PII masking, error formatting, IP masking, and flattening
- Route logs conditionally by level, message, or attribute using built-in and custom predicates
- Integrate HTTP middleware for Gin, Echo, Fiber, Chi, and net/http frameworks
- Send logs to 20+ backends: Datadog, Sentry, Loki, Syslog, Logstash, Graylog, Kafka, Slack, Telegram, and more
How to install golang-samber-slog
npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-slog- Go 1.21 or later
- Existing project using slog or planning to adopt it
How to use golang-samber-slog
- 1.Import the core libraries: slog-multi for composition, slog-sampling for throughput, slog-formatter for transforms
- 2.Design your pipeline order: place sampling first (outermost) to drop records early, then formatting, then routing to sinks
- 3.Use Pipe() to chain middlewares (sampling, formatting) before passing to a Router or Fanout handler
- 4.Configure Router predicates (LevelIs, MessageContains, AttrValueIs) to route records to appropriate backends
- 5.Add HTTP middleware to your framework (router.Use(sloggin.New(logger))) with optional Config for filtering
- 6.Test the pipeline with sample records to verify sampling rates, attribute masking, and sink delivery
Use cases
- Build a production pipeline that routes errors to Sentry while sending all logs to Loki, with sampling to reduce noise
- Mask PII fields before logs leave the process using PIIFormatter in a Pipe middleware
- Implement threshold sampling to log the first 10 records per interval, then sample at 10% to balance visibility and cost
- Add structured HTTP request/response logging to a Gin or Echo API with configurable filters for health checks
- Load-balance log writes across multiple backends using Pool to distribute per-record
- Go backend engineers building production logging systems
- DevOps teams managing multi-sink log aggregation pipelines
- Teams adopting Go 1.21+ slog and needing extensibility beyond stdlib
- Organizations requiring PII masking and compliance-aware logging
golang-samber-slog FAQ
Sampling must be outermost to drop records before wasting CPU on formatting. Formatting should precede routing so all sinks receive clean attributes. Reversing this order wastes work on records that get dropped.
Use Fanout for broadcasting to all handlers, Router for conditional routing, FirstMatch for single-handler routing, Failover for fallback chains, Pool for load-balancing, and Pipe for middleware chains before a sink.
Apply slogformatter.PIIFormatter as a Pipe middleware wrapping your sink handler. This ensures all downstream handlers receive clean attributes without PII.
Yes. Use Router().Add(handler, predicate) to route to multiple backends conditionally, or Fanout(handlers...) to broadcast to all backends sequentially.
Threshold sampling is recommended: log the first N records per interval, then sample at rate R. This preserves initial visibility of new issues while capping cost.
Full instructions (SKILL.md)
Source of truth, from samber/cc-skills-golang.
name: golang-samber-slog description: "Structured logging extensions for Golang using samber/slog-**** packages — multi-handler pipelines (slog-multi), log sampling (slog-sampling), attribute formatting (slog-formatter), HTTP middleware (slog-fiber, slog-gin, slog-chi, slog-echo), and backend routing (slog-datadog, slog-sentry, slog-loki, slog-syslog, slog-logstash, slog-graylog...). Apply when using or adopting slog, or when the codebase already imports any github.com/samber/slog-* package." user-invocable: true license: MIT compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang. metadata: author: samber version: "1.1.2" openclaw: emoji: "🪵" homepage: https://github.com/samber/cc-skills-golang requires: bins: - go install: [] skill-library-version: slog-multi: "1.8.0" slog-sampling: "1.6.0" slog-formatter: "1.3.0" slog-fiber: "1.22.1" slog-gin: "1.21.0" slog-chi: "1.19.0" slog-echo: "1.21.0" slog-http: "1.12.0" slog-betterstack: "1.4.4" slog-channel: "1.4.4" slog-datadog: "2.10.4" slog-sentry: "2.10.3" slog-loki: "3.7.2" slog-syslog: "2.5.4" slog-logstash: "2.6.4" slog-graylog: "2.7.5" slog-fluentd: "2.5.4" slog-kafka: "2.6.5" slog-logrus: "2.5.4" slog-zap: "2.6.4" slog-zerolog: "2.9.2" slog-slack: "2.7.5" slog-telegram: "2.4.4" slog-webhook: "2.8.4" slog-mattermost: "2.5.4" slog-microsoft-teams: "2.7.4" slog-nats: "0.4.5" slog-otel: "0.1.0" slog-parquet: "2.5.2" slog-quickwit: "0.3.4" slog-rollbar: "2.7.4" slog-mock: "0.1.0" allowed-tools: Read Edit Write Glob Grep Bash(go:) Bash(golangci-lint:) Bash(git:) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs AskUserQuestion Bash(godig:) Bash(gopls:) LSP mcp__gopls__ paths:
- "**/*.go"
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 — handler composition
- github.com/samber/slog-sampling — throughput control
- github.com/samber/slog-formatter — attribute transformation
This skill is not exhaustive — refer to library documentation and code examples for more information:
- For Go package docs, symbols, versions, importers, and known vulnerabilities, → See
samber/cc-skills-golang@golang-pkg-go-devskill (godig), preferred over Context7 for Go package facts. - To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See
samber/cc-skills-golang@golang-goplsskill (gopls). - Context7 remains a fallback for docs not indexed on pkg.go.dev.
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...) | Load-balance: sends each record to ONE handler | Single handler latency |
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.
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.
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.
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.
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.LogValueron your types instead - Benchmark your pipeline with
go test -benchbefore 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
AttrFromContextto 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-observabilityskill for slog fundamentals (levels, context, handler setup, migration) - → See
samber/cc-skills-golang@golang-error-handlingskill for the log-or-return rule - → See
samber/cc-skills-golang@golang-securityskill for PII handling in logs - → See
samber/cc-skills-golang@golang-samber-oopsskill for structured error context withsamber/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, slog-sampling/issues).
Related skills
More from samber/cc-skills-golang and the wider catalog.

golang-security
Security best practices and vulnerability prevention for Go: injection, cryptography, secrets, threat modeling, and SAST tooling.

golang-spf13-cobra
Golang CLI command tree library with subcommands, flags, validation, completions, and doc generation.

golang-spf13-viper
Layered configuration resolution for Go: flags, env vars, files, and defaults in fixed precedence order.

golang-stay-updated
Curated guide to official Go sources, newsletters, communities, influential developers, and blogs for staying current with the Go ecosystem.

golang-stretchr-testify
Comprehensive guide to stretchr/testify for readable assertions, mocks, and test suites in Go.

golang-structs-interfaces
Go struct and interface design patterns — composition, embedding, type assertions, and dependency injection.