# `@suaveplan/i18n-backend-http/observability` _(no submodules)_ ## Purpose Lazy OpenTelemetry instrument factory and matched in-memory state ring for `@suaveplan/i18n-backend-http`. Production paths in [`backend.ts`](../backend/backend.md) call `recordRead(...)` once per `HttpBackend.read` call; the instruments are no-ops until a `MeterProvider` is registered against `@opentelemetry/api`, so consumers pay zero overhead unless they wire up the SDK. The matched state ring exists so spec-conformance tests can assert exact attribute payloads without standing up a full SDK + `InMemoryMetricExporter` pipeline. ## Features - `i18n.backend.http.read_duration_ms` — Histogram, milliseconds. Attributes: `locale`, `namespace`, `outcome ∈ hit | miss | error`. - `i18n.backend.http.read_total` — Counter. Attribute: `outcome`. - `i18n.backend.http.read_errors_total` — Counter. Attributes: `code` (the `I18N.*` error code), optional `status` (HTTP status code as string when the error originated from a known HTTP response). - Zero-cost when no MeterProvider is wired — every instrument is a cached singleton. - Test-only state ring + reset helpers (`getHttpBackendMetricsState`, `resetHttpBackendMetricsState`, `resetHttpBackendMetricsCache`). ## Usage: Basic Example ```ts import { recordRead } from "@suaveplan/i18n-backend-http/observability"; recordRead("en", "auth", "hit", 0.42); ``` ## Usage: Advanced Example ```ts import { getHttpBackendMetricsState, recordRead, resetHttpBackendMetricsState, } from "@suaveplan/i18n-backend-http/observability"; resetHttpBackendMetricsState(); recordRead("xx", "auth", "miss", 1.2, "I18N.BACKEND_LOCALE_NOT_AVAILABLE", 404); const state = getHttpBackendMetricsState(); console.log(state.readErrorsTotal); // → [{ attributes: { code: "I18N.BACKEND_LOCALE_NOT_AVAILABLE", status: "404" } }] ``` ## API Reference - `getHttpBackendMetrics(): { readDurationMs, readTotal, readErrorsTotal }` — idempotent factory. - `recordRead(locale, namespace, outcome, durationMs, errorCode?, status?)` — emit + ring-record. - `getHttpBackendMetricsState(): HttpBackendMetricsState` — frozen snapshot. - `resetHttpBackendMetricsState()` / `resetHttpBackendMetricsCache()` — test helpers. ## Implementation Notes `status` is encoded as a string attribute so OTel SDK aggregators can union it with the `code` label without numeric coercion ambiguity. The counter cardinality is bounded by the small `I18N.*` error-code set times a typical handful of HTTP statuses (404 / 500 / 502 / 503), which stays well below downstream backend high-cardinality limits. The cached instruments survive across `recordRead` calls inside one process — the `resetHttpBackendMetricsCache` helper exists purely so tests can verify the cache-hit path is exercised.