3.3 KiB
instruments.ts — webhook plugin OpenTelemetry instruments
(no submodules)
Purpose
Defines the four OpenTelemetry instruments emitted by the webhook plugin: two counters and two histograms covering every observable outcome of WebhookService.send. The bundle is lazily built against the process-wide MeterProvider and cached so repeat calls return the same Counter / Histogram references — this means tests can install a fresh provider, call resetWebhookInstruments(), and trust that the next getWebhookInstruments() rebinds against it. Without this seam, tests that install a MeterProvider after the first import see metrics flow to a stale meter and silently drop observations.
Features
- Four instruments —
deliveries_total,dead_letters_total,delivery_attempts,send_duration_ms. - Lazy + cached binding so the meter is resolved on first read, not at import time.
resetWebhookInstruments()for test isolation.- Stable namespace
webhook_plugin.*to keep the plugin's metrics separate from@suaveplan/webhook-client'swebhook_client.*metrics.
Usage: Basic
import { getWebhookInstruments } from "@suaveplan/api-plugin-webhook/otel/instruments";
const inst = getWebhookInstruments();
inst.deliveriesTotal.add(1, { event: "order.created", status: "delivered" });
Usage: Advanced
// Tests typically install a fresh MeterProvider, then call resetWebhookInstruments
// so the next getWebhookInstruments() rebinds against the freshly-installed provider.
import { metrics } from "@opentelemetry/api";
import {
AggregationTemporality,
InMemoryMetricExporter,
MeterProvider,
PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import {
getWebhookInstruments,
resetWebhookInstruments,
} from "@suaveplan/api-plugin-webhook/otel/instruments";
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetWebhookInstruments();
const inst = getWebhookInstruments();
inst.deliveriesTotal.add(1, { event: "evt", status: "delivered" });
await provider.forceFlush();
console.log(exporter.getMetrics());
API Reference
getWebhookInstruments()— returns the cachedWebhookInstrumentsbundle, lazily binding on first call.resetWebhookInstruments()— drops the cache so the nextgetWebhookInstruments()rebinds.WebhookInstruments—{ deliveriesTotal, deadLettersTotal, deliveryAttempts, sendDurationMs }.
Implementation Notes
The namespace webhook_plugin.* was chosen explicitly so dashboards and alerts can distinguish plugin-level emissions from the webhook_client.* emissions the underlying delivery library emits. The label set {event, status, endpoint_id} on deliveries_total deliberately includes endpoint_id even though it has unbounded cardinality — operators with many endpoints SHOULD aggregate at scrape time using a recording rule that drops the label. Including it at emission time means operators can debug a single endpoint without recompiling. The histograms inherit OTel's default bucket layout (no custom boundaries supplied) — operators tune via SDK views, not by editing this file.