first commit
This commit is contained in:
70
docs/identity/auth/webauthn/src/observability/metrics.md
Normal file
70
docs/identity/auth/webauthn/src/observability/metrics.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# WebAuthn observability — metrics
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Defines every OTel instrument emitted by `@suaveplan/webauthn`. The registry is a single bag of pre-created `Histogram` / `Counter` instances cached at module-load time so production paths can record without per-call allocation. The cache resets via `resetMetricsForTesting()` so a fresh in-memory `MeterProvider` registered in `beforeEach` produces deterministic assertions.
|
||||
|
||||
## Features
|
||||
|
||||
- Five instruments cover every production path: `webauthn.register_duration_ms`, `webauthn.authenticate_duration_ms`, `webauthn.outcome_total`, `webauthn.attestation_format_total`, `webauthn.errors_total`.
|
||||
- Bounded label cardinality: `outcome` ∈ `{ ok | error | aborted }`, `op` ∈ `{ register | authenticate }`, `fmt` ∈ the seven IANA-registered formats plus `unknown`.
|
||||
- `recordRegister` / `recordAuthenticate` write both the duration histogram and the outcome counter atomically so dashboards never disagree.
|
||||
- `resetMetricsForTesting` / `getInstrumentsForTesting` keep test hooks out of the runtime module surface but available to spec tests.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
nowMs,
|
||||
recordRegister,
|
||||
} from "@suaveplan/webauthn/observability/metrics";
|
||||
|
||||
const start = nowMs();
|
||||
try {
|
||||
await doRegister();
|
||||
recordRegister("ok", nowMs() - start);
|
||||
} catch (err) {
|
||||
recordRegister("error", nowMs() - start);
|
||||
throw err;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { MeterProvider, InMemoryMetricExporter } from "@opentelemetry/sdk-metrics";
|
||||
import { metrics } from "@opentelemetry/api";
|
||||
import {
|
||||
resetMetricsForTesting,
|
||||
recordAttestationFormat,
|
||||
} from "@suaveplan/webauthn/observability/metrics";
|
||||
|
||||
const exporter = new InMemoryMetricExporter();
|
||||
const provider = new MeterProvider({ readers: [/* periodic reader */] });
|
||||
metrics.setGlobalMeterProvider(provider);
|
||||
resetMetricsForTesting();
|
||||
|
||||
recordAttestationFormat("packed");
|
||||
const points = await exporter.collect();
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `WebAuthnOutcome` — `"ok" | "error" | "aborted"`.
|
||||
- `WebAuthnOp` — `"register" | "authenticate"`.
|
||||
- `WebAuthnAttestationFmt` — `"packed" | "fido-u2f" | "tpm" | "android-key" | "android-safetynet" | "apple" | "none" | "unknown"`.
|
||||
- `recordRegister(outcome, durationMs)` — record both histogram + outcome counter.
|
||||
- `recordAuthenticate(outcome, durationMs)` — same for the assertion path.
|
||||
- `recordAttestationFormat(fmt)` — increment dispatch counter.
|
||||
- `recordError(code)` — increment `webauthn.errors_total{code}`.
|
||||
- `nowMs()` — wall-clock reader.
|
||||
- `resetMetricsForTesting()` / `getInstrumentsForTesting()` — test hooks.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The instrument bag is lazily created on first call so the meter resolves against whatever `MeterProvider` the host application has installed.
|
||||
- The reset hook is mandatory because OTel meter caching makes pre-registered instruments outlive a test's MeterProvider swap; without it a second test reads metrics from the first test's exporter.
|
||||
- `nowMs()` is exposed as a function rather than `Date.now` directly so future tests can stub it without monkey-patching `globalThis.Date`.
|
||||
Reference in New Issue
Block a user