@rpc-bastion/observability
v0.4.1
Published
Event bus to OpenTelemetry (metrics + traces); Datadog via OTLP.
Readme
@rpc-bastion/observability
Bridge the RPC Bastion event bus to OpenTelemetry — metrics + traces, then out to Prometheus, Datadog, or any OTLP backend. No logging on the hot path; everything flows through the structured event bus.
Use it
import { createEventBus, registerOtelExporter } from '@rpc-bastion/observability';
const bus = createEventBus(); // re-exported from @rpc-bastion/core
const off = registerOtelExporter(bus, { prefix: 'bastion' });
// pass `bus` to createResilientRpc({ bus }) and createSender({ bus })
// ... later: off();@opentelemetry/api is an optional peer dependency. Without an OTel SDK
registered the exporter is a no-op — safe to call unconditionally. Register a
NodeSDK with an OTLP exporter to start shipping data.
What it emits
- Metrics: counters (
rpc.requests,rpc.errors,rpc.retries,rpc.failovers,tx.submitted{route},tx.rebroadcast,tx.route_fallback,tx.confirmed/tx.expired/tx.failed), histograms (rpc.latency,tx.confirmation_time), observable gauges (endpoint.health_score,endpoint.inflight,breaker.open_count). - Traces: a span tree per
sendSmart(tx.sendroot →tx.attemptchildren per route, withroute-fallbackrecorded). Per-RPC-call spans are off by default (volume).
Options
| Option | Default | Notes |
|---|---|---|
| meterProvider | global API | false disables metrics |
| tracerProvider | global API | false disables traces |
| prefix | none | prepended to every metric/span name |
| scope | @rpc-bastion/observability | instrumentation scope |
Backends: Prometheus & Datadog
Point your OTel SDK's OTLP exporter at an OpenTelemetry Collector, which fans
out to Prometheus (scrape) and Datadog (OTLP ingest) — one exporter, both
backends, no dd-trace. A runnable docker-compose stack and configs are in
docs/observability.md and
docs/observability/.
Safety
The event bus isolates listeners: a throwing exporter never breaks the hot path
or other listeners (it's routed to bus.onListenerError). The exporter also
guards its own recorders, so observability can't affect transaction execution.
