Structured Logging in Go with log/slog

A
Author
23 Apr, 2026 1 min read 968 views

Plain text logs are hard to search at scale. Structured logs attach key-value fields to each message, so you can filter by user_id or status in your log platform. Go's standard library includes log/slog for this.

Getting started

import (
    "log/slog"
    "os"
)

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
    slog.SetDefault(logger)

    slog.Info("server started", "port", 8080, "env", "production")
    slog.Warn("slow query", "duration_ms", 1240, "table", "orders")
    slog.Error("payment failed", "order_id", 42, "err", err)
}
{"time":"2026-10-11T09:30:00Z","level":"INFO","msg":"server started","port":8080,"env":"production"}

Use slog.NewTextHandler for readable output during local development.

Typed attributes and groups

slog.Info("order placed",
    slog.Int("order_id", 42),
    slog.Group("customer", slog.String("id", "c_9"), slog.String("plan", "pro")),
)

Child loggers carry context

func withRequestLogger(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        reqID := r.Header.Get("X-Request-ID")
        if reqID == "" {
            reqID = newID()
        }
        logger := slog.Default().With("request_id", reqID, "path", r.URL.Path)
        ctx := context.WithValue(r.Context(), loggerKey{}, logger)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Every line logged with that logger includes the request ID, so you can follow one request through your logs.

Good logging habits

  • Use consistent, lowercase snake_case keys across services.
  • Log at boundaries (incoming requests, outgoing calls, errors), not every function.
  • Never log secrets, tokens or full card numbers.
  • Make the level configurable so you can turn on debug logs without a redeploy.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.