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

This plugin captures HTTP request metrics emitted by `Plug.Router` and `Plug.Telemetry`.

This plugin is heavily inspired on plugin `Plug.Cowboy`, and exposes the following metric group:
 - `:plug_router_http_event_metrics`

## Plugin options

- `routers`: **Required** This is a list with the full module names of your Routers (e.g MyAppWeb.Router).
 Metrics produced by routers not in this list will be discarded.

- `event_prefix`: **Required**, allows you to set the event prefix defined in your `Plug.Telemetry` configuration:

- `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.

```
defmodule WebApp.Router do
  use Plug.Router

  plug PromEx.Plug, prom_ex_module: WebApp.PromEx, path: "/metrics"
  plug Plug.Telemetry, event_prefix: [:webapp, :router]
  ...
end
```

With the above configuration, this plugin will subscribe to `[:webapp, :router, :stop]` telemetry events
produced by `Plug.Telemetry`. These events will be fired **before** the response is actually sent, therefore this
plugin will be able to export response body size metrics, since the `Plug.Conn` struct in the metadata of the
telemetry measurement still contains the response body.

However, `Plug.Telemetry` does not use `:telemetry.span/3`, which means the `:stop` event might not always be fired
(eg. if the process handling the request crashes). For this reason, this PromEx plugin also subscribes to
`[:plug, :router_dispatch, :exception]` telemetry events fired by `Plug.Router`, which are fired within a
`:telemetry.span/3` call.

Unfortunately, we cannot safely rely on `[:plug, :router_dispatch, :stop]` events produced by `Plug.Router` since
these are fired **after** the response is sent (as opposed to `Plug.Telemetry` `:stop` events). As a consequence,
the response body is no longer available in the `Plug.Conn` struct attached to the telemetry measurement metadata.

- `metric_prefix`: This option is OPTIONAL and is used to override the default metric prefix of
 `[otp_app, :prom_ex, :plug_router]`. If this changes you will also want to set `plug_router_metric_prefix`
 in your `dashboard_assigns` to the snakecase version of your prefix, the default
 `plug_router_metric_prefix` is `{otp_app}_prom_ex_plug_router`.
- `ignore_routes`: This option is OPTIONAL and is used to ignore certain paths.

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

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

  alias PromEx.Plugins

  @impl true
  def plugins do
    [
      ...
      {Plugins.PlugRouter,
        event_prefix: [:webapp, :router], metric_prefix: [:prom_ex, :router], routers: [WebApp.Router]}
    ]
  end

  @impl true
  def dashboard_assigns do
    [
      datasource_id: "...",
      plug_router_metric_prefix: "prom_ex_router"
    ]
  end

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

To ignore certain paths, pass a list of routes using the `:ignore_routes` option

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

  @impl true
  def plugins do
    [
      ...
      {PromEx.Plugins.PlugRouter,
        event_prefix: [:webapp, :router], metric_prefix: [:prom_ex, :router], routers: [WebApp.Router],
        ignore_routes: ["/metrics"]}
    ]
  end

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

---

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