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,57 @@
# `metrics`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
OpenTelemetry instrumentation surface for the JWS verify and sign hot paths. Every production code path records a histogram for wall-time latency and increments outcome-tagged counters; the error registry's `recordError` also fires once per typed throw so dashboards can pivot on `code` cardinality. The `outcome` attribute is bounded to a 4-value enum (`success | sig_invalid | alg_not_allowed | header_invalid`) so production observability backends do not blow up under attacker-controlled token streams.
## Features
- `recordVerify(alg, outcome, durationMs)` — histogram + outcome counter.
- `recordSign(alg, "success" | "error", durationMs)` — sign-side mirror.
- `recordError(code)` — typed-error counter pivoted by code.
- `resetMetricsForTesting()` — rebinds the cached instrument bag after a test installs a fresh `MeterProvider`.
- `getInstrumentsForTesting()` — exposes the bag for assertion-time introspection.
## Usage: Basic Example
```ts
import { metrics } from "@opentelemetry/api";
import { resetMetricsForTesting, compactVerify } from "@suaveplan/jws";
metrics.setGlobalMeterProvider(myInMemoryProvider);
resetMetricsForTesting();
await compactVerify(token, key, { algorithms: ["HS256"] });
// `jws.verify_duration_ms{alg=HS256, outcome=success}` has 1 sample.
```
## Usage: Advanced Example
```ts
import { getInstrumentsForTesting, recordVerify, recordError, JWS_CODES } from "@suaveplan/jws";
const bag = getInstrumentsForTesting();
// bag.verifyDurationMs / bag.signDurationMs (Histogram)
// bag.verifyTotal / bag.signTotal (Counter)
// bag.errorTotal (Counter)
// Bypass the pipeline for an ad-hoc observation:
recordVerify("RS256", "sig_invalid", 4.2);
recordError(JWS_CODES.SIG_INVALID);
```
## API Reference
- `recordVerify(alg: string, outcome: JwsVerifyOutcome, durationMs: number): void`
- `recordSign(alg: string, outcome: "success" | "error", durationMs: number): void`
- `recordError(code: string): void`
- `nowMs(): number`
- `resetMetricsForTesting(): void`
- `getInstrumentsForTesting(): InstrumentBag`
- `type JwsVerifyOutcome = "success" | "sig_invalid" | "alg_not_allowed" | "header_invalid"`
## Implementation Notes
The instrument bag is cached in module scope so repeated invocations do not call `metrics.getMeter` on every request — that call has non-trivial overhead under the OTel SDK because it walks the provider's registry. Tests that install a fresh `MeterProvider` MUST call `resetMetricsForTesting()` in `beforeEach`; otherwise the cached bag stays bound to the original (no-op) provider and the test asserts against an empty histogram. The `outcome` enum's bounded cardinality is deliberate: an unbounded enum would let an adversarial token stream blow up the metrics backend's series count, and most OTel sinks bill by series.