Files
skills/docs/api-stack/api/api-ws-broker-redis/src/instruments/instruments.md
2026-05-29 08:20:56 +01:00

3.5 KiB

instruments — OTel ws.broker.* surface

(no submodules)

Purpose

This module owns the OpenTelemetry instrument surface for the Redis broker. Six instruments cover every documented operational signal: publish attempts and durations, inbound receive counts, reconnect-buffer reads and writes (with hit/miss labelling), and observed connection drops. Operators wire a MeterProvider against the global metrics API and the broker emits into it without any wiring inside the broker module itself.

Resolving the meter and instruments lazily (rather than at module load) lets tests install a fresh MeterProvider after importing the broker and still observe emissions from production paths. The resetBrokerMetricsForTests helper exposes the same lazy cache to test teardown.

Features

  • Six instruments, each documented with attribute keys:
    • ws.broker.publishes_total — counter, labels { topic, outcome }.
    • ws.broker.publish_duration_ms — histogram (ms).
    • ws.broker.receives_total — counter, labels { topic }.
    • ws.broker.buffer_writes_total — counter.
    • ws.broker.buffer_reads_total — counter, labels { hit }.
    • ws.broker.connection_lost_total — counter.
  • Lazy resolution against metrics.getMeter("@suaveplan/api-ws-broker-redis") so tests can install their own SDK between cases.
  • resetBrokerMetricsForTests() clears the lazy cache.
  • No singletons leak into the public surface — every getter returns the meter-bound instrument so tests can assert against them directly.

Usage: Basic

import {
    publishDurationHistogram,
    publishesCounter,
} from "@suaveplan/api-ws-broker-redis/instruments";

publishesCounter().add(1, { topic: "orders", outcome: "ok" });
publishDurationHistogram().record(12);

Usage: Advanced

import {
    metrics,
} from "@opentelemetry/api";
import {
    AggregationTemporality,
    MeterProvider,
    MetricReader,
} from "@opentelemetry/sdk-metrics";
import {
    publishesCounter,
    resetBrokerMetricsForTests,
} from "@suaveplan/api-ws-broker-redis/instruments";

class CollectingReader extends MetricReader {
    constructor() {
        super({
            aggregationTemporalitySelector: () =>
                AggregationTemporality.CUMULATIVE,
        });
    }
    protected override async onForceFlush() {}
    protected override async onShutdown() {}
    snapshot() {
        return this.collect();
    }
}

const reader = new CollectingReader();
const provider = new MeterProvider({ readers: [reader] });
metrics.setGlobalMeterProvider(provider);
resetBrokerMetricsForTests();
// Now the broker's emissions land in `reader.snapshot()`.

API Reference

  • publishesCounter(): Counter
  • publishDurationHistogram(): Histogram
  • receivesCounter(): Counter
  • bufferWritesCounter(): Counter
  • bufferReadsCounter(): Counter
  • connectionLostCounter(): Counter
  • resetBrokerMetricsForTests(): void

Implementation Notes

Module-local let cache variables (_meter, _publishes, etc.) keep the instrument identity stable across calls within a single process so OTel SDK aggregation works correctly. resetBrokerMetricsForTests() re-initialises those to undefined so tests can switch SDKs between cases without inheriting the previous run's Meter reference.

The instrument names follow the ws.broker.* namespace convention — every WS-related OTel surface in Suaveplan lives under ws.* to keep dashboard queries simple, and ws.broker.* distinguishes broker-side emissions from engine-side ones (ws.engine.*).