cxuu/golang-skills

go-logging

Use when choosing a logging approach, configuring slog, writing structured log statements, or deciding log levels in Go.

Quelltext ansehen
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

Go Logging

Compatibility: log/slog requires Go 1.21+; testing/slogtest requires Go 1.22+.

Resource Routing

  • references/LEVELS-AND-CONTEXT.md - Read when choosing log levels, deciding logger-in-context versus explicit parameters, or excluding sensitive fields.
  • references/LOGGING-PATTERNS.md - Read when configuring slog handlers, logging HTTP requests, testing handlers, or migrating from log.Printf.

Core Principle

Logs are for operators, not developers. Every log line should help someone diagnose a production issue. If it doesn't serve that purpose, it's noise.


Choosing a Logger

Normative: Use log/slog for new Go code.

slog is structured, leveled, and in the standard library (Go 1.21+). It covers the vast majority of production logging needs.

Which logger?
├─ New production code      → log/slog
├─ Trivial CLI / one-off    → log (standard)
└─ Measured perf bottleneck → zerolog or zap (benchmark first)

Do not introduce a third-party logging library unless profiling shows slog is a bottleneck in your hot path. When you do, keep the same structured key-value style.


Structured Logging

Normative: Always use key-value pairs. Never interpolate values into the message string.

The message is a static description of what happened. Dynamic data goes in key-value attributes:

go
// Good: static message, structured fields
slog.Info("order placed", "order_id", orderID, "total", total)

// Bad: dynamic data baked into the message string
slog.Info(fmt.Sprintf("order %d placed for $%.2f", orderID, total))

Key Naming

Advisory: Use snake_case for log attribute keys.

Keys should be lowercase, underscore-separated, and consistent across the codebase: user_id, request_id, elapsed_ms.

Typed Attributes

For performance-critical paths, use typed constructors to avoid allocations:

go
slog.LogAttrs(ctx, slog.LevelInfo, "request handled",
    slog.String("method", r.Method),
    slog.Int("status", code),
    slog.Duration("elapsed", elapsed),
)

Log Levels

Advisory: Follow these level semantics consistently.
LevelWhen to useProduction default
DebugDeveloper-only diagnostics, tracing internal stateDisabled
InfoNotable lifecycle events: startup, shutdown, config loadedEnabled
WarnUnexpected but recoverable: deprecated feature used, retry succeededEnabled
ErrorOperation failed, requires operator attentionEnabled

Rules of thumb:

  • If nobody should act on it, it's not Error — use Warn or Info
  • If it's only useful with a debugger attached, it's Debug
  • slog.Error should always include an "err" attribute
go
slog.Error("payment failed", "err", err, "order_id", id)
slog.Warn("retry succeeded", "attempt", n, "endpoint", url)
slog.Info("server started", "addr", addr)
slog.Debug("cache lookup", "key", key, "hit", hit)

Request-Scoped Logging

Advisory: Derive loggers from context to carry request-scoped fields.

Use middleware to enrich a logger with request ID, user ID, or trace ID, then pass the enriched logger downstream via context or as an explicit parameter. Keep the full context-key and middleware implementation in the logging patterns reference so request-scoped logging has one owner.


Log or Return, Not Both

The handle-once rule belongs to go-error-handling. In logging work, apply it by choosing either a local log-and-recover path or a return path with context, not both for the same error.

Exception: HTTP handlers and other top-of-stack boundaries may log detailed errors server-side while returning a sanitized message to the client:

go
if err != nil {
    slog.Error("checkout failed", "err", err, "user_id", uid)
    http.Error(w, "internal error", http.StatusInternalServerError)
    return
}

See go-error-handling for the full handle-once pattern and error wrapping guidance.


What NOT to Log

Normative: Never log secrets, credentials, PII, or high-cardinality unbounded data.
  • Passwords, API keys, tokens, session IDs
  • Full credit card numbers, SSNs
  • Request/response bodies that may contain user data
  • Entire slices or maps of unbounded size

Quick Reference

DoDon't
slog.Info("msg", "key", val)log.Printf("msg %v", val)
Static message + structured fieldsfmt.Sprintf in message
snake_case keyscamelCase or inconsistent keys
Log OR return errorsLog AND return the same error
Derive logger from contextCreate a new logger per call
Use slog.Error with "err" attrslog.Info for errors
Pre-check Enabled() on hot pathsAlways allocate log args

Related Skills

  • Error handling: See go-error-handling when deciding whether to log or return an error, or for the handle-once pattern
  • Context propagation: See go-context when passing request-scoped values (including loggers) through context
  • Performance: See go-performance when optimizing hot-path logging or reducing allocations in log calls
  • Code review: See go-code-review when reviewing logging practices in Go PRs
aus demselben Repository

Weitere Skills

Alle Skills
cxuu
Community

go-context

Use when working with context.Context in Go — placement in signatures, propagating cancellation and deadlines, and storing values in context vs parameters. Also use when cancelling long-running operations, setting timeouts, or passing request-scoped data, even if they don't mention context.Context directly. Does not cover goroutine lifecycle or sync primitives (see go-concurrency).

Installationen
2
GitHub Stars
165
Aktualisiert
20. Juni
cxuu
Community

go-defensive

Use when hardening Go code at API boundaries — copying slices/maps, verifying interface compliance, using defer for cleanup, time.Time/time.Duration, or avoiding mutable globals. Also use when reviewing for robustness concerns like missing cleanup or unsafe crypto usage, even if the user doesn't mention "defensive programming." Does not cover error handling strategy (see go-error-handling).

Installationen
2
GitHub Stars
165
Aktualisiert
20. Juni
cxuu
Community

go-functions

Use when organizing functions within a Go file, formatting function signatures, designing return values, or following Printf-style naming conventions. Also use when a user is adding or refactoring any Go function, even if they don't mention function design or signature formatting. Does not cover functional options constructors (see go-functional-options).

Installationen
2
GitHub Stars
165
Aktualisiert
20. Juni
cxuu
Community

go-naming

Use when naming any Go identifier — packages, types, functions, methods, variables, constants, or receivers — to ensure idiomatic, clear names. Also use when a user is creating new types, packages, or exported APIs, even if they don't explicitly ask about naming conventions. Does not cover package organization (see go-packages).

Installationen
2
GitHub Stars
165
Aktualisiert
20. Juni