Help us shape the future of Go! Take the 2026 Go Developer Survey

logging

package
v0.36.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package logging provides a context-aware slog handler and helpers for stamping per-request fields (request_id, user_id, vehicle_id, trace_id) onto every log line emitted while serving a request, without requiring callers to thread the logger through.

Mechanism: ContextHandler wraps any underlying slog.Handler and on every Handle() pulls registered values out of context.Context. The fields are added as top-level attributes on the record, so the existing slog.JSONHandler output gains them transparently.

HTTP middleware sets request_id (from chi) and is followed by the auth middleware (user_id) and vehicle-ownership middleware (vehicle_id). Background goroutines pass nil/Background context and simply emit log lines without those fields — no harm.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AccessLog

func AccessLog(r *http.Request, ww middleware.WrapResponseWriter, dur time.Duration, uid uuid.UUID)

AccessLog emits one structured slog.Info line summarising an HTTP request. Split out from HTTPMiddleware so tests (and future adapters) can call it directly. Suppresses noisy paths that would otherwise dominate Loki: health probes (every readiness tick) and the live websocket upgrade (one line per packet would be insane).

uid is the user_id resolved by auth middleware during the request, passed in explicitly because middleware-chain context updates don't propagate back to this outer scope. uuid.Nil = pre-auth or unauthenticated request; we skip the field rather than emit "user_id": "00000000-..." which would muddy Loki filters.

func HTTPMiddleware

func HTTPMiddleware(next http.Handler) http.Handler

HTTPMiddleware extracts chi's RequestID into the context (so ContextHandler can stamp it on every log line emitted while the handler runs), then emits a single structured access-log entry when the request finishes.

Place this AFTER chi's middleware.RequestID and middleware.RealIP, but BEFORE middleware.Recoverer so panics still get a log line.

func IDHash added in v0.33.0

func IDHash(s string) string

IDHash returns a short salted hash standing in for an identifier (email, username) in log lines.

func ImpersonatorIDFromContext added in v0.26.0

func ImpersonatorIDFromContext(ctx context.Context) uuid.UUID

ImpersonatorIDFromContext returns the real admin identity behind an impersonated request, or uuid.Nil when the request isn't impersonated.

func RequestIDFromContext

func RequestIDFromContext(ctx context.Context) string

RequestIDFromContext returns the request ID, or "" if unset.

func ScrubEmails added in v0.33.0

func ScrubEmails(s string) string

ScrubEmails masks anything email-shaped (plain or URL-encoded) in third-party text before it's logged. Use for error strings from databases, IdPs and HTTP clients, which can echo the identifier.

func ScrubErr added in v0.33.0

func ScrubErr(err error) string

ScrubErr is ScrubEmails over err.Error(); empty for nil.

func TargetIDFromContext added in v0.26.0

func TargetIDFromContext(ctx context.Context) uuid.UUID

TargetIDFromContext returns the user being viewed via impersonation, or uuid.Nil when the request isn't impersonated.

func TraceIDFromContext

func TraceIDFromContext(ctx context.Context) string

TraceIDFromContext returns the trace ID, or "" if unset.

func UserIDFromContext

func UserIDFromContext(ctx context.Context) uuid.UUID

UserIDFromContext returns the user ID, or uuid.Nil if unset.

func VehicleIDFromContext

func VehicleIDFromContext(ctx context.Context) string

VehicleIDFromContext returns the vehicle ID, or "" if unset.

func WithImpersonation added in v0.26.0

func WithImpersonation(ctx context.Context, impersonatorID, targetID uuid.UUID) context.Context

WithImpersonation stamps both the admin's real user id (impersonatorID) and the user being viewed (targetID) onto the context so every log line emitted for the rest of the request carries both — the request's plain user_id field (set separately by auth.WithUser as part of the identity swap) shows *whose data* was read, while these two fields preserve *who actually made the call*. A no-op when either id is uuid.Nil, so a half-built impersonation context never emits a misleading single field.

func WithRequestID

func WithRequestID(ctx context.Context, id string) context.Context

WithRequestID returns a context that carries the given request ID. Empty values are not stored (avoids polluting logs with empty keys).

func WithTraceID

func WithTraceID(ctx context.Context, tid string) context.Context

WithTraceID returns a context that carries the given trace ID. Reserved for OpenTelemetry wire-up later; currently nothing sets it but ContextHandler will surface it whenever it appears.

func WithUserID

func WithUserID(ctx context.Context, uid uuid.UUID) context.Context

WithUserID returns a context that carries the given user UUID. uuid.Nil is treated as unset. Also writes into the userIDSink holder if HTTPMiddleware installed one — this lets the outer access-log line see a user_id stamped by an inner middleware, even though context updates don't propagate up the chain.

func WithVehicleID

func WithVehicleID(ctx context.Context, vid string) context.Context

WithVehicleID returns a context that carries the given Rivian vehicle ID. Empty values are not stored.

Types

type ContextHandler

type ContextHandler struct {
	// contains filtered or unexported fields
}

ContextHandler is a slog.Handler that decorates each record with request-scoped fields pulled from context.Context. It delegates formatting and IO to an inner handler.

func NewContextHandler

func NewContextHandler(inner slog.Handler) *ContextHandler

NewContextHandler wraps the given handler. Pass slog.NewJSONHandler or slog.NewTextHandler as inner depending on RIVOLT_LOG_FORMAT.

func (*ContextHandler) Enabled

func (h *ContextHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled defers to the inner handler.

func (*ContextHandler) Handle

func (h *ContextHandler) Handle(ctx context.Context, r slog.Record) error

Handle decorates the record with context-scoped attributes and then delegates to the inner handler.

func (*ContextHandler) WithAttrs

func (h *ContextHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new ContextHandler whose inner handler has the given attrs pre-applied.

func (*ContextHandler) WithGroup

func (h *ContextHandler) WithGroup(name string) slog.Handler

WithGroup returns a new ContextHandler whose inner handler is in the given group. Note: context-derived attrs are still emitted at the record's top level, not under the group — request_id and friends should always be addressable by exact key in Loki/Grafana regardless of how nested the call site is.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL