# `ZenWebsocket.LatencyStats`
[🔗](https://github.com/ZenHive/zen_websocket/blob/v0.4.2/lib/zen_websocket/latency_stats.ex#L1)

Bounded circular buffer for latency statistics calculation.

Maintains a fixed-size buffer of latency samples and provides
percentile calculations (p50, p99) for request/response timing.

Uses `:queue` for O(1) insertion with eviction of oldest samples
when capacity is reached. Percentile calculation requires sorting
(O(n log n)) but operates on bounded data.

## Telemetry Integration

This module is designed to work with ZenWebsocket's telemetry events,
providing aggregated latency metrics from individual measurements.

## API Functions
| Function | Arity | Description | Param Kinds |
| --- | --- | --- | --- |
| `summary` | 1 | Get a summary of latency statistics. | `stats: value` |
| `percentile` | 2 | Calculate a percentile from buffered latency samples. | `stats: value`, `percentile: value` |
| `add` | 2 | Add a latency sample to the buffer. | `stats: value`, `sample_ms: value` |
| `new` | 1 | Create a new latency stats buffer. | `opts: value` |

# `t`

```elixir
@type t() :: %ZenWebsocket.LatencyStats{
  count: non_neg_integer(),
  max_size: pos_integer(),
  samples: :queue.queue(non_neg_integer())
}
```

# `add`

```elixir
@spec add(t(), non_neg_integer()) :: t()
```

Adds a latency sample in milliseconds to the buffer.

Evicts the oldest sample if the buffer is at capacity.

## Examples

    iex> stats = ZenWebsocket.LatencyStats.new(max_size: 3)
    iex> stats = ZenWebsocket.LatencyStats.add(stats, 10)
    iex> stats = ZenWebsocket.LatencyStats.add(stats, 20)
    iex> stats.count
    2

# `new`

```elixir
@spec new(keyword()) :: t()
```

Creates a new latency stats buffer with configurable max size.

## Options

- `max_size` - Maximum number of samples to retain (default: 100)

## Examples

    iex> stats = ZenWebsocket.LatencyStats.new()
    iex> stats.max_size
    100

    iex> stats = ZenWebsocket.LatencyStats.new(max_size: 50)
    iex> stats.max_size
    50

# `percentile`

```elixir
@spec percentile(t(), number()) :: non_neg_integer() | nil
```

Calculates the specified percentile from buffered samples.

Returns `nil` if the buffer is empty.

## Examples

    iex> stats = ZenWebsocket.LatencyStats.new()
    iex> stats = Enum.reduce(1..100, stats, &ZenWebsocket.LatencyStats.add(&2, &1))
    iex> ZenWebsocket.LatencyStats.percentile(stats, 50)
    50

    iex> ZenWebsocket.LatencyStats.percentile(ZenWebsocket.LatencyStats.new(), 50)
    nil

# `summary`

```elixir
@spec summary(t()) ::
  %{
    p50: non_neg_integer(),
    p99: non_neg_integer(),
    last: non_neg_integer(),
    count: non_neg_integer()
  }
  | nil
```

Returns a summary map with p50, p99, last sample, and count.

Returns `nil` if the buffer is empty.

## Examples

    iex> stats = ZenWebsocket.LatencyStats.new()
    iex> stats = Enum.reduce([10, 20, 30, 40, 50], stats, &ZenWebsocket.LatencyStats.add(&2, &1))
    iex> summary = ZenWebsocket.LatencyStats.summary(stats)
    iex> summary.count
    5
    iex> summary.last
    50

---

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