# `CCXT.Telemetry`
[🔗](https://github.com/ZenHive/ccxt_client/blob/main/lib/ccxt/telemetry.ex#L1)

Centralized telemetry contract for CCXT.

Single source of truth for all telemetry events emitted by the library.
Both `CCXT.HTTP` and `CCXT.CircuitBreaker` delegate event names here.

## Contract Version

Bumped on breaking changes to event names, measurements, or metadata shapes.
Consumers can assert compatibility at startup.

## Request Events

Emitted by `CCXT.HTTP` during HTTP request lifecycle.

### `[:ccxt, :request, :start]`

- **Measurements:** `%{system_time: integer()}`
- **Metadata:** `%{exchange: String.t(), method: atom(), path: String.t()}`

### `[:ccxt, :request, :stop]`

- **Measurements:** `%{duration: integer()}` (native time units)
- **Metadata:** `%{exchange: String.t(), method: atom(), path: String.t(), status: integer()}`

### `[:ccxt, :request, :exception]`

- **Measurements:** `%{duration: integer()}` (native time units)
- **Metadata:** `%{exchange: String.t(), method: atom(), path: String.t(), kind: atom(), reason: term()}`

## Circuit Breaker Events

Emitted by `CCXT.CircuitBreaker` on state transitions.

### `[:ccxt, :circuit_breaker, :open]`

- **Measurements:** `%{system_time: integer()}`
- **Metadata:** `%{exchange: String.t()}`

### `[:ccxt, :circuit_breaker, :closed]`

- **Measurements:** `%{system_time: integer()}`
- **Metadata:** `%{exchange: String.t()}`

### `[:ccxt, :circuit_breaker, :rejected]`

- **Measurements:** `%{system_time: integer()}`
- **Metadata:** `%{exchange: String.t()}`

## Rate Limiter Events

Emitted by `CCXT.HTTP` when rate limiting is triggered.

### `[:ccxt, :rate_limiter, :throttled]`

- **Measurements:** `%{delay_ms: integer(), cost: number()}`
- **Metadata:** `%{exchange: String.t()}`

# `attach`

```elixir
@spec attach(String.t(), (list(), map(), map(), term() -&gt; any()), term()) ::
  :ok | {:error, :already_exists}
```

Attaches a handler to all CCXT telemetry events.

Wraps `:telemetry.attach_many/4` with `events/0` as the event list.

## Parameters

- `handler_id` - Unique string identifying this handler
- `handler_fn` - Function of arity 4: `(event, measurements, metadata, config)`
- `config` - Optional handler config (default: `nil`)

# `circuit_breaker_closed`

```elixir
@spec circuit_breaker_closed() :: [atom()]
```

Event name for circuit breaker closed: `[:ccxt, :circuit_breaker, :closed]`.

# `circuit_breaker_events`

```elixir
@spec circuit_breaker_events() :: [[atom()]]
```

Returns the 3 circuit breaker event names.

# `circuit_breaker_open`

```elixir
@spec circuit_breaker_open() :: [atom()]
```

Event name for circuit breaker open: `[:ccxt, :circuit_breaker, :open]`.

# `circuit_breaker_rejected`

```elixir
@spec circuit_breaker_rejected() :: [atom()]
```

Event name for circuit breaker rejected: `[:ccxt, :circuit_breaker, :rejected]`.

# `contract_version`

```elixir
@spec contract_version() :: pos_integer()
```

Returns the telemetry contract version.

Bumped on breaking changes to event names, measurements, or metadata shapes.

    if CCXT.Telemetry.contract_version() != 1 do
      raise "Incompatible CCXT telemetry contract"
    end

# `detach`

```elixir
@spec detach(String.t()) :: :ok | {:error, :not_found}
```

Detaches a previously attached handler by ID.

# `events`

```elixir
@spec events() :: [[atom()]]
```

Returns all telemetry event names.

# `rate_limiter_events`

```elixir
@spec rate_limiter_events() :: [[atom()]]
```

Returns the rate limiter event names.

# `rate_limiter_throttled`

```elixir
@spec rate_limiter_throttled() :: [atom()]
```

Event name for rate limiter throttled: `[:ccxt, :rate_limiter, :throttled]`.

# `request_events`

```elixir
@spec request_events() :: [[atom()]]
```

Returns the 3 HTTP request event names.

# `request_exception`

```elixir
@spec request_exception() :: [atom()]
```

Event name for request exception: `[:ccxt, :request, :exception]`.

# `request_start`

```elixir
@spec request_start() :: [atom()]
```

Event name for request start: `[:ccxt, :request, :start]`.

# `request_stop`

```elixir
@spec request_stop() :: [atom()]
```

Event name for request stop: `[:ccxt, :request, :stop]`.

---

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