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(): CounterpublishDurationHistogram(): HistogramreceivesCounter(): CounterbufferWritesCounter(): CounterbufferReadsCounter(): CounterconnectionLostCounter(): CounterresetBrokerMetricsForTests(): 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.*).