nquic_qlog behaviour (nquic v1.0.0)
View Sourceqlog tracing for nquic connections (draft-ietf-quic-qlog-main-schema).
qlog is the IETF-standard observability format for QUIC. A backend records per-connection events to a sink (file, gen_event manager, caller-supplied module); tools like qvis render the resulting NDJSON stream into time-series and packet-level diagrams.
This module defines the backend behaviour and a tiny dispatcher
the protocol calls at known hook points. Backends do all the
formatting work; the dispatcher only branches on whether a backend
is attached.
The protocol carries the active backend on #conn_state.qlog as
undefined | qlog_state(). When the field is undefined every
event/3 call returns immediately in a single field read.
Hook points
Currently wired:
packet_sent: every wire packet leaves with a payload, header, PN, encryption level. Fired fromnquic_protocol_send.packet_received: every successfully decrypted packet. Fired fromnquic_protocol_recv.
Future hook points (documented in
plans/current/3_TRANSPORT_GAPS_PLAN.md §C2):
transport:datagrams_receivedtransport:packet_lostrecovery:metrics_updatedrecovery:congestion_state_updatedrecovery:loss_timer_updated
Configuration
#{qlog => Backend} on nquic:listen_opts/0 and
nquic:connect_opts/0. Backend is one of:
{file, Path}: open a per-connection NDJSON file atPath(nquic_qlog_file).{Module, InitArgs}: caller-supplied backend that implements this behaviour.
Summary
Callbacks
Initialise the backend. Args is the second element of the
backend_config() tuple. The returned state is opaque to the
dispatcher and threaded through event/2 / terminate/2.
Functions
Construct a qlog_state() from a backend_config() for the connection
whose original DCID is CID. {ok, undefined} if Cfg is the
sentinel undefined (the option was not set).
Tear down the backend.
Record a qlog event. Zero-overhead when no backend is attached. The dispatcher is intentionally unhelpful about misbehaving backends: it threads the new backend state back into the connection state and lets errors propagate. Backends MUST NOT crash on malformed event payloads.
Types
-type backend_config() :: {file, file:filename_all()} | {module(), term()}.
-type event_name() ::
transport_packet_sent | transport_packet_received | transport_packet_lost |
recovery_metrics_updated.
Callbacks
-callback event(BackendState :: term(), Event :: {event_name(), event_data()}) -> {ok, BackendState :: term()}.
-callback init(nquic:connection_id(), Args :: term()) -> {ok, BackendState :: term()} | {error, term()}.
Initialise the backend. Args is the second element of the
backend_config() tuple. The returned state is opaque to the
dispatcher and threaded through event/2 / terminate/2.
Functions
-spec attach(nquic:connection_id(), undefined | backend_config()) -> {ok, undefined | qlog_state()} | {error, term()}.
Construct a qlog_state() from a backend_config() for the connection
whose original DCID is CID. {ok, undefined} if Cfg is the
sentinel undefined (the option was not set).
-spec detach(undefined | qlog_state()) -> ok.
Tear down the backend.
-spec event(undefined | qlog_state(), event_name(), event_data()) -> undefined | qlog_state().
Record a qlog event. Zero-overhead when no backend is attached. The dispatcher is intentionally unhelpful about misbehaving backends: it threads the new backend state back into the connection state and lets errors propagate. Backends MUST NOT crash on malformed event payloads.