57 lines
2.6 KiB
Markdown
57 lines
2.6 KiB
Markdown
# 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.
|