Files
skills/docs/security-stack/crypto/crypto-rsa/src/observability/metrics.md
2026-05-29 08:20:56 +01:00

3.0 KiB

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

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

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 MeterProviders under test. Production code should never call it.