first commit
This commit is contained in:
@@ -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.*`).
|
||||
Reference in New Issue
Block a user