first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# `observability/metrics`
|
||||
|
||||
## Purpose
|
||||
|
||||
OpenTelemetry meter + instrument registry for `@suaveplan/crypto-rsa`. Stage 1
|
||||
defines the full instrument set the proposal pins (so dashboards and SLOs can
|
||||
be authored ahead of Stages 2-4) and wires up the parse/serialise duration
|
||||
histograms and the typed-error counter — the only paths that have a hot
|
||||
production call site at this stage.
|
||||
|
||||
The instruments are lazily constructed on first use to keep the module
|
||||
import-side-effect-free; this matters because some downstream consumers
|
||||
import the package without ever installing a `MeterProvider`, and constructing
|
||||
real instruments against the no-op global meter is harmless but unnecessary.
|
||||
|
||||
## Features
|
||||
|
||||
- Lazy `meter()` and `instruments()` accessors — first access constructs,
|
||||
subsequent accesses reuse cached instruments.
|
||||
- `resetMetricsForTesting()` — drops the caches so a fresh `MeterProvider`
|
||||
installed by a test takes effect.
|
||||
- `recordParseDuration(format, ms)`, `recordSerializeDuration(format, ms)`,
|
||||
`recordError(code)` — production helpers wrapping the instrument calls.
|
||||
- `getInstrumentsForTesting()` — exposes the bag for test assertions.
|
||||
- Full instrument set (8 histograms + 6 counters) declared up-front so the
|
||||
metric names cannot drift between Stages.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
recordError,
|
||||
recordParseDuration,
|
||||
} from "@suaveplan/crypto-rsa/observability";
|
||||
|
||||
const start = performance.now();
|
||||
try {
|
||||
parse();
|
||||
recordParseDuration("pkcs1", performance.now() - start);
|
||||
} catch (error) {
|
||||
recordError(error.code);
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
getInstrumentsForTesting,
|
||||
resetMetricsForTesting,
|
||||
} from "@suaveplan/crypto-rsa/observability";
|
||||
import { metrics } from "@opentelemetry/api";
|
||||
import { MeterProvider } from "@opentelemetry/sdk-metrics";
|
||||
|
||||
resetMetricsForTesting();
|
||||
metrics.setGlobalMeterProvider(new MeterProvider({ readers: [reader] }));
|
||||
const bag = getInstrumentsForTesting();
|
||||
// bag.errorsTotal, bag.outcomeTotal, …
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `recordParseDuration(format: string, durationMs: number): void`
|
||||
- `recordSerializeDuration(format: string, durationMs: number): void`
|
||||
- `recordError(code: string): void`
|
||||
- `resetMetricsForTesting(): void`
|
||||
- `getInstrumentsForTesting(): InstrumentBag`
|
||||
|
||||
The instrument bag carries (counters): `errorsTotal`, `outcomeTotal`,
|
||||
`engineSelectedTotal`, `fingerprintTotal`, `profileViolationTotal`,
|
||||
`blindingDisabledTotal`; (histograms): `verifyDurationMs`, `signDurationMs`,
|
||||
`encryptDurationMs`, `decryptDurationMs`, `keygenDurationMs`,
|
||||
`modpowDurationMs`, `parseDurationMs`, `serializeDurationMs`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The instruments are declared even though most are not yet wired into
|
||||
production paths because the proposal pins them as the canonical observable
|
||||
surface; declaring them lets dashboards reference the metric
|
||||
names by build time, not by feature-arrival time, and prevents naming drift
|
||||
when Stages 2-4 wire them up.
|
||||
|
||||
`resetMetricsForTesting` is the documented seam for swapping
|
||||
`MeterProvider`s under test. Production code should never call it.
|
||||
Reference in New Issue
Block a user