# `Rulestead.Telemetry`
[🔗](https://github.com/szTheory/rulestead/blob/v1.0.0/lib/rulestead/telemetry.ex#L2)

Telemetry helpers and the locked 1.x public event catalog for Rulestead.

`Rulestead.Telemetry` is stable in the 1.x contract (`api_stability.md` —
"Stable rulestead Modules"). It wraps `:telemetry` with Rulestead-aware
metadata normalisation and provides the canonical event names emitted by the
runtime.

## Event Catalog (stable, 1.x)

All events follow the `[:rulestead | rest]` prefix convention.

| Event | When emitted |
|-------|-------------|
| `[:rulestead, :eval, :decide, :stop]` | After every flag evaluation |
| `[:rulestead, :admin, :scheduled_execution, :*]` | Scheduled governance executions |
| `[:rulestead, :admin, :webhook_outbound, :*]` | Outbound webhook deliveries |

Event names and their documented metadata keys are **stable for 1.x**.
Adding a new event name is a minor change; removing or renaming one is a
breaking change.

## Attaching handlers

    Rulestead.Telemetry.attach_many(
      "my-app-rulestead-handler",
      [[:rulestead, :eval, :decide, :stop]],
      &MyApp.Telemetry.handle_event/4,
      nil
    )

Use `detach/1` with the same handler ID to remove a handler.

## Internal use

`span/3`, `execute/3`, and the `*_metadata` helpers are used internally by
the Rulestead runtime. They are part of the public module but primarily exist
to normalise metadata; most adopters only need `attach_many/4` and `detach/1`.

# `event_name`

```elixir
@type event_name() :: [atom()]
```

# `event_prefix`

```elixir
@type event_prefix() :: [atom()]
```

# `metadata`

```elixir
@type metadata() :: map()
```

# `attach_many`

```elixir
@spec attach_many(term(), [event_name()], :telemetry.handler_function(), term()) ::
  :ok | {:error, term()}
```

# `base_metadata`

```elixir
@spec base_metadata(
  map() | nil,
  Rulestead.Context.t() | map() | keyword() | nil,
  map()
) :: map()
```

# `command_metadata`

```elixir
@spec command_metadata(
  struct(),
  map()
) :: map()
```

# `detach`

```elixir
@spec detach(term()) :: :ok
```

# `dispatch`

```elixir
@spec dispatch(event_name(), map(), metadata(), event_name()) :: :ok
```

# `execute`

```elixir
@spec execute(event_name(), map(), metadata()) :: :ok
```

# `governance_metadata`

```elixir
@spec governance_metadata(
  struct(),
  map()
) :: map()
```

# `guardrail_metadata`

```elixir
@spec guardrail_metadata(map(), map()) :: map()
```

# `metadata`

```elixir
@spec metadata(map()) :: map()
```

# `result_metadata`

```elixir
@spec result_metadata(
  Rulestead.Result.t(),
  Rulestead.Context.t() | map() | keyword() | nil,
  map()
) ::
  map()
```

# `runtime_metadata`

```elixir
@spec runtime_metadata(map(), map()) :: map()
```

# `scheduled_execution_event`

```elixir
@spec scheduled_execution_event(atom() | binary()) :: event_name()
```

# `scheduled_execution_metadata`

```elixir
@spec scheduled_execution_metadata(map(), map()) :: map()
```

# `span`

```elixir
@spec span(event_prefix(), metadata(), (-&gt; {term(), metadata()} | term())) :: term()
```

# `webhook_delivery_event`

```elixir
@spec webhook_delivery_event(atom(), map(), map()) :: :ok
```

# `webhook_metadata`

```elixir
@spec webhook_metadata(map(), map()) :: map()
```

# `webhook_outbound_metadata`

```elixir
@spec webhook_outbound_metadata(map(), map()) :: map()
```

---

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