first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
# `react-auth-metrics`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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:
```ts
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.