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

57 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# otel/instruments
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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 new `MeterProvider` can be picked up between tests.
- Counter and histogram surfaces follow the OTel semantic-conventions naming style (`audit.<noun>_<unit>` for histograms, `<noun>_total` for counters).
## Usage: Basic
```ts
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
```ts
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.