Files
skills/docs/api-stack/api/api-plugin-auth/src/otel/instruments.md
2026-05-29 08:20:56 +01:00

3.7 KiB

otel/instruments

(no submodules)

Purpose

The instruments module owns the OpenTelemetry counters and histogram emitted by every code path inside @suaveplan/api-plugin-auth. The bundle is lazily constructed against the global MeterProvider so operators can wire an SDK before the plugin loads without import-time side effects, and tests can call resetAuthInstruments() between suites to rebind against a fresh in-memory provider.

Features

  • Five named instruments — sessionsResolvedTotal, sessionResolveDurationMs, roleCheckTotal, signupsTotal, signinsTotal — bundled in one AuthInstruments value.
  • Lazy global-provider binding via metrics.getMeter(...) so the instruments resolve at first call, never at import time.
  • resetAuthInstruments() for deterministic test setup.
  • Stable instrument names (auth.*) mirrored by the spec delta so operators can scrape known metric IDs without code inspection.

Usage: Basic

import { getAuthInstruments } from "@suaveplan/api-plugin-auth/otel/instruments";

const ins = getAuthInstruments();
ins.sessionsResolvedTotal.add(1, { outcome: "authenticated" });
ins.sessionResolveDurationMs.record(durationMs, { outcome: "authenticated" });

Usage: Advanced

For testing, install an in-memory MeterProvider, then reset the cached instruments so the next access binds against it. The plugin's own test polyfill (tests/setup/polyfills.ts) does exactly this for every test file in the package.

import { metrics } from "@opentelemetry/api";
import {
    InMemoryMetricExporter,
    MeterProvider,
    PeriodicExportingMetricReader,
    AggregationTemporality,
} from "@opentelemetry/sdk-metrics";
import {
    getAuthInstruments,
    resetAuthInstruments,
} from "@suaveplan/api-plugin-auth/otel/instruments";

const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);

resetAuthInstruments();
const ins = getAuthInstruments();
ins.signinsTotal.add(1, { outcome: "failure" });
await provider.forceFlush();
const collected = exporter.getMetrics();

API Reference

interface AuthInstruments

  • sessionsResolvedTotal: Counter — auth.sessions_resolved_total.
  • sessionResolveDurationMs: Histogram — auth.session_resolve_duration_ms (unit ms).
  • roleCheckTotal: Counter — auth.role_check_total.
  • signupsTotal: Counter — auth.signups_total.
  • signinsTotal: Counter — auth.signins_total.

getAuthInstruments(): AuthInstruments

Returns the cached bundle, building it on first call. Safe to call concurrently — the cache is single-writer because the function is synchronous.

resetAuthInstruments(): void

Drops the cache so the next getAuthInstruments() builds afresh against whatever MeterProvider is currently registered.

Implementation Notes

  • The module deliberately reads metrics.getMeter lazily — calling it at import time would resolve the no-op meter before tests install their provider, which is exactly the failure mode that the resetAuthInstruments() helper exists to prevent.
  • Counter / histogram attribute keys (outcome) are documented per call site rather than enforced at the meter — OpenTelemetry's attribute API is intentionally untyped, but the call-site values are string literals ("authenticated", "anonymous", "error", "allowed", "denied", "success", "failure") so dashboards can rely on the cardinality being bounded.
  • Histogram unit is ms so dashboards do not need to renormalise.