logging

package
v0.18.47 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: MIT Imports: 7 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 RequestIDFromContext

func RequestIDFromContext(ctx context.Context) string

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

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