Files
skills/docs/localization/i18n/i18n-formatter-currency/src/observability/observability.md
2026-05-29 08:20:56 +01:00

3.9 KiB

CurrencyFormatter Observability

(no submodules)

Purpose

Per-package OpenTelemetry instruments for @suaveplan/i18n-formatter-currency. Exposes a histogram (i18n.format.currency.duration_ms) recording wall-clock duration of every formatCurrency call (tagged with locale, currency, and display) and a counter (i18n.format.cache_hit) tagged with formatter: "currency" that increments on every cache reuse.

The currency formatter introduces these instruments as part of the Wave 3 uplift — the monolith currently emits no OTel for currency formatting. The two instruments are constructed once via metrics.getMeter and are lazily initialised on first record so cold-start latency stays low.

Features

  • Lazy instrument construction
  • Stable histogram name i18n.format.currency.duration_ms with attributes { locale, currency, display }
  • Stable counter name i18n.format.cache_hit with attributes { formatter: "currency" }
  • In-memory sample ring (currencyDurationSamples, cacheHitSamples)
  • resetCurrencyFormatMetricsState() clears both arrays so tests stay isolated

Usage: Basic Example

import {
    recordCurrencyFormat,
    recordCurrencyCacheHit,
    getCurrencyFormatMetricsState,
    resetCurrencyFormatMetricsState,
} from "@suaveplan/i18n-formatter-currency/observability";

resetCurrencyFormatMetricsState();
recordCurrencyFormat("en-US", "USD", "symbol", 0.4);
recordCurrencyCacheHit();
const state = getCurrencyFormatMetricsState();
state.currencyDurationSamples.length; // 1
state.cacheHitSamples.length; // 1

Usage: Advanced Example — Asserting OTel emission in a test

import { describe, expect, it } from "@suaveplan/testing/runner";
import {
    formatCurrency,
    clearCurrencyFormatterCache,
} from "@suaveplan/i18n-formatter-currency";
import {
    getCurrencyFormatMetricsState,
    resetCurrencyFormatMetricsState,
} from "@suaveplan/i18n-formatter-currency/observability";

describe("metrics emission", () => {
    it("emits duration histogram and cache-hit counter", { timeout: 5000 }, () => {
        clearCurrencyFormatterCache();
        resetCurrencyFormatMetricsState();
        formatCurrency(42, "USD", "en-US");
        formatCurrency(42, "USD", "en-US");
        const state = getCurrencyFormatMetricsState();
        expect(state.currencyDurationSamples).toHaveLength(2);
        expect(state.cacheHitSamples).toHaveLength(1);
    });
});

API Reference

recordCurrencyFormat(locale, currency, display, durationMs): void

Records one observation on the i18n.format.currency.duration_ms histogram and pushes a { attributes: { locale, currency, display } } entry into the in-memory sample ring.

recordCurrencyCacheHit(): void

Adds 1 to the i18n.format.cache_hit counter with formatter: "currency" and pushes a matching entry into the in-memory sample ring.

getCurrencyFormatMetricsState(): CurrencyFormatMetricsState

Returns the in-memory sample ring (live reference — do not mutate).

resetCurrencyFormatMetricsState(): void

Empties both sample arrays in place.

CurrencyFormatMetricsState

{ currencyDurationSamples: FormatMetricSample[]; cacheHitSamples: FormatMetricSample[] } where FormatMetricSample = { attributes: Record<string, string | number> }.

Implementation Notes

The instruments are built lazily so consumers who never call formatCurrency do not pay the OTel meter-lookup cost. The cache check is a strict identity check against the closure-scoped cached slot — once built, the instruments are never rebuilt, even across resetCurrencyFormatMetricsState calls.

The currency attribute is the ISO 4217 code ("USD", "EUR", "JPY"); the display attribute is the resolved display mode ("symbol", "code", "name", "narrowSymbol"). Both are included in the histogram tags so consumers can dashboard the most-formatted currencies and the most-used display modes per locale.