Initial Commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# `@suaveplan/i18n-backend-http/observability`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## 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.
|
||||
Reference in New Issue
Block a user