# `otel` _(no submodules)_ ## Purpose This module wires `@suaveplan/audio-decode-wav` into OpenTelemetry: it builds (and caches) the tracer, meter, counters and histogram the package emits, supports swapping the meter provider for tests, and exposes the two convenience recorders (`recordSuccess`, `recordError`) used by the decoder and the stream wrapper. Every public call in the package routes its telemetry through one of those two functions so the spec's `audio_decode_wav.*` instrument names are emitted from exactly one place. ## Features - `setAudioDecodeWavMeterProvider(provider)` overrides the meter provider; pass `undefined` to revert to the global. Resets the instrument cache so the next access binds to the new provider — essential for tests that snapshot per-test metrics. - Lazy-built, cached instruments via `getInstruments(force?)` — first call builds, subsequent calls return the cache unless `force === true`. - Three counters (`bytes_in_total`, `frames_out_total`, `errors_total`) and one histogram (`op_duration_ms`) on the `@suaveplan/audio-decode-wav` meter. - Tracer spans on the `@suaveplan/audio-decode-wav` tracer, named `audio_decode_wav.` where `op ∈ {"decodeWav", "stream.feed", "stream.flush"}`. - `recordSuccess(input)` and `recordError(input)` are the canonical emit points — both increment the duration histogram, the relevant counter, and start/end a span. ## Usage: Basic ```ts import { getInstruments, recordSuccess } from "@suaveplan/audio-decode-wav"; recordSuccess({ op: "decodeWav", bytesIn: 1024, framesOut: 256, durationMs: 1.2, }); const inst = getInstruments(); inst.tracer.startSpan("custom.span").end(); ``` ## Usage: Advanced ```ts import { resetInstruments, setAudioDecodeWavMeterProvider, } from "@suaveplan/audio-decode-wav"; const counters: Array<{ name: string; value: number }> = []; setAudioDecodeWavMeterProvider({ getMeter: () => ({ createCounter: (name) => ({ add: (v) => counters.push({ name, value: v }) }), createHistogram: () => ({ record: () => {} }), }), } as never); resetInstruments(); // run decode(), then assert against `counters` setAudioDecodeWavMeterProvider(undefined); resetInstruments(); ``` ## API Reference - `setAudioDecodeWavMeterProvider(provider: MeterProvider | undefined): void` — override the meter provider; clears the instrument cache. - `getInstruments(force?: boolean): AudioDecodeWavInstruments` — return the cached instruments (or rebuild if `force`). - `resetInstruments(): void` — drop the cache; next `getInstruments` rebuilds. - `recordSuccess(input: SuccessOpInput): void` — emit duration + bytes_in + frames_out + span for a successful op. - `recordError(input: ErrorOpInput): void` — emit duration + errors_total + span for a failed op. - `type AudioDecodeWavOp = "decodeWav" | "stream.feed" | "stream.flush"`. - `type AudioDecodeWavOutcome = "success" | "error"`. ## Implementation Notes The cache is module-scoped — there is exactly one set of instruments per process. Tests swap the provider via `setAudioDecodeWavMeterProvider` and call `resetInstruments()` to force a rebuild; the override pointer is read inside `getInstruments` so the swap takes effect on the next access. Span attributes include `audio_decode_wav.outcome` and either `audio_decode_wav.bytes_in`/`audio_decode_wav.frames_out` (success) or `audio_decode_wav.code` (error); these mirror the metric attribute keys so an OTel collector can join spans and metrics on the same dimension.