2.6 KiB
otel/instruments
(no submodules)
Purpose
Owns the OpenTelemetry instrument bundle the audit plugin emits to every request lifecycle. Resolving the instruments lazily on first call lets test harnesses install a custom MeterProvider BEFORE the production module loads, so the in-memory exporter captures every observation. Without this lazy resolution, the meter would bind to the no-op default provider at import time and tests would see no metrics.
The four instruments cover the entire surface needed to operate the plugin in production: per-request recorded counter (labelled by outcome and sampled flag), excluded-path counter, sink-failure counter, and a duration histogram.
Features
- Lazy, cached resolution — first call constructs the meter + four instruments; subsequent calls return the same bundle.
resetAuditPluginInstruments()test hook drops the cache so a newMeterProvidercan be picked up between tests.- Counter and histogram surfaces follow the OTel semantic-conventions naming style (
audit.<noun>_<unit>for histograms,<noun>_totalfor counters).
Usage: Basic
import { getAuditPluginInstruments } from "@suaveplan/api-plugin-audit/otel/instruments";
const instruments = getAuditPluginInstruments();
instruments.requestsRecorded.add(1, { outcome: "success", sampled: "true" });
instruments.middlewareDuration.record(12.4);
Usage: Advanced
import { metrics } from "@opentelemetry/api";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import {
getAuditPluginInstruments,
resetAuditPluginInstruments,
} from "@suaveplan/api-plugin-audit/otel/instruments";
const provider = new MeterProvider();
metrics.setGlobalMeterProvider(provider);
resetAuditPluginInstruments();
const instruments = getAuditPluginInstruments();
instruments.sinkFailures.add(1);
await provider.forceFlush();
API Reference
interface AuditPluginInstruments { meter, requestsRecorded, requestsExcluded, sinkFailures, middlewareDuration }.getAuditPluginInstruments(): AuditPluginInstruments— cached resolver.resetAuditPluginInstruments(): void— drops the cache.
Implementation Notes
The lazy cache is keyed on a single module-level let binding; concurrent first-callers see the same instance because the resolver is synchronous. Histogram unit is explicitly declared ms so OTel collectors don't have to infer it from the metric name. The labels on requestsRecorded are kept low-cardinality (outcome ∈ {success, error} × sampled ∈ {true, false}) so the cardinality budget for downstream backends stays bounded.