# `instruments` _(no submodules)_ ## Purpose Lazily-bound OpenTelemetry instrument bundle for the Better-Auth adapter. Built once per process against the current global `MeterProvider` and cached. Tests call {@link resetBetterAuthInstruments} after installing a fresh `MeterProvider` so assertions only see the instruments emitted by the unit under test. ## Features - Four canonical instruments matching the spec's OTel surface contract: `auth.better_auth.sessions_resolved_total`, `auth.better_auth.session_resolve_duration_ms`, `auth.better_auth.oauth_flows_total`, `auth.better_auth.principal_mapping_errors_total`. - Singleton-per-process pattern so consumers can call `getBetterAuthInstruments()` from anywhere without worrying about meter proliferation. - Reset helper for test isolation. ## Usage: Basic ```ts import { getBetterAuthInstruments } from "@suaveplan/api-auth-better-auth/instruments"; const ins = getBetterAuthInstruments(); ins.sessionsResolvedTotal.add(1, { outcome: "resolved" }); ins.sessionResolveDurationMs.record(elapsedMs, { outcome: "resolved" }); ``` ## Usage: Advanced ```ts import { getBetterAuthInstruments, resetBetterAuthInstruments, } from "@suaveplan/api-auth-better-auth/instruments"; import { metrics } from "@opentelemetry/api"; import { MeterProvider } from "@opentelemetry/sdk-metrics"; // In test setup const provider = new MeterProvider({ /* reader, ... */ }); metrics.setGlobalMeterProvider(provider); resetBetterAuthInstruments(); // force the cache to rebind to the new provider // In test const ins = getBetterAuthInstruments(); ins.oauthFlowsTotal.add(1, { provider: "github", outcome: "state_mismatch" }); ``` ## API Reference | Export | Shape | Purpose | | ------ | ----- | ------- | | `BetterAuthInstruments` | interface | Bundle of `Counter` / `Histogram` instances | | `getBetterAuthInstruments()` | `() => BetterAuthInstruments` | Lazy cached accessor | | `resetBetterAuthInstruments()` | `() => void` | Drop the cache (tests only) | Instrument labels: | Instrument | Labels | Semantics | | --- | --- | --- | | `auth.better_auth.sessions_resolved_total` | `outcome ∈ "resolved" \| "null" \| "error"` | Session-resolver call count | | `auth.better_auth.session_resolve_duration_ms` | `outcome` (same) | Duration histogram | | `auth.better_auth.oauth_flows_total` | `provider`, `outcome ∈ "success" \| "state_mismatch" \| "provider_rejected"` | OAuth flow conclusion count | | `auth.better_auth.principal_mapping_errors_total` | none | Mapper-threw count | ## Implementation Notes The meter is acquired via `metrics.getMeter("@suaveplan/api-auth-better-auth")` to match the OpenTelemetry naming convention (instrument scope = package name). Caching is critical — calling `meter.createCounter(name, ...)` more than once for the same `name` produces a stable instrument under the OTel spec, but the SDK MAY emit a warning, and re-binding the cached objects on every `add()` call would generate measurable overhead. The reset helper exists purely for tests because the global `MeterProvider` IS the cache key that decides whether the cached instruments still point at the live provider.