first commit
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# DisplayName observability
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
The DisplayName formatter exports two OpenTelemetry instruments and a
|
||||
small in-memory state ring so spec-conformance tests can assert exact
|
||||
attribute payloads without standing up a full SDK exporter. The
|
||||
instruments match the canonical Wave-3 formatter contract — every
|
||||
sibling formatter (number, relative-time, list, date, currency,
|
||||
collator, segmenter) emits the same two metric names so dashboards
|
||||
and alerts compose cleanly across the family.
|
||||
|
||||
## Features
|
||||
|
||||
- Histogram `i18n.format.display_name.duration_ms` (unit `ms`) — per-format wall-clock time
|
||||
- Counter `i18n.format.cache_hit{formatter="display_name"}` — increments on cache reuse only
|
||||
- In-memory state ring (`getDisplayNameMetricsState()`) for spec-conformance assertions
|
||||
- `resetDisplayNameMetricsState()` test-only helper to clear the ring between cases
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { metrics } from "@opentelemetry/api";
|
||||
import { MeterProvider } from "@opentelemetry/sdk-metrics";
|
||||
// import your MetricReader / OTLP exporter ...
|
||||
|
||||
const provider = new MeterProvider({ readers: [/* reader */] });
|
||||
metrics.setGlobalMeterProvider(provider);
|
||||
|
||||
// Subsequent formatDisplayName calls now emit through your reader.
|
||||
import { formatDisplayName } from "@suaveplan/i18n-formatter-display-name";
|
||||
formatDisplayName("fr", "en-GB", { type: "language" });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import {
|
||||
clearDisplayNameCache,
|
||||
formatDisplayName,
|
||||
} from "@suaveplan/i18n-formatter-display-name";
|
||||
import {
|
||||
getDisplayNameMetricsState,
|
||||
resetDisplayNameMetricsState,
|
||||
} from "@suaveplan/i18n-formatter-display-name";
|
||||
|
||||
it("emits histogram + cache-hit counter", () => {
|
||||
clearDisplayNameCache();
|
||||
resetDisplayNameMetricsState();
|
||||
formatDisplayName("fr", "en-GB", { type: "language" });
|
||||
formatDisplayName("fr", "en-GB", { type: "language" });
|
||||
const state = getDisplayNameMetricsState();
|
||||
expect(state.durationSamples).toHaveLength(2);
|
||||
expect(state.cacheHitSamples).toHaveLength(1);
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `recordDisplayNameFormat(locale, type, style, durationMs): void`
|
||||
|
||||
Records the duration histogram sample. Tags: `locale`, `type`,
|
||||
`style`. Called internally by `formatDisplayName`; consumers do not
|
||||
need to invoke it directly.
|
||||
|
||||
### `recordDisplayNameCacheHit(): void`
|
||||
|
||||
Increments the cache-hit counter with the constant tag
|
||||
`{ formatter: "display_name" }`. Called internally on a cache hit.
|
||||
|
||||
### `getDisplayNameMetricsState(): DisplayNameMetricsState`
|
||||
|
||||
Returns the in-memory ring of `durationSamples` and `cacheHitSamples`.
|
||||
Used by spec-conformance tests to assert exact attribute payloads.
|
||||
|
||||
### `resetDisplayNameMetricsState(): void`
|
||||
|
||||
Clears both ring buffers. Test-only helper; call before the
|
||||
under-test code to assert exactly the samples your scenario
|
||||
generates.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The OTel meter is named `suaveplan.i18n.formatter.display_name`.
|
||||
Every formatter in the family has its own meter so OTel resource
|
||||
attributes can be tied per-package if a consumer chooses.
|
||||
- Sample dashboard query (PromQL/Grafana over OTLP):
|
||||
`histogram_quantile(0.99, sum(rate(i18n_format_display_name_duration_ms_bucket[5m])) by (le, locale))`
|
||||
- The in-memory ring is intentionally unbounded — tests are short and
|
||||
call `resetDisplayNameMetricsState()` between cases. A long-running
|
||||
test loop should call reset to avoid memory growth.
|
||||
- `style` defaults to `"long"` in the histogram tag when the caller
|
||||
omits it; `type` is always required so it is never defaulted.
|
||||
Reference in New Issue
Block a user