Files
skills/docs/ui/react/react-auth/src/observability/react-auth-metrics.md
2026-05-29 08:20:56 +01:00

3.6 KiB

react-auth-metrics

(no submodules)

Purpose

react-auth-metrics.ts builds the OTel instrument set for @suaveplan/react-auth. Instruments are constructed lazily through metrics.getMeter("suaveplan.react-auth") so consumers without a registered MeterProvider pay zero overhead — the OTel API ships a no-op meter by default. The module exposes five counters (react_auth.sign_in.total, react_auth.sign_up.total, react_auth.sign_out.total, react_auth.guard.allow.total, react_auth.guard.deny.total) and one histogram (react_auth.session_fetch.duration_ms), plus helper functions that record the corresponding event with a typed attribute payload. The helpers also push every event into an in-memory state ring so spec-conformance tests can assert exact attribute payloads without standing up a full SDK pipeline. resetReactAuthMetricsState() clears the ring between tests.

Features

  • Lazy OTel instrument construction; no-op until a MeterProvider is registered.
  • 5 counters + 1 histogram covering the wave-1 production paths.
  • Typed outcome/predicate attributes per record helper.
  • In-memory state ring (getReactAuthMetricsState) for assertion-friendly tests.
  • resetReactAuthMetricsState() test-only helper.

Usage: Basic

import { recordSignIn } from "@suaveplan/react-auth";

await client.signIn(credentials);
recordSignIn("success");

Usage: Advanced

Wire a real MeterProvider (e.g. for shipping metrics to Prometheus) and assert via the in-memory ring in tests:

import { metrics } from "@opentelemetry/api";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import {
    getReactAuthMetricsState,
    recordSessionFetchDuration,
    resetReactAuthMetricsState,
} from "@suaveplan/react-auth";

const provider = new MeterProvider();
metrics.setGlobalMeterProvider(provider);

resetReactAuthMetricsState();
recordSessionFetchDuration(42, "success");
const state = getReactAuthMetricsState();
expect(state.sessionFetchDurationMs).toEqual([
    { attributes: { outcome: "success" }, value: 42 },
]);

API Reference

  • interface ReactAuthMetricSample — { attributes: Record<string, string>; value?: number }.
  • interface ReactAuthMetricsState — { signInTotal; signUpTotal; signOutTotal; guardAllowTotal; guardDenyTotal; sessionFetchDurationMs } arrays.
  • function getReactAuthMetrics() — returns the cached instrument bundle.
  • function recordSignIn(outcome: "success" | "failure"): void.
  • function recordSignUp(outcome: "success" | "failure"): void.
  • function recordSignOut(outcome: "success" | "failure"): void.
  • function recordGuardAllow(predicate: string): void.
  • function recordGuardDeny(predicate: string): void.
  • function recordSessionFetchDuration(durationMs: number, outcome: "success" | "failure"): void.
  • function getReactAuthMetricsState(): ReactAuthMetricsState.
  • function resetReactAuthMetricsState(): void.

Implementation Notes

The OTel API exposes a global no-op MeterProvider until the application opts in by calling setGlobalMeterProvider(...); this means the helpers are safe to call from production paths without any registration ceremony. The in-memory state ring is unbounded by design — it is intended only for tests and the package's own conformance checks. A long-running process would never call getReactAuthMetricsState() directly, so leak risk is bounded by test scope. The cached instrument bundle is module-level (let cached: CachedInstruments | undefined) so the meter is resolved at most once per process; the lazy build means importing the module is free.