# `PromEx.Plugins.Phoenix`
[🔗](https://github.com/akoutmos/prom_ex/blob/master/lib/prom_ex/plugins/phoenix.ex#L2)

This plugin captures metrics emitted by Phoenix. Specifically, it captures HTTP request metrics and
Phoenix channel metrics.

## Plugin options

This plugin supports the following options:
- `metric_prefix`: This option is OPTIONAL and is used to override the default metric prefix of
  `[otp_app, :prom_ex, :phoenix]`. If this changes you will also want to set `phoenix_metric_prefix`
  in your `dashboard_assigns` to the snakecase version of your prefix, the default
  `phoenix_metric_prefix` is `{otp_app}_prom_ex_phoenix`.

- `duration_unit`: This is an OPTIONAL option and is a `Telemetry.Metrics.time_unit()`. It can be one of:
  `:second | :millisecond | :microsecond | :nanosecond`. It is `:millisecond` by default.

### Single Endpoint/Router
- `router`: This option is REQUIRED and is the full module name of your Phoenix Router (e.g MyAppWeb.Router).

- `endpoint`: This is a REQUIRED option and is the full module name of your Phoenix Endpoint (e.g MyAppWeb.Endpoint).

- `event_prefix`: This option is OPTIONAL and allows you to set the event prefix for the Telemetry events. This
  value should align with what you pass to `Plug.Telemetry` in your `endpoint.ex` file (see the plug docs
  for more information https://hexdocs.pm/plug/Plug.Telemetry.html) This value should align with what you pass
  to `Plug.Telemetry` in your `endpoint.ex` file (see the plug docs for more
  information https://hexdocs.pm/plug/Plug.Telemetry.html)

- `additional_routes`: This option is OPTIONAL and allows you to specify route path labels for applications routes
  not defined in your Router module.

  For example, if you want to track telemetry events for a plug in your
  `endpoint.ex` file, you can provide a keyword list with the structure `[some-route: ~r(/some-path)]` and any
  time that the route is called and the plug handles the call, the path label for this particular Prometheus metric
  will be set to `some-route`. You can pass in either a regular expression or a string to match the incoming
  request.

- `additional_tags`: This option is OPTIONAL and allows you to specify additional tags (as a list of atoms) to be
  added to the HTTP metrics. This is useful if you want to add additional context to your metrics. The additional
  tag values will be taken from the private key `:prom_ex_[tag]` on the connection struct. Defaults to `[]`.

  For example, if you want to report the authentication status of the request, you can set
  `additional_tags: [:authenticated]` and use `Plug.Conn.put_private(conn, :prom_ex_authenticated, true)`
  in a controller or plug to add the tag to the metrics.

- `normalize_event_name`: This option is OPTIONAL and allows you to remap the channel event names to a different
  name. This is useful if you want to limit the number or size of event names that are emitted.

  For example, if you have a channel and only want to emit unique metrics for the 'join' and 'leave' events, you can
  map those events to themselves and map all other events to an 'unknown' event.

  ```elixir
    fn
      "join" -> "join"
      "leave" -> "leave"
      _ -> "unknown"
    end
  ```

#### Example plugin configuration

```elixir
{
  PromEx.Plugins.Phoenix,
  endpoint: MyApp.Endpoint,
  router: MyAppWeb.Public.Router,
  event_prefix: [:admin, :endpoint],
  normalize_event_name: fn event -> event end)
}
```

### Multiple Endpoints/Router

- `endpoints`: This accepts a list of per Phoenix Endpoint options `{endpoint_name, endpoint_opts}`
  - `endpoint_name`: This option is REQUIRED and is the full module name of your Phoenix Endpoint (e.g MyAppWeb.Endpoint).

  - `endpoint_opts`: Per endpoint plugin options:
    - `:routers`: This option is REQUIRED and lists all of routers modules for the endpoint, the HTTP metrics will
      be augmented with controller/action/path information from the routers.

    - `:event_prefix`: This option is OPTIONAL and allows you to set the event prefix for the Telemetry events. This
    value should align with what you pass to `Plug.Telemetry` in the  corresponding endpoint module (see the plug docs
    for more information https://hexdocs.pm/plug/Plug.Telemetry.html)

    - `:additional_routes`: This option is OPTIONAL and allows you to specify route path labels for applications routes
    not defined in your Router modules for the corresponding endpoint.

    - `additional_tags`: This option is OPTIONAL and allows you to specify additional tags (as a list of atoms) to be
      added to the HTTP metrics. This is useful if you want to add additional context to your metrics. The additional
      tag values will be taken from the private key `:prom_ex_[tag]` on the connection struct. Defaults to `[]`.

      For example, if you want to report the authentication status of the request, you can set
      `additional_tags: [:authenticated]` and use `Plug.Conn.put_private(conn, :prom_ex_authenticated, true)`
      in a controller or plug to add the tag to the metrics.

#### Example plugin configuration

```elixir
{
  PromEx.Plugins.Phoenix,
  endpoints: [
    {MyApp.Endpoint, routers: [MyAppWeb.Public.Router]},
    {MyApp.Endpoint2, routers: [MyAppWeb.Admin.Router], event_prefix: [:admin, :endpoint]}
  ]
}
```

## Metric Groups

This plugin exposes the following metric groups:
- `:phoenix_http_event_metrics`
- `:phoenix_channel_event_metrics`
- `:phoenix_socket_event_metrics`
- `:phoenix_endpoint_metrics`

## Usage

To use plugin in your application, add the following to your PromEx module:

```elixir
defmodule WebApp.PromEx do
  use PromEx, otp_app: :web_app

  @impl true
  def plugins do
    [
      ...
      {
        PromEx.Plugins.Phoenix,
        endpoint: MyApp.Endpoint,
        router: MyAppWeb.Public.Router
      }
    ]
  end

  @impl true
  def dashboards do
    [
      ...
      {:prom_ex, "phoenix.json"}
    ]
  end
end
```

When working with multiple Phoenix routers use the `endpoints` option instead:

```elixir
defmodule WebApp.PromEx do
  use PromEx, otp_app: :web_app

  @impl true
  def plugins do
    [
      ...
      {
        PromEx.Plugins.Phoenix,
        endpoints: [
          {MyApp.Endpoint, routers: [MyAppWeb.Public.Router]},
          {MyApp.Endpoint2, routers: [MyAppWeb.Admin.Router], event_prefix: [:admin, :endpoint]}
        ]
      }
    ]
  end

  @impl true
  def dashboards do
    [
      ...
      {:prom_ex, "phoenix.json"}
    ]
  end
end
```

---

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