Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
# `instruments` — OpenTelemetry instruments for `api-plugin-example`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The reference plugin declares three OTel instruments that mirror the
`telemetry.metrics[]` block in `plugin.json`. The instruments are
lazily materialised against the global `MeterProvider` so the test
setup can install an `InMemoryMetricExporter` before the first call.
The integration suite reads the in-memory exporter to assert each
manifest-declared instrument emits values during the run.
## Features
- `example.invoices_finalised_total` — counter, no unit.
- `example.stripe.call_duration_ms` — histogram, `unit: "ms"`.
- `example.outstanding_invoice_count` — counter modelling a gauge.
- Lazy single-shot resolution — second call returns the cached object.
- `resetExampleInstrumentsForTest` — clears the cache between suites.
## Usage: Basic
```ts
import { getExampleInstruments } from "@suaveplan/api-plugin-example/instruments/instruments";
const m = getExampleInstruments();
m.invoicesFinalisedTotal.add(1, { tenant_id: ctx.tenantId ?? "none" });
```
## Usage: Advanced
The histogram is recorded around outbound Stripe calls. Wrap the
network call to capture duration even on error:
```ts
const start = performance.now();
try {
await stripe.charges.create({ amount, currency });
} finally {
m.stripeCallDurationMs.record(performance.now() - start);
}
```
## API Reference
- `getExampleInstruments(): ExampleInstruments` — Lazy accessor.
- `resetExampleInstrumentsForTest(): void` — Cache reset.
- `ExampleInstruments` — `{ invoicesFinalisedTotal, stripeCallDurationMs, outstandingInvoiceCount }`.
## Implementation Notes
The instruments are materialised against `metrics.getMeter(METER_NAME)`
rather than a passed-in provider so plugin code does not need to
plumb a meter through every handler. The provider is installed once
in `tests/setup/polyfills.ts` and the cached registry binds to it on
first call. The cache is intentionally process-wide rather than
per-`MeterProvider` because plugin authors typically install a global
provider at boot and never swap it; tests that DO swap providers call
`resetExampleInstrumentsForTest` between cases so the second call
re-materialises against the new meter. The OTel SDK's
`InMemoryMetricExporter` is the only test substrate that needs the
cache reset — production paths bind to the global provider for the
lifetime of the host process and any datapoint emitted goes through
the same instrument instance. The histogram declares `unit: "ms"` so
downstream Prometheus / OTLP collectors expose the unit in their
metric metadata. The counter and the gauge-modelling counter both
omit the `unit` field because they are dimensionless.