first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user