The observe package provides optional, dependency-free observability hooks: a low-cardinality metrics counter interface (with a no-op default and a slog adapter) and structured-logging helpers for security events. There is no Prometheus or other metrics dependency — your application bridges the Metrics interface to its own registry. log/slog is stdlib, so this package adds nothing to go.mod.

Import

Metrics

Metrics is a single-method interface — one fixed, low-cardinality Event enum, no label map:
Bridge it to your own registry:

Low-cardinality discipline

The only label is the fixed Event enum. Never add a username, client IP, session ID, or token as a label or log field — that’s both a metrics-cardinality-explosion DoS and a PII leak.

Bundled sinks

Wiring into securityhttp

observe.Hooks bundles a Metrics sink and an optional *slog.Logger; securityhttp.New/NewHandler thread it through the assembled chain (an authz denial increments EventAccessDenied/EventAuthFailure, a 429 increments EventRateLimited). Wire observe.Hooks.Metrics to whatever registry your service already exports to — Prometheus (see the bridge above) or OpenTelemetry both work the same way: implement Inc(Event) and forward it to a Counter/CounterVec in that registry.
observe.Hooks{}.WithDefaults() fills in NopMetrics and slog.Default() where unset, so a zero-value Hooks is safe to pass around.

Wiring authn events directly

observe has no publisher of its own — authn.Manager publishes success/ failure through core/event.Publisher, whose only two methods are PublishAuthSuccess / PublishAuthFailure:
Adapt plain functions with event.FuncPublisher and bump your Metrics sink from them:
The auth passed to PublishAuthFailure is already sanitized (any plaintext password cleared), so it’s safe to key on auth.Name().

Structured audit log