ZenWebsocket.LatencyStats (ZenWebsocket v0.3.1)

Copy Markdown View Source

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.

Summary

Functions

Adds a latency sample in milliseconds to the buffer.

Creates a new latency stats buffer with configurable max size.

Calculates the specified percentile from buffered samples.

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

Types

t()

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

Functions

add(stats, sample_ms)

@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(opts \\ [])

@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(latency_stats, percentile)

@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(stats)

@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