Files
2026-05-27 23:29:53 +01:00

2.7 KiB

instruments — OpenTelemetry instruments for api-plugin-example

(no submodules)

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

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:

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.