Skillshub golang-samber-slog

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.

install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/Harmeet10000/skills/golang-samber-slog" ~/.claude/skills/comeonoliver-skillshub-golang-samber-slog && rm -rf "$T"
manifest: skills/Harmeet10000/skills/golang-samber-slog/SKILL.md
source content

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

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

PatternBehaviorLatency impact
Fanout(handlers...)
Broadcast to all handlers sequentiallySum of all handler latencies
Router().Add(h, predicate).Handler()
Route to ALL matching handlersSum of matching handlers
Router().Add(...).FirstMatch().Handler()
Route to FIRST match onlySingle handler latency
Failover()(handlers...)
Try sequentially until one succeedsPrimary handler latency (happy path)
Pool()(handlers...)
Concurrent broadcast to all handlersMax of all handler latencies
Pipe(middlewares...).Handler(sink)
Middleware chain before sinkMiddleware 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

StrategyBehaviorBest for
UniformDrop fixed % of all recordsDev/staging noise reduction
ThresholdLog first N per interval, then sample at rate RProduction — preserves initial visibility
AbsoluteCap at N records per interval globallyHard cost control
CustomUser function returns sample rate per recordLevel-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.

CategoryPackages
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

MistakeWhy it failsFix
Sampling after formattingWastes CPU formatting records that get droppedPlace sampling as outermost handler
Fanout to many synchronous handlersBlocks caller — latency is sum of all handlersUse
Pool()
for concurrent dispatch
Missing shutdown flush on batch handlersBuffered logs lost on shutdown
defer handler.Stop(ctx)
(Datadog),
defer lokiClient.Stop()
(Loki),
defer writer.Close()
(Kafka)
Router without default/catch-all handlerUnmatched records silently droppedAdd a handler with no predicate as catch-all
AttrFromContext
without HTTP middleware
Context has no request attributes to extractInstall
slog-gin
/
echo
/
fiber
/
chi
middleware first
Using
Pipe
with no middleware
No-op wrapper adding per-record overheadRemove
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
  2. Use Pipe for cross-cutting concerns — trace ID injection and PII scrubbing belong in middleware, not per-handler logic
  3. Test pipelines with
    slogmulti.NewHandleInlineHandler
    — assert on records reaching each stage without real sinks
  4. Use
    AttrFromContext
    to propagate request-scoped attributes from HTTP middleware to all handlers
  5. 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, slog-sampling/issues).