first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user