first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
# SpritePlayerTelemetry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`SpritePlayerTelemetry` is the OTel-facing facade that `SpritePlayer` opens for every public invocation. It manages one tracer plus three metric instruments — a counter, an observable gauge, and a histogram — so consumers running a real OTel SDK can plug spans and metrics straight into their pipeline without any glue code in the player.
The facade is constructed with a `getVoiceCount` callback rather than a direct reference to the player, so it can be unit-tested in isolation and so the gauge callback closes over a stable function reference for the lifetime of the player.
## Features
- One tracer (`audio-sprite-player`) for spans named `audio-sprite-player.play`.
- One counter (`audio_sprite_player.play_total`) keyed by `sprite.entry_name`.
- One observable gauge (`audio_sprite_player.voices_active`) driven by the injected voice-count getter.
- One histogram (`audio_sprite_player.play_duration_ms`) recorded on `complete` events.
- Spans are closed via `recordSuccess` / `recordFailure`, with `error.code` attribute attached on the failure path.
## Usage: Basic Example
```ts
import { SpritePlayerTelemetry } from "@suaveplan/audio-sprite-player";
const telemetry = new SpritePlayerTelemetry(() => activeVoices.size);
const h = telemetry.startPlay("hit");
try {
await adapter.play(/* ... */);
telemetry.recordSuccess(h, { entryName: "hit" });
} catch (err) {
telemetry.recordFailure(h, {
entryName: "hit",
errorCode: "AUDIO_SPRITE_PLAYER.PLAYBACK_FAILED",
});
throw err;
}
```
## Usage: Advanced Example
```ts
import { createSpritePlayer } from "@suaveplan/audio-sprite-player";
const player = createSpritePlayer({ adapter });
// Consumers wanting to inspect the live voice count without subscribing
// to events can call _runGaugeCallback (the OTel SDK normally drives it).
player.events.on("voice-stolen", () => {
player.telemetry._runGaugeCallback();
console.log(player.telemetry.observedVoiceCount);
});
// recordCompletion is also exposed for adapter authors who want to drive
// the histogram from the engine-side "voice ended" signal directly.
player.telemetry.recordCompletion(450, "hit");
```
## API Reference
### `new SpritePlayerTelemetry(getVoiceCount: () => number)`
Constructs the facade. The callback is invoked by the OTel SDK whenever it polls the observable gauge.
### `startPlay(entryName): PlayTelemetryHandle`
Opens a span and records the wall-clock start time.
### `recordSuccess(handle, attrs): void`
Increments the counter, sets `OK` status, closes the span.
### `recordFailure(handle, attrs): void`
Sets `ERROR` status, attaches `error.code` attribute when provided, closes the span. The counter is not incremented on failure (`play_total` reflects accepted plays only).
### `recordCompletion(durationMs, entryName): void`
Records an observation on the duration histogram.
### `observedVoiceCount: number`
Last value observed by the gauge callback.
### `_runGaugeCallback(): void`
Test-visible hook that drives the gauge callback synchronously. Useful in environments without a real OTel SDK — the default `@opentelemetry/api` ships a noop SDK that never polls the gauge.
## Implementation Notes
- The default `@opentelemetry/api` package provides a noop tracer and meter when no SDK is installed; this facade still records the calls correctly via the noop instruments, so calling code never has to gate on SDK presence.
- The gauge callback is stored as a member so its identity is stable for the lifetime of the player; rebinding on every observation would defeat OTel's deduplication.
- `recordFailure` deliberately does not increment the counter — a failed play is not a play.