Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# `metrics.ts`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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 typed
`EmailerErrorCode` so 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
global `MeterProvider`; tests call this after installing an in-memory
provider so subsequent emissions land on the test exporter.
## Usage: Basic
```ts
import { recordSend } from "@suaveplan/emailer/otel/metrics";
const startedAt = Date.now();
// ... actual send ...
recordSend("dummy", "ok", Date.now() - startedAt);
```
## Usage: Advanced
```ts
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(): void`
- `recordSend(transport: string, outcome: "ok" | "error", latencyMs: number): void`
- `recordSendError(transport: string, code: string): void`
- `recordRetry(transport: string): void`
- `recordQueue(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.
- `refreshEmailerMeters` is 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.