# `Dsxir.Telemetry`

Event-name constants and the `emit/3` helper for dsxir telemetry.

Documents the full event vocabulary and exposes a thin wrapper over
`:telemetry.execute/3`. Producers (predictors, adapters, optimizers, evaluate)
and subscribers (the `Dsxir.History` ETS handler, the upstream LM relay,
user-supplied handlers) attach as their consumers land.

## Event vocabulary

    [:dsxir, :predictor, :start]
    [:dsxir, :predictor, :stop]
    [:dsxir, :predictor, :exception]

    [:dsxir, :adapter, :format]
    [:dsxir, :adapter, :parse]
    [:dsxir, :adapter, :fallback]

    [:dsxir, :optimizer, :start]
    [:dsxir, :optimizer, :stop]
    [:dsxir, :optimizer, :trial]
    [:dsxir, :optimizer, :item_error]

    [:dsxir, :evaluate, :item]
    [:dsxir, :evaluate, :stop]

## Always-present keys

The `:error_class` metadata key on `[:dsxir, :predictor, :stop]` and
`[:dsxir, :predictor, :exception]` is always present, with value `nil` when no
error occurred. Subscribers should branch on `nil`, never on `Map.has_key?/2`.

Token measurements (`tokens_in`, `tokens_out`, `cost`) follow the same
always-present-nil convention on `[:dsxir, :predictor, :stop]`. They are
populated by `Dsxir.LM` implementations via the `Dsxir.LM.usage()` shape;
when the upstream provider did not report usage, the impl returns
`Dsxir.LM.empty_usage/0` (all three keys `nil`).

## Optimizer events

`[:dsxir, :optimizer, :start]`

  * **Measurements:** `%{system_time: integer()}`.
  * **Metadata:** `%{optimizer: module(), trainset_size: non_neg_integer(), error_class: nil}`.

`[:dsxir, :optimizer, :stop]`

  * **Measurements:** `%{duration: integer(), score: nil | float()}`. `score` is
    `nil` for optimizers that do not compute a holdout score during compile
    (e.g. `Dsxir.Optimizer.LabeledFewShot`, `Dsxir.Optimizer.BootstrapFewShot`);
    future optimizers (MIPROv2, GEPA) may populate it.
  * **Metadata:** `%{optimizer: module(), trainset_size: non_neg_integer(),
    error_class: nil | atom()}`. `error_class` is `nil` on success and the
    aggregated error class atom on failure.

`[:dsxir, :optimizer, :trial]`

  * **Measurements:** `%{score: float()}`. Coerced metric value for the trial.
  * **Metadata:** `%{optimizer: module(), round: pos_integer(),
    example_index: non_neg_integer(), kept: boolean(), error_class: nil}`.

`[:dsxir, :optimizer, :item_error]`

  * **Measurements:** `%{system_time: integer()}`.
  * **Metadata:** `%{optimizer: module(), round: pos_integer(),
    example_index: non_neg_integer(), error: Exception.t(),
    error_class: atom()}`.

Subscribers branch on `nil` for `score` and `error_class`; never on
`Map.has_key?/2`.

# `event`

```elixir
@type event() :: [atom(), ...]
```

# `adapter_fallback`

```elixir
@spec adapter_fallback() :: event()
```

Event name for `[:dsxir, :adapter, :fallback]`.

# `adapter_format`

```elixir
@spec adapter_format() :: event()
```

Event name for `[:dsxir, :adapter, :format]`.

# `adapter_parse`

```elixir
@spec adapter_parse() :: event()
```

Event name for `[:dsxir, :adapter, :parse]`.

# `emit`

```elixir
@spec emit(event(), map(), map()) :: :ok
```

Thin wrapper over `:telemetry.execute/3`.

# `evaluate_item`

```elixir
@spec evaluate_item() :: event()
```

Event name for `[:dsxir, :evaluate, :item]`.

# `evaluate_stop`

```elixir
@spec evaluate_stop() :: event()
```

Event name for `[:dsxir, :evaluate, :stop]`.

# `optimizer_item_error`

```elixir
@spec optimizer_item_error() :: event()
```

Event name for `[:dsxir, :optimizer, :item_error]`.

# `optimizer_start`

```elixir
@spec optimizer_start() :: event()
```

Event name for `[:dsxir, :optimizer, :start]`.

# `optimizer_stop`

```elixir
@spec optimizer_stop() :: event()
```

Event name for `[:dsxir, :optimizer, :stop]`.

# `optimizer_trial`

```elixir
@spec optimizer_trial() :: event()
```

Event name for `[:dsxir, :optimizer, :trial]`.

# `predictor_exception`

```elixir
@spec predictor_exception() :: event()
```

Event name for `[:dsxir, :predictor, :exception]`.

# `predictor_start`

```elixir
@spec predictor_start() :: event()
```

Event name for `[:dsxir, :predictor, :start]`.

# `predictor_stop`

```elixir
@spec predictor_stop() :: event()
```

Event name for `[:dsxir, :predictor, :stop]`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
