3.3 KiB
instruments
(no submodules)
Purpose
Lazily resolves the OpenTelemetry instruments (Counter, Histogram)
the plugin emits from its production paths. The bundle is built on
first call and cached; tests call resetTenantPluginInstruments after
installing a fresh MeterProvider so subsequent calls rebind to the
test exporter. This pattern lets the package work seamlessly in
production (where the global provider is the OTel SDK) and under test
(where the global provider is an InMemoryMetricExporter).
Features
- Four instruments:
resolutionsTotal(counter),resolutionDurationMs(histogram),cacheTotal(counter),managementOpsTotal(counter). - Lazy initialisation — the meter is resolved on first call so test polyfills installed before the package loads bind correctly.
resetTenantPluginInstrumentsclears the cache so a re-bind is forced; primarily useful in test setup hooks.
Usage: Basic Example
import { getTenantPluginInstruments } from "@suaveplan/api-plugin-tenant";
const instruments = getTenantPluginInstruments();
instruments.resolutionsTotal.add(1, { outcome: "resolved", strategy: "header" });
instruments.resolutionDurationMs.record(12.4, { strategy: "header" });
Usage: Advanced Example
import {
getTenantPluginInstruments,
resetTenantPluginInstruments,
} from "@suaveplan/api-plugin-tenant";
import { metrics } from "@opentelemetry/api";
import { InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader, AggregationTemporality } from "@opentelemetry/sdk-metrics";
// In test setup before the package's other modules load:
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetTenantPluginInstruments();
// Later — assert the counters that were emitted:
await provider.forceFlush();
const collected = exporter.getMetrics();
const resolutions = collected[0]?.scopeMetrics[0]?.metrics.find(
(m) => m.descriptor.name === "tenant_plugin.resolutions_total"
);
console.assert(resolutions !== undefined);
API Reference
interface TenantPluginInstruments—{ resolutionsTotal: Counter, resolutionDurationMs: Histogram, cacheTotal: Counter, managementOpsTotal: Counter }.function getTenantPluginInstruments(): TenantPluginInstruments— returns the cached bundle, building it on first call.function resetTenantPluginInstruments(): void— drops the cache.
Implementation Notes
The lazy pattern is essential — calling metrics.getMeter("...") at
module top-level binds to whichever MeterProvider was installed at
import time. Because Vitest's setupFiles run before src/ modules
import, installing the in-memory provider there guarantees the test
bundle binds correctly. Production callers that install their OTel SDK
late (e.g. behind a feature flag) call resetTenantPluginInstruments
once the SDK is up so the plugin rebinds. The instrument names use
tenant_plugin. rather than tenant. so dashboards can cleanly
distinguish the plugin's emissions from the underlying
@suaveplan/api-tenant library's instruments (if any are added later).