Files
skills/docs/api-stack/api/api-plugin-sse/src/otel/instruments.md
2026-05-29 08:20:56 +01:00

3.4 KiB
Raw Blame History

instruments

(no submodules)

Purpose

Provides the canonical OpenTelemetry instrument bundle emitted by the SSE plugin. Counters and a histogram cover the four observability questions operators ask: "how many connections are live?", "how busy is each channel?", "are heartbeats firing?", and "are we shedding load under backpressure?". Instruments are lazily resolved against the global MeterProvider and cached so every production call site shares the same identity (a cold-start operator can install a fresh provider in tests via resetSseInstruments()).

Features

  • sse.active_connections — UpDownCounter; +1 on subscribe, −1 on close. Carries channel attribute so dashboards can show per-channel concurrency.
  • sse.broadcasts_total — counter incremented on every service.broadcast call, partitioned by channel.
  • sse.heartbeats_total — counter incremented every time the handler writes a : heartbeat\n\n comment frame.
  • sse.message_bytes_total — total bytes written across every framed event (helps capacity planning).
  • sse.queue_overflow_total — counter incremented when the handler drops events under backpressure; tags policy and the originating code: SSE.QUEUE_OVERFLOW.
  • sse.connection_duration_ms — histogram of per-connection lifetime in milliseconds, recorded on close.

Usage: Basic

import { getSseInstruments } from "@suaveplan/api-plugin-sse/otel/instruments";

const instruments = getSseInstruments();
instruments.broadcastsTotal.add(1, { channel: "notifications" });

Usage: Advanced

import { metrics } from "@opentelemetry/api";
import {
    InMemoryMetricExporter,
    AggregationTemporality,
    MeterProvider,
    PeriodicExportingMetricReader,
} from "@opentelemetry/sdk-metrics";
import {
    getSseInstruments,
    resetSseInstruments,
} from "@suaveplan/api-plugin-sse/otel/instruments";

// Install a fresh provider in a test, then rebind the cache.
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
const reader = new PeriodicExportingMetricReader({
    exporter,
    exportIntervalMillis: 60_000,
});
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetSseInstruments();

const i = getSseInstruments();
i.activeConnections.add(1, { channel: "c" });
await provider.forceFlush();
console.log(exporter.getMetrics());

API Reference

  • interface SseInstruments — the bundle: activeConnections: UpDownCounter, broadcastsTotal: Counter, heartbeatsTotal: Counter, messageBytesTotal: Counter, queueOverflowTotal: Counter, connectionDurationMs: Histogram.
  • getSseInstruments(): SseInstruments — lazily resolve the bundle against the current global MeterProvider; cached so subsequent calls are O(1).
  • resetSseInstruments(): void — drop the cache so the next getSseInstruments rebinds. Tests call this after installing a fresh provider.

Implementation Notes

  • Instrument names use the canonical OpenTelemetry semantic conventions style (sse.snake_case_name). They are public — renaming is a breaking change.
  • The bundle is module-level cached. A second MeterProvider.setGlobalMeterProvider call after getSseInstruments has been invoked will NOT take effect until resetSseInstruments runs.
  • connection_duration_ms is recorded with the channel attribute so per-channel SLO dashboards work without a separate aggregator.