first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
# `instruments` — OTel `ws.broker.*` surface
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
import {
publishDurationHistogram,
publishesCounter,
} from "@suaveplan/api-ws-broker-redis/instruments";
publishesCounter().add(1, { topic: "orders", outcome: "ok" });
publishDurationHistogram().record(12);
```
## Usage: Advanced
```ts
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.*`).