nquic_metrics (nquic v1.0.0)

View Source

Per-listener observability primitives.

Owns one atomics ref for listener-wide counters (packets, conns, handshakes, accept queue depth, ...) and one ETS table that holds a row per tracked connection. Both are allocated by new/0 when the listener's dispatch table is built and destroyed on listener shutdown.

Counter increments are inline atomics:add/3 calls (~10ns) so the hot receive path stays cheap. The per-conn rows track identity, peer, and lifecycle state for internal lookup; they are written on handshake completion, state change, and connection termination.

Per-connection lifetime byte counters live in a smaller atomics ref attached to the row, so the conn-statem can bump bytes_in / bytes_out without rewriting the row.

Summary

Functions

Add Delta to the named counter.

Delete the row keyed by DCID. No-op if absent.

Destroy the info ETS table. The atomics ref is GC'd with the metrics record.

Read a single counter value.

Increment the named counter by 1.

Add N to the row's lifetime bytes_in total.

Add N to the row's lifetime bytes_out total.

Return the ETS tid for the info table (testing / advanced callers).

Insert (or replace) a row. Used on handshake completion and when peer identity changes mid-connection.

Return every row currently in the table.

Look up a single row by DCID.

Allocate a fresh metrics handle (atomics ref + info ETS table).

Allocate a fresh per-conn counters block.

Build a fresh row with the given identity and a new counters block.

Return the current InErrors delta vs the baseline taken at listener start. On non-Linux (no /proc/net/snmp) returns 0.

Read the full per-conn counters block as a map.

Return the row's lifetime counters block.

Return the row's initial DCID (the key).

Return the row's owning conn pid.

Return the row's lifecycle state.

Return a snapshot of every counter plus uptime_ms and udp_rcvbuf_errs.

Record TsUs (monotonic microseconds) as the last-packet timestamp.

Update the lifecycle state field of an existing row.

Types

conn_counters()

-type conn_counters() :: #conn_counters{ref :: atomics:atomics_ref()}.

conn_row()

-type conn_row() ::
          #conn_row{dcid :: binary(),
                    pid :: pid(),
                    peer :: nquic_socket:sockaddr() | undefined,
                    state :: handshake | established | draining,
                    counters :: conn_counters()}.

slot()

-type slot() ::
          packets_in | packets_dropped_mailbox | packets_dropped_ratelimit | conns_established |
          conns_closed_normal | conns_closed_idle_timeout | conns_closed_peer |
          conns_closed_protocol_error | handshakes_inflight | accept_queue_depth.

t()

-type t() ::
          #metrics{counters :: atomics:atomics_ref(),
                   info_table :: ets:tid(),
                   start_monotonic_us :: integer(),
                   rcvbuf_baseline :: non_neg_integer()}.

Functions

add/3

-spec add(t(), slot(), integer()) -> ok.

Add Delta to the named counter.

delete_row/2

-spec delete_row(t(), binary()) -> ok.

Delete the row keyed by DCID. No-op if absent.

destroy/1

-spec destroy(t()) -> ok.

Destroy the info ETS table. The atomics ref is GC'd with the metrics record.

get/2

-spec get(t(), slot()) -> integer().

Read a single counter value.

inc(M, Slot)

-spec inc(t(), slot()) -> ok.

Increment the named counter by 1.

inc_bytes_in/2

-spec inc_bytes_in(conn_counters(), non_neg_integer()) -> ok.

Add N to the row's lifetime bytes_in total.

inc_bytes_out/2

-spec inc_bytes_out(conn_counters(), non_neg_integer()) -> ok.

Add N to the row's lifetime bytes_out total.

info_table/1

-spec info_table(t()) -> ets:tid().

Return the ETS tid for the info table (testing / advanced callers).

insert_row/2

-spec insert_row(t(), conn_row()) -> true.

Insert (or replace) a row. Used on handshake completion and when peer identity changes mid-connection.

list_rows/1

-spec list_rows(t()) -> [conn_row()].

Return every row currently in the table.

lookup_row/2

-spec lookup_row(t(), binary()) -> {ok, conn_row()} | {error, not_found}.

Look up a single row by DCID.

new()

-spec new() -> t().

Allocate a fresh metrics handle (atomics ref + info ETS table).

new_conn_counters()

-spec new_conn_counters() -> conn_counters().

Allocate a fresh per-conn counters block.

new_row(DCID, Pid, Peer, State)

-spec new_row(binary(), pid(), nquic_socket:sockaddr() | undefined, handshake | established | draining) ->
                 conn_row().

Build a fresh row with the given identity and a new counters block.

rcvbuf_errs/1

-spec rcvbuf_errs(t()) -> non_neg_integer().

Return the current InErrors delta vs the baseline taken at listener start. On non-Linux (no /proc/net/snmp) returns 0.

read_conn_counters/1

-spec read_conn_counters(conn_counters()) -> #{atom() => integer()}.

Read the full per-conn counters block as a map.

row_counters/1

-spec row_counters(conn_row()) -> conn_counters().

Return the row's lifetime counters block.

row_dcid/1

-spec row_dcid(conn_row()) -> binary().

Return the row's initial DCID (the key).

row_pid/1

-spec row_pid(conn_row()) -> pid().

Return the row's owning conn pid.

row_state/1

-spec row_state(conn_row()) -> handshake | established | draining.

Return the row's lifecycle state.

snapshot/1

-spec snapshot(t()) -> #{atom() => integer()}.

Return a snapshot of every counter plus uptime_ms and udp_rcvbuf_errs.

touch_last_packet/2

-spec touch_last_packet(conn_counters(), integer()) -> ok.

Record TsUs (monotonic microseconds) as the last-packet timestamp.

update_state/3

-spec update_state(t(), binary(), handshake | established | draining) -> ok.

Update the lifecycle state field of an existing row.