# `instruments.ts` _(no submodules)_ ## Purpose OpenTelemetry instrument factory for `@suaveplan/api-plugin-export`. Builds a cached bundle of six instruments — five counters and one histogram — bound to the meter named `@suaveplan/api-plugin-export`. The cache lets the hot path (`POST /exports` + `GET /:id/download`) resolve instruments once per process instead of paying the meter-provider lookup cost on every job, while `resetExportInstruments()` gives tests a hook to rebind against an in-memory `MeterProvider` installed at suite startup. ## Features - Lazy resolution against the global `MeterProvider`, cached after the first call. - `export.jobs_total` counter (with `outcome` attribute) for every job, completed or failed. - `export.rows_total` and `export.bytes_total` counters that track the cumulative size of successful exports. - `export.duration_ms` histogram so dashboards / SLOs can report p50 / p99 latency. - `export.download.served` counter (with `format` attribute) for every successful download. - `export.download.failed` counter (with `reason` attribute) for every failed download. - `resetExportInstruments()` for tests installing fresh providers. ## Usage: Basic ```ts import { getExportInstruments } from "@suaveplan/api-plugin-export"; const inst = getExportInstruments(); inst.jobsTotal.add(1, { outcome: "completed" }); inst.rowsTotal.add(rowCount); inst.bytesTotal.add(byteSize); inst.durationMs.record(elapsedMs); ``` ## Usage: Advanced ```ts // In test setup, after installing a fresh MeterProvider: import { getExportInstruments, resetExportInstruments, } from "@suaveplan/api-plugin-export"; resetExportInstruments(); const inst = getExportInstruments(); // rebinds against the new provider ``` ## API Reference | Symbol | Kind | Notes | |---|---|---| | `ExportInstruments` | interface | `{ jobsTotal, rowsTotal, bytesTotal, durationMs, downloadServed, downloadFailed }`. | | `getExportInstruments()` | function | Lazy + cached. | | `resetExportInstruments()` | function | Drops the cache. | ## Implementation Notes The bundle is held in a module-scope `let cached: ExportInstruments | undefined` rather than in a class instance, because the function is the only documented entry point and there is no per-plugin state to keep — every plugin instance in a process shares the same meter. Counters use `add(value, attributes?)`; the `outcome` attribute is set by the call site rather than declared on the instrument because OTel attributes are runtime keys, not instrument metadata. The histogram unit is set to `"ms"` (lower-case) per OTel semantic conventions for latency. Resetting between tests is mandatory: meter handles cache internally inside `@opentelemetry/api`, so without `resetExportInstruments()` a test would emit to whichever provider was installed when the *first* `getExportInstruments()` call ran — usually the global default provider, which loses every metric.