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

3.0 KiB

otel/instruments.ts

(no submodules)

Purpose

Owns the lazy-built OpenTelemetry instrument bundle (SiteInstruments) that every observable code path in @suaveplan/api-plugin-site emits to. Instruments are constructed against the global MeterProvider on first call and cached so each call to getSiteInstruments() reuses the same Counter/Histogram handles. resetSiteInstruments() drops the cache so tests can install a fresh MeterProvider and re-bind against it — the canonical suaveplan pattern used by every other plugin's OTel module.

Features

  • sitesCreatedTotal{outcome} counter — success | error.
  • sitesUpdatedTotal{kind} counter — settings | fields | state | domain.
  • domainResolutionsTotal{outcome} counter — hit | miss | error.
  • domainResolutionDurationMs histogram — wall-clock ms.
  • bootstrapFailedTotal counter — incremented when createDefaultSite fails during an organization:created event.
  • Cache reset for test rebinding via resetSiteInstruments().

Usage: Basic

import { getSiteInstruments } from "@suaveplan/api-plugin-site/otel/instruments";

const inst = getSiteInstruments();
inst.sitesCreatedTotal.add(1, { outcome: "success" });

Usage: Advanced

import { MeterProvider } from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";
import {
    getSiteInstruments,
    resetSiteInstruments,
} from "@suaveplan/api-plugin-site/otel/instruments";

beforeAll(() => {
    const mp = new MeterProvider();
    metrics.setGlobalMeterProvider(mp);
    resetSiteInstruments();
});

it("counts a resolution miss", () => {
    const inst = getSiteInstruments();
    inst.domainResolutionsTotal.add(1, { outcome: "miss" });
});

API Reference

  • interface SiteInstruments — five readonly handles.
  • getSiteInstruments(): SiteInstruments — lazy + cached.
  • resetSiteInstruments(): void — drop cache so the next call rebinds.

Implementation Notes

  • The cache lives at module scope. Reset is required between tests that swap the global provider — without it, an old handle pinned to a destroyed provider would record forever into the void.
  • Metric names follow <package>.<noun>_total / _duration_ms convention so dashboards can grep across plugins consistently.
  • The histogram unit is ms so collectors can render p50/p95/p99 latency without additional conversion.
  • The counter / histogram handles returned by getSiteInstruments() are safe to retain across requests — they are thin proxies over the underlying MeterProvider's metric registry, and recreating them on every call would defeat the purpose of OTel's batched export pipeline. Tests that swap providers therefore MUST call resetSiteInstruments() before the next read so the next handle points at the new provider.
  • This module avoids any side effects at import time so consumers can tree-shake it cleanly when they disable observability via a build flag — the getMeter call is gated behind the first invocation of getSiteInstruments.