# `PhoenixGenApi.Telemetry`
[🔗](https://github.com/ohhi-vn/phoenix_gen_api/blob/main/lib/phoenix_gen_api/telemetry.ex#L1)

Telemetry integration for PhoenixGenApi.

This module provides a central place to discover, attach to, and
handle all telemetry events emitted by PhoenixGenApi.

## Events

### Executor

| Event | Measurements | Metadata |
|-------|-------------|----------|
| `[:phoenix_gen_api, :executor, :request, :start]` | `%{system_time: integer()}` | `%{request_id: String.t(), request_type: String.t(), service: String.t(), user_id: String.t()}` |
| `[:phoenix_gen_api, :executor, :request, :stop]` | `%{duration_us: integer()}` | `%{request_id: String.t(), request_type: String.t(), service: String.t(), user_id: String.t(), success: boolean(), async: boolean()}` |
| `[:phoenix_gen_api, :executor, :request, :exception]` | `%{duration_us: integer()}` | `%{request_id: String.t(), request_type: String.t(), service: String.t(), user_id: String.t(), kind: atom(), reason: String.t(), stacktrace: Exception.stacktrace()}` |
| `[:phoenix_gen_api, :executor, :retry]` | `%{attempt: non_neg_integer()}` | `%{mode: :same_node or :all_nodes, type: :local or :remote}` + optional `nodes: list()` for remote retries |

### Rate Limiter

| Event | Measurements | Metadata |
|-------|-------------|----------|
| `[:phoenix_gen_api, :rate_limiter, :check]` | `%{duration_us: integer()}` | `%{request_id: String.t(), user_id: String.t(), service: String.t(), request_type: String.t(), result: :ok or {:error, :rate_limited, map()}}` |
| `[:phoenix_gen_api, :rate_limiter, :exceeded]` | `%{retry_after_ms: non_neg_integer()}` | `%{key: String.t(), scope: :global or {String.t(), String.t()}, max_requests: non_neg_integer(), current_requests: non_neg_integer(), request_id: String.t(), user_id: String.t()}` |
| `[:phoenix_gen_api, :rate_limiter, :reset]` | `%{}` | `%{key: String.t(), scope: atom(), rate_limit_key: atom()}` |
| `[:phoenix_gen_api, :rate_limiter, :cleanup]` | `%{duration_us: integer(), cleaned_entries: non_neg_integer()}` | `%{global_limits_count: non_neg_integer(), api_limits_count: non_neg_integer()}` |

### Hooks

| Event | Measurements | Metadata |
|-------|-------------|----------|
| `[:phoenix_gen_api, :hook, :before, :start]` | `%{system_time: integer()}` | `%{module: module(), function: atom(), type: :before}` |
| `[:phoenix_gen_api, :hook, :before, :stop]` | `%{duration_us: integer()}` | `%{module: module(), function: atom(), type: :before}` |
| `[:phoenix_gen_api, :hook, :before, :exception]` | `%{duration_us: integer()}` | `%{module: module(), function: atom(), type: :before, kind: atom(), reason: String.t(), stacktrace: Exception.stacktrace()}` |
| `[:phoenix_gen_api, :hook, :after, :start]` | `%{system_time: integer()}` | `%{module: module(), function: atom(), type: :after}` |
| `[:phoenix_gen_api, :hook, :after, :stop]` | `%{duration_us: integer()}` | `%{module: module(), function: atom(), type: :after}` |
| `[:phoenix_gen_api, :hook, :after, :exception]` | `%{duration_us: integer()}` | `%{module: module(), function: atom(), type: :after, kind: atom(), reason: String.t(), stacktrace: Exception.stacktrace()}` |

### Worker Pool

| Event | Measurements | Metadata |
|-------|-------------|----------|
| `[:phoenix_gen_api, :worker_pool, :task, :start]` | `%{system_time: integer()}` | `%{pool_name: atom()}` |
| `[:phoenix_gen_api, :worker_pool, :task, :stop]` | `%{duration_us: integer()}` | `%{pool_name: atom()}` |
| `[:phoenix_gen_api, :worker_pool, :task, :exception]` | `%{duration_us: integer()}` | `%{pool_name: atom(), kind: atom(), reason: term(), stacktrace: Exception.stacktrace()}` |
| `[:phoenix_gen_api, :worker_pool, :circuit_breaker, :open]` | `%{}` | `%{pool_name: atom(), consecutive_failures: non_neg_integer()}` |
| `[:phoenix_gen_api, :worker_pool, :circuit_breaker, :close]` | `%{}` | `%{pool_name: atom()}` |

### Config Cache

| Event | Measurements | Metadata |
|-------|-------------|----------|
| `[:phoenix_gen_api, :config, :pull, :start]` | `%{system_time: integer()}` | `%{service: String.t() | atom()}` |
| `[:phoenix_gen_api, :config, :pull, :stop]` | `%{duration_us: integer(), count: non_neg_integer()}` | `%{service: String.t() | atom(), version: String.t() | nil}` |
| `[:phoenix_gen_api, :config, :push]` | `%{count: non_neg_integer()}` | `%{service: String.t() | atom(), version: String.t()}` |
| `[:phoenix_gen_api, :config, :add]` | `%{}` | `%{service: String.t() | atom(), request_type: String.t(), version: String.t()}` |
| `[:phoenix_gen_api, :config, :batch_add]` | `%{count: non_neg_integer()}` | `%{service: String.t() | atom()}` |
| `[:phoenix_gen_api, :config, :delete]` | `%{}` | `%{service: String.t() | atom(), request_type: String.t(), version: String.t()}` |
| `[:phoenix_gen_api, :config, :clear]` | `%{}` | `%{service: atom(), request_type: atom(), version: atom()}` |
| `[:phoenix_gen_api, :config, :disable]` | `%{}` | `%{service: String.t() | atom(), request_type: String.t(), version: String.t()}` |
| `[:phoenix_gen_api, :config, :enable]` | `%{}` | `%{service: String.t() | atom(), request_type: String.t(), version: String.t()}` |

## Usage

    # Attach a handler to all events
    PhoenixGenApi.Telemetry.attach_all("my-handler", &MyApp.handle_event/4)

    # Attach only to executor events
    PhoenixGenApi.Telemetry.attach_executor("my-handler", &MyApp.handle_event/4)

    # Attach the built-in debug logger
    PhoenixGenApi.Telemetry.attach_default_logger()

    # Detach everything for a handler ID
    PhoenixGenApi.Telemetry.detach_all("my-handler")

# `attach_all`

```elixir
@spec attach_all(String.t(), function(), map()) :: :ok
```

Attaches a handler function to all PhoenixGenApi telemetry events.

# `attach_config`

```elixir
@spec attach_config(String.t(), function(), map()) :: :ok
```

Attaches a handler to config cache events.

# `attach_default_logger`

```elixir
@spec attach_default_logger(String.t()) :: :ok
```

Attaches a default console logger that logs all telemetry events at debug level.

# `attach_executor`

```elixir
@spec attach_executor(String.t(), function(), map()) :: :ok
```

Attaches a handler to executor events.

# `attach_hooks`

```elixir
@spec attach_hooks(String.t(), function(), map()) :: :ok
```

Attaches a handler to hook events.

# `attach_many`

```elixir
@spec attach_many(String.t(), [[atom()]], function(), map()) :: :ok
```

Attaches a handler to a list of events.

# `attach_rate_limiter`

```elixir
@spec attach_rate_limiter(String.t(), function(), map()) :: :ok
```

Attaches a handler to rate limiter events.

# `attach_worker_pool`

```elixir
@spec attach_worker_pool(String.t(), function(), map()) :: :ok
```

Attaches a handler to worker pool events.

# `detach_all`

```elixir
@spec detach_all(String.t()) :: :ok
```

Detaches all handlers for the given handler ID.

# `detach_default_logger`

```elixir
@spec detach_default_logger(String.t()) :: :ok
```

Detaches the default console logger.

# `execute`

```elixir
@spec execute([atom()], map(), map()) :: :ok
```

Emits a telemetry event. Thin wrapper around `:telemetry.execute/3`.

# `list_events`

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

Returns the full list of telemetry events emitted by PhoenixGenApi.

# `span`

```elixir
@spec span([atom()], map(), function()) :: any()
```

Wraps a function in a telemetry span. Thin wrapper around `:telemetry.span/3`.

---

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