2.7 KiB
2.7 KiB
metrics.ts
(no submodules)
Purpose
Single source of truth for every OpenTelemetry instrument emitted by
@suaveplan/emailer. Every production path that touches the wire — send
attempts, send failures, latency, retries, queue enqueues — records exactly
one observation through one of the helpers exported here. Centralising the
emission lets the spec-conformance test grep one file to assert that every
declared instrument is wired into a production call.
Features
recordSend(transport, outcome, latencyMs)— counter + histogram pair for every send attempt.recordSendError(transport, code)— counter keyed on the typedEmailerErrorCodeso dashboards filter by code path, not message.recordRetry(transport)— counter on every retry attempt.recordQueue(transport)— counter on every enqueue.refreshEmailerMeters()— re-binds every instrument against the current globalMeterProvider; tests call this after installing an in-memory provider so subsequent emissions land on the test exporter.
Usage: Basic
import { recordSend } from "@suaveplan/emailer/otel/metrics";
const startedAt = Date.now();
// ... actual send ...
recordSend("dummy", "ok", Date.now() - startedAt);
Usage: Advanced
import { MeterProvider } from "@opentelemetry/sdk-metrics";
import { metrics } from "@opentelemetry/api";
import { refreshEmailerMeters, recordSend } from "@suaveplan/emailer/otel/metrics";
const provider = new MeterProvider();
metrics.setGlobalMeterProvider(provider);
refreshEmailerMeters();
recordSend("dummy", "ok", 12);
// `provider.collect()` now contains an `emailer.send.total` observation
// with attributes `{ transport: "dummy", outcome: "ok" }`.
API Reference
refreshEmailerMeters(): voidrecordSend(transport: string, outcome: "ok" | "error", latencyMs: number): voidrecordSendError(transport: string, code: string): voidrecordRetry(transport: string): voidrecordQueue(transport: string): void
Implementation Notes
- The five instrument names —
emailer.send.total,emailer.send.errors,emailer.send.latency_ms,emailer.retry.total,emailer.queue.depth— are part of the public surface. Renaming them silently breaks every downstream dashboard, so any change must move through OpenSpec. refreshEmailerMetersis required because the OpenTelemetry SDK does not propagate provider changes to existing instruments. Tests that swap the global provider must call it before invoking the production path, otherwise observations land on the module-load meter and the test sees zero data.- All instruments are universally available — the helpers carry no IO and are safe to call from synchronous hot paths.