# `X402.Telemetry.Metrics`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/telemetry/metrics.ex#L2)

`Telemetry.Metrics` definitions for every x402 telemetry event.

Ready to hand to Phoenix LiveDashboard or any `Telemetry.Metrics`
reporter, without this library depending on Phoenix:

    # router.ex
    live_dashboard "/dashboard", metrics: X402.Telemetry.Metrics

    # or a reporter
    {TelemetryMetricsPrometheus, metrics: X402.Telemetry.Metrics.metrics()}

Requires the optional `:telemetry_metrics` dependency
(`{:telemetry_metrics, "~> 1.0"}`). `X402.Telemetry.Stats` provides a
dependency-free aggregator for deployments without a reporter.

## Definitions

Every event listed by `X402.Telemetry.events/0` is covered:

* emit-style events (`%{count: 1}` measurements) become counters
  tagged by `:status`, plus a `:reason` tag on the client, RPC, local
  verification, and engine events;
* `[:x402, :plug, ...]` and `[:x402, :mcp, ...]` events become counters
  tagged by route/tool and, for rejections, by `:reason`;
* `[:x402, :facilitator, operation, :stop]` spans become a counter, a
  summary, and a distribution of `:duration` in milliseconds tagged by
  `:success`, and `:exception` events a counter tagged by `:kind`;
* `[:x402, :facilitator, :failover]` becomes a counter tagged by
  operation and reason.

Tag values that are error terms (tuples, structs) are reduced to an
atom with `reason_tag/1` so that a malformed payload cannot explode the
tag cardinality of a reporter.

# `metric`

```elixir
@type metric() :: Telemetry.Metrics.t()
```

A `Telemetry.Metrics` metric definition.

# `metrics`
*since 0.9.0* 

```elixir
@spec metrics() :: [metric()]
```

Returns metric definitions for every x402 telemetry event.

## Examples

    iex> metrics = X402.Telemetry.Metrics.metrics()
    iex> Enum.all?(metrics, &is_struct/1)
    true

# `metrics`
*since 0.9.0* 

```elixir
@spec metrics(keyword()) :: [metric()]
```

Returns metric definitions filtered by component.

## Options

* `:only` - Components to include (the second element of each event name).

* `:except` - Components to exclude.

## Examples

    iex> metrics = X402.Telemetry.Metrics.metrics(only: [:plug])
    iex> Enum.all?(metrics, &(Enum.at(&1.event_name, 1) == :plug))
    true

    iex> metrics = X402.Telemetry.Metrics.metrics(except: [:facilitator, :client])
    iex> Enum.any?(metrics, &(Enum.at(&1.event_name, 1) in [:facilitator, :client]))
    false

# `reason_tag`
*since 0.9.0* 

```elixir
@spec reason_tag(term()) :: atom() | String.t()
```

Reduces a `:reason` metadata value to a low-cardinality atom tag.

Tuples reduce to their first element when it is an atom, structs to
their `:type` field or module name, atoms and strings pass through, and
anything else becomes `:other`.

## Examples

    iex> X402.Telemetry.Metrics.reason_tag(:invalid_base64)
    :invalid_base64

    iex> X402.Telemetry.Metrics.reason_tag({:verification_failed, "insufficient_funds"})
    :verification_failed

    iex> X402.Telemetry.Metrics.reason_tag(%X402.Facilitator.Error{type: :timeout})
    :timeout

    iex> X402.Telemetry.Metrics.reason_tag(%{"weird" => true})
    :other

---

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