3.0 KiB
3.0 KiB
otel/instruments — counter + histogram per migration apply
(no submodules)
Purpose
Lazily builds and caches the two OpenTelemetry instruments that
@suaveplan/api-migrations emits on every migration apply attempt:
- counter
migrations.applied_total{dialect, outcome} - histogram
migrations.apply_duration_ms{name}
Lazy construction defers metrics.getMeter(...) until the first apply, so
the meter resolves against whatever MeterProvider is globally installed at
that moment — including the test in-memory provider that
tests/setup/polyfills.ts registers before any source module loads.
Features
- Single
recordApply(dialect, name, durationMs, outcome)entry point — keeps the call-site code inrunner.tsshort and uniform regardless of success or failure path. - Emits both instruments on every call, so observability does not depend on whether a migration succeeded.
resetMigrationInstruments()lets the test suite discard the cached instance betweenMeterProviderswaps.- Counter attributes are deliberately low-cardinality (
dialect× two outcomes) so the time series is stable across releases.
Usage: Basic Example
import { getMigrationInstruments } from "@suaveplan/api-migrations/otel/instruments";
const instruments = getMigrationInstruments();
instruments.recordApply("sqlite", "001_initial", 17, "success");
Usage: Advanced Example
import {
getMigrationInstruments,
resetMigrationInstruments,
} from "@suaveplan/api-migrations/otel/instruments";
import { metrics } from "@opentelemetry/api";
import { MeterProvider } from "@opentelemetry/sdk-metrics";
// Swap providers between test phases — call reset to rebuild the cached
// instruments against the new meter.
metrics.setGlobalMeterProvider(new MeterProvider());
resetMigrationInstruments();
getMigrationInstruments().recordApply("postgres", "002_users", 42, "error");
API Reference
interface MigrationInstruments { recordApply(dialect, name, durationMs, outcome): void }.getMigrationInstruments(): MigrationInstruments— returns the cached instance, building it on first call against the currently registeredMeterProvider.resetMigrationInstruments(): void— clears the cache (test-only).
Implementation Notes
- The module-level
instrumentscache is the only mutable state and is scoped to the module — re-importing the module under a fresh ESM realm yields a fresh cache, which is the desired behaviour for isolated tests. - The counter is namespaced
migrations.applied_total; the histogram is namespacedmigrations.apply_duration_ms— both names match the spec delta literally so downstream dashboards do not need translation tables. - Attribute cardinality:
dialectis bounded byMigrationDialect(currently four members),outcomeis exactly two, andnameis the user-supplied migration basename. The histogram attribute is intentionallyname-only — addingoutcomehere would explode the bucket count.