ZenWebsocket.LatencyStats (ZenWebsocket v0.4.2)

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.

API Functions

FunctionArityDescriptionParam Kinds
summary1Get a summary of latency statistics.stats: value
percentile2Calculate a percentile from buffered latency samples.stats: value, percentile: value
add2Add a latency sample to the buffer.stats: value, sample_ms: value
new1Create a new latency stats buffer.opts: value

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