Skip to main content

QUIC event definitions for qlog
draft-ietf-quic-qlog-quic-events-14

Document Type Active Internet-Draft (quic WG)
Authors Robin Marx , Luca Niccolini , Marten Seemann , Lucas Pardue
Last updated 2026-11-02
Replaces draft-marx-quic-qlog-quic-events
RFC stream Internet Engineering Task Force (IETF)
Intended RFC status Proposed Standard
Formats
Additional resources Mailing list discussion
Stream WG state WG Document
Associated WG milestone
Qlog documents to IESG
On agenda quic at IETF-127
Document shepherd (None)
IESG IESG state I-D Exists
Consensus boilerplate Yes
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-ietf-quic-qlog-quic-events-14
QUIC                                                        R. Marx, Ed.
Internet-Draft                                                    Akamai
Intended status: Standards Track                       L. Niccolini, Ed.
Expires: 6 May 2027                                                 Meta
                                                         M. Seemann, Ed.
                                                                        
                                                          L. Pardue, Ed.
                                                                   Apple
                                                         2 November 2026

                    QUIC event definitions for qlog
                  draft-ietf-quic-qlog-quic-events-14

Abstract

   This document describes a qlog event schema containing concrete qlog
   event definitions and their metadata for the core QUIC protocol and
   selected extensions.

Note to Readers

      Note to RFC editor: Please remove this section before publication.

   Feedback and discussion are welcome at https://github.com/quicwg/qlog
   (https://github.com/quicwg/qlog).  Readers are advised to refer to
   the "editor's draft" at that URL for an up-to-date version of this
   document.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 6 May 2027.

Marx, et al.               Expires 6 May 2027                   [Page 1]
Internet-Draft       QUIC event definitions for qlog       November 2026

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
     1.1.  Use of Group IDs  . . . . . . . . . . . . . . . . . . . .   5
     1.2.  Raw Packet and Frame Information  . . . . . . . . . . . .   5
     1.3.  Events without a Known Connection . . . . . . . . . . . .   5
     1.4.  Notational Conventions  . . . . . . . . . . . . . . . . .   6
   2.  Event Schema Definition . . . . . . . . . . . . . . . . . . .   6
     2.1.  Draft Event Schema Identification . . . . . . . . . . . .   6
   3.  QUIC Event Overview . . . . . . . . . . . . . . . . . . . . .   7
   4.  Connectivity Events . . . . . . . . . . . . . . . . . . . . .  10
     4.1.  server_listening  . . . . . . . . . . . . . . . . . . . .  10
     4.2.  connection_started  . . . . . . . . . . . . . . . . . . .  10
     4.3.  connection_closed . . . . . . . . . . . . . . . . . . . .  11
     4.4.  connection_id_updated . . . . . . . . . . . . . . . . . .  12
     4.5.  spin_bit_updated  . . . . . . . . . . . . . . . . . . . .  13
     4.6.  connection_state_updated  . . . . . . . . . . . . . . . .  13
     4.7.  tuple_assigned  . . . . . . . . . . . . . . . . . . . . .  15
     4.8.  mtu_updated . . . . . . . . . . . . . . . . . . . . . . .  16
   5.  Transport Events  . . . . . . . . . . . . . . . . . . . . . .  16
     5.1.  version_information . . . . . . . . . . . . . . . . . . .  16
     5.2.  alpn_information  . . . . . . . . . . . . . . . . . . . .  17
     5.3.  parameters_set  . . . . . . . . . . . . . . . . . . . . .  18
     5.4.  parameters_restored . . . . . . . . . . . . . . . . . . .  20
     5.5.  packet_sent . . . . . . . . . . . . . . . . . . . . . . .  21
     5.6.  packet_received . . . . . . . . . . . . . . . . . . . . .  22
     5.7.  packet_dropped  . . . . . . . . . . . . . . . . . . . . .  23
     5.8.  packet_buffered . . . . . . . . . . . . . . . . . . . . .  25
     5.9.  packets_acked . . . . . . . . . . . . . . . . . . . . . .  25
     5.10. udp_datagrams_sent  . . . . . . . . . . . . . . . . . . .  26
     5.11. udp_datagrams_received  . . . . . . . . . . . . . . . . .  27
     5.12. udp_datagram_dropped  . . . . . . . . . . . . . . . . . .  27
     5.13. stream_state_updated  . . . . . . . . . . . . . . . . . .  28
     5.14. Frame-Related Events  . . . . . . . . . . . . . . . . . .  30

Marx, et al.               Expires 6 May 2027                   [Page 2]
Internet-Draft       QUIC event definitions for qlog       November 2026

       5.14.1.  frames_created . . . . . . . . . . . . . . . . . . .  31
       5.14.2.  frames_parsed  . . . . . . . . . . . . . . . . . . .  31
     5.15. stream_data_moved . . . . . . . . . . . . . . . . . . . .  31
     5.16. datagram_data_moved . . . . . . . . . . . . . . . . . . .  32
     5.17. datagram_dropped  . . . . . . . . . . . . . . . . . . . .  33
     5.18. connection_data_blocked_updated . . . . . . . . . . . . .  34
     5.19. stream_data_blocked_updated . . . . . . . . . . . . . . .  35
     5.20. datagram_data_blocked_updated . . . . . . . . . . . . . .  35
     5.21. migration_state_updated . . . . . . . . . . . . . . . . .  35
     5.22. timer_updated . . . . . . . . . . . . . . . . . . . . . .  37
   6.  Security Events . . . . . . . . . . . . . . . . . . . . . . .  38
     6.1.  key_updated . . . . . . . . . . . . . . . . . . . . . . .  38
     6.2.  key_discarded . . . . . . . . . . . . . . . . . . . . . .  39
   7.  Recovery Events . . . . . . . . . . . . . . . . . . . . . . .  40
     7.1.  recovery_parameters_set . . . . . . . . . . . . . . . . .  40
     7.2.  recovery_metrics_updated  . . . . . . . . . . . . . . . .  41
     7.3.  congestion_state_updated  . . . . . . . . . . . . . . . .  43
     7.4.  packet_lost . . . . . . . . . . . . . . . . . . . . . . .  43
     7.5.  marked_for_retransmit . . . . . . . . . . . . . . . . . .  44
     7.6.  ecn_state_updated . . . . . . . . . . . . . . . . . . . .  45
   8.  QUIC Data Type Definitions  . . . . . . . . . . . . . . . . .  45
     8.1.  QuicVersion . . . . . . . . . . . . . . . . . . . . . . .  45
     8.2.  ConnectionID  . . . . . . . . . . . . . . . . . . . . . .  46
     8.3.  Initiator . . . . . . . . . . . . . . . . . . . . . . . .  46
     8.4.  IPAddressPort . . . . . . . . . . . . . . . . . . . . . .  46
     8.5.  TupleEndpointInfo . . . . . . . . . . . . . . . . . . . .  46
     8.6.  PacketType  . . . . . . . . . . . . . . . . . . . . . . .  47
     8.7.  PacketNumberSpace . . . . . . . . . . . . . . . . . . . .  47
     8.8.  PacketHeader  . . . . . . . . . . . . . . . . . . . . . .  47
     8.9.  Token . . . . . . . . . . . . . . . . . . . . . . . . . .  49
     8.10. StatelessResetToken . . . . . . . . . . . . . . . . . . .  49
     8.11. KeyType . . . . . . . . . . . . . . . . . . . . . . . . .  49
     8.12. ECN . . . . . . . . . . . . . . . . . . . . . . . . . . .  50
     8.13. QUIC Frames . . . . . . . . . . . . . . . . . . . . . . .  50
       8.13.1.  PaddingFrame . . . . . . . . . . . . . . . . . . . .  51
       8.13.2.  PingFrame  . . . . . . . . . . . . . . . . . . . . .  51
       8.13.3.  AckFrame . . . . . . . . . . . . . . . . . . . . . .  52
       8.13.4.  ResetStreamFrame . . . . . . . . . . . . . . . . . .  52
       8.13.5.  ResetStreamAtFrame . . . . . . . . . . . . . . . . .  53
       8.13.6.  StopSendingFrame . . . . . . . . . . . . . . . . . .  53
       8.13.7.  CryptoFrame  . . . . . . . . . . . . . . . . . . . .  54
       8.13.8.  NewTokenFrame  . . . . . . . . . . . . . . . . . . .  54
       8.13.9.  StreamFrame  . . . . . . . . . . . . . . . . . . . .  54
       8.13.10. MaxDataFrame . . . . . . . . . . . . . . . . . . . .  55
       8.13.11. MaxStreamDataFrame . . . . . . . . . . . . . . . . .  55
       8.13.12. MaxStreamsFrame  . . . . . . . . . . . . . . . . . .  55
       8.13.13. DataBlockedFrame . . . . . . . . . . . . . . . . . .  55
       8.13.14. StreamDataBlockedFrame . . . . . . . . . . . . . . .  56

Marx, et al.               Expires 6 May 2027                   [Page 3]
Internet-Draft       QUIC event definitions for qlog       November 2026

       8.13.15. StreamsBlockedFrame  . . . . . . . . . . . . . . . .  56
       8.13.16. NewConnectionIDFrame . . . . . . . . . . . . . . . .  56
       8.13.17. RetireConnectionIDFrame  . . . . . . . . . . . . . .  57
       8.13.18. PathChallengeFrame . . . . . . . . . . . . . . . . .  57
       8.13.19. PathResponseFrame  . . . . . . . . . . . . . . . . .  57
       8.13.20. ConnectionCloseFrame . . . . . . . . . . . . . . . .  57
       8.13.21. HandshakeDoneFrame . . . . . . . . . . . . . . . . .  58
       8.13.22. UnknownFrame . . . . . . . . . . . . . . . . . . . .  58
       8.13.23. DatagramFrame  . . . . . . . . . . . . . . . . . . .  59
     8.14. TransportError  . . . . . . . . . . . . . . . . . . . . .  59
     8.15. ApplicationError  . . . . . . . . . . . . . . . . . . . .  60
     8.16. CryptoError . . . . . . . . . . . . . . . . . . . . . . .  60
   9.  Handling Packet Coalescing  . . . . . . . . . . . . . . . . .  61
   10. Security and Privacy Considerations . . . . . . . . . . . . .  61
   11. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  61
   12. References  . . . . . . . . . . . . . . . . . . . . . . . . .  62
     12.1.  Normative References . . . . . . . . . . . . . . . . . .  62
     12.2.  Informative References . . . . . . . . . . . . . . . . .  63
   Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . .  63
   Change Log  . . . . . . . . . . . . . . . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-13: . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-12: . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-11: . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-09: . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-08: . . . . . . . . . . . . .  64
     Since draft-ietf-qlog-quic-events-07: . . . . . . . . . . . . .  65
     Since draft-ietf-qlog-quic-events-06: . . . . . . . . . . . . .  65
     Since draft-ietf-qlog-quic-events-05: . . . . . . . . . . . . .  65
     Since draft-ietf-qlog-quic-events-04: . . . . . . . . . . . . .  65
     Since draft-ietf-qlog-quic-events-03: . . . . . . . . . . . . .  66
     Since draft-ietf-qlog-quic-events-02: . . . . . . . . . . . . .  66
     Since draft-ietf-qlog-quic-events-01: . . . . . . . . . . . . .  67
     Since draft-ietf-qlog-quic-events-00: . . . . . . . . . . . . .  67
     Since draft-marx-qlog-event-definitions-quic-h3-02: . . . . . .  67
     Since draft-marx-qlog-event-definitions-quic-h3-01: . . . . . .  67
     Since draft-marx-qlog-event-definitions-quic-h3-00: . . . . . .  68
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .  69

1.  Introduction

   This document defines a qlog event schema (Section 8 of [QLOG-MAIN])
   containing concrete events for the core QUIC protocol (see
   [QUIC-TRANSPORT], [QUIC-RECOVERY], and [QUIC-TLS]) and some of its
   extensions (see [QUIC-DATAGRAM], [GREASEBIT], and [RESET-STREAM-AT]).

Marx, et al.               Expires 6 May 2027                   [Page 4]
Internet-Draft       QUIC event definitions for qlog       November 2026

   The event namespace with identifier quic is defined; see Section 2.
   In this namespace multiple events derive from the qlog abstract Event
   class (Section 7 of [QLOG-MAIN]), each extending the data field and
   defining their name field values and semantics.  The data types that
   the events use are defined in Section 8.

1.1.  Use of Group IDs

   QUIC's Original Destination Connection ID (ODCID) can be used as the
   value of the qlog group_id field.  The ODCID is the connection ID
   that the client chooses for its first Initial packet.  It stays the
   same for the whole connection, unlike the connection IDs that
   endpoints use, which can change.  It can also link packets such as
   Retry and Version Negotiation to the connection.

   The ODCID can also be used as the qlog filename or file identifier,
   optionally suffixed by the vantage point type.  For example,
   abcd1234_server.qlog would contain the server-side trace of the
   connection with ODCID abcd1234.

1.2.  Raw Packet and Frame Information

   Protected QUIC packets (Initial, 0-RTT, Handshake, and 1-RTT) end
   with an AEAD authentication tag.  Every cipher suite that QUIC
   version 1 can use has a 16-byte tag; see Section 5.3 of [QUIC-TLS].
   When calculating the lengths in RawInfo fields (Section 10 of
   [QLOG-MAIN]) for these packets, the tag is treated as a 16-byte
   trailer.

1.3.  Events without a Known Connection

   A qlog trace is typically associated with a single QUIC connection.
   However, some events cannot be tied to a specific connection,
   especially on the server.  For example, a packet_dropped event
   (Section 5.7) with the trigger "connection_unknown" is for a packet
   that matches no known connection.

   There are various ways to handle these events, each with tradeoffs
   between file size overhead, flexibility, ease of use, and ease of
   implementation.  Some options include:

   *  Log them in a separate endpoint-wide trace, or use a special
      group_id value, not associated with a single connection.

   *  Log them in the most recently used trace.

   *  Use additional heuristics to identify the connection, for example
      the four-tuple in addition to the connection ID.

Marx, et al.               Expires 6 May 2027                   [Page 5]
Internet-Draft       QUIC event definitions for qlog       November 2026

   *  Buffer events until they can be assigned to a connection, for
      example events about the Version Negotiation and Retry packets
      that a server sends before it creates connection state.

1.4.  Notational Conventions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

   The event and data structure definitions in this document are
   expressed in the Concise Data Definition Language [CDDL] and its
   extensions described in Section 1.2 of [QLOG-MAIN].

   This document uses the following from [QLOG-MAIN]: the event
   namespace and event type concepts; the name, data, tuple, group_id,
   and time-related fields; and the RawInfo type.

   Events are defined with an importance level as described in
   Section 8.3 of [QLOG-MAIN].

   As is the case for [QLOG-MAIN], the qlog schema definitions in this
   document are intentionally agnostic to serialization formats.  The
   choice of format is an implementation decision.

2.  Event Schema Definition

   This document describes how the core QUIC protocol and selected
   extensions can be expressed in qlog using a newly defined event
   schema.  Per the requirements in Section 8 of [QLOG-MAIN], this
   document registers the quic namespace.  The event schema URI is
   urn:ietf:params:qlog:events:quic.

2.1.  Draft Event Schema Identification

   This section is to be removed before publishing as an RFC.

   Only implementations of the final, published RFC can use the events
   belonging to the event schema with the URI
   urn:ietf:params:qlog:events:quic.  Until such an RFC exists,
   implementations MUST NOT identify themselves using this URI.

   Implementations of draft versions of the event schema MUST append the
   string "-" and the corresponding draft number to the URI.  For
   example, draft 07 of this document is identified using the URI
   urn:ietf:params:qlog:events:quic-07.

Marx, et al.               Expires 6 May 2027                   [Page 6]
Internet-Draft       QUIC event definitions for qlog       November 2026

   The namespace identifier itself is not affected by this requirement.

3.  QUIC Event Overview

   Table 1 summarizes the name value of each event type that is defined
   in this specification.

   +======================================+============+==============+
   | Name value                           | Importance | Definition   |
   +======================================+============+==============+
   | quic:server_listening                | Extra      | Section 4.1  |
   +--------------------------------------+------------+--------------+
   | quic:connection_started              | Base       | Section 4.2  |
   +--------------------------------------+------------+--------------+
   | quic:connection_closed               | Base       | Section 4.3  |
   +--------------------------------------+------------+--------------+
   | quic:connection_id_updated           | Base       | Section 4.4  |
   +--------------------------------------+------------+--------------+
   | quic:spin_bit_updated                | Base       | Section 4.5  |
   +--------------------------------------+------------+--------------+
   | quic:connection_state_updated        | Base       | Section 4.6  |
   +--------------------------------------+------------+--------------+
   | quic:tuple_assigned                  | Base       | Section 4.7  |
   +--------------------------------------+------------+--------------+
   | quic:mtu_updated                     | Extra      | Section 4.8  |
   +--------------------------------------+------------+--------------+
   | quic:version_information             | Core       | Section 5.1  |
   +--------------------------------------+------------+--------------+
   | quic:alpn_information                | Core       | Section 5.2  |
   +--------------------------------------+------------+--------------+
   | quic:parameters_set                  | Core       | Section 5.3  |
   +--------------------------------------+------------+--------------+
   | quic:parameters_restored             | Base       | Section 5.4  |
   +--------------------------------------+------------+--------------+
   | quic:packet_sent                     | Core       | Section 5.5  |
   +--------------------------------------+------------+--------------+
   | quic:packet_received                 | Core       | Section 5.6  |
   +--------------------------------------+------------+--------------+
   | quic:packet_dropped                  | Base       | Section 5.7  |
   +--------------------------------------+------------+--------------+
   | quic:packet_buffered                 | Base       | Section 5.8  |
   +--------------------------------------+------------+--------------+
   | quic:packets_acked                   | Extra      | Section 5.9  |
   +--------------------------------------+------------+--------------+
   | quic:udp_datagrams_sent              | Extra      | Section 5.10 |
   +--------------------------------------+------------+--------------+
   | quic:udp_datagrams_received          | Extra      | Section 5.11 |
   +--------------------------------------+------------+--------------+

Marx, et al.               Expires 6 May 2027                   [Page 7]
Internet-Draft       QUIC event definitions for qlog       November 2026

   | quic:udp_datagram_dropped            | Extra      | Section 5.12 |
   +--------------------------------------+------------+--------------+
   | quic:stream_state_updated            | Base       | Section 5.13 |
   +--------------------------------------+------------+--------------+
   | quic:frames_created                  | Extra      | Section      |
   |                                      |            | 5.14.1       |
   +--------------------------------------+------------+--------------+
   | quic:frames_parsed                   | Extra      | Section      |
   |                                      |            | 5.14.2       |
   +--------------------------------------+------------+--------------+
   | quic:stream_data_moved               | Base       | Section 5.15 |
   +--------------------------------------+------------+--------------+
   | quic:datagram_data_moved             | Base       | Section 5.16 |
   +--------------------------------------+------------+--------------+
   | quic:datagram_dropped                | Base       | Section 5.17 |
   +--------------------------------------+------------+--------------+
   | quic:connection_data_blocked_updated | Extra      | Section 5.18 |
   +--------------------------------------+------------+--------------+
   | quic:stream_data_blocked_updated     | Extra      | Section 5.19 |
   +--------------------------------------+------------+--------------+
   | quic:datagram_data_blocked_updated   | Extra      | Section 5.20 |
   +--------------------------------------+------------+--------------+
   | quic:migration_state_updated         | Extra      | Section 5.21 |
   +--------------------------------------+------------+--------------+
   | quic:timer_updated                   | Extra      | Section 5.22 |
   +--------------------------------------+------------+--------------+
   | quic:key_updated                     | Base       | Section 6.1  |
   +--------------------------------------+------------+--------------+
   | quic:key_discarded                   | Base       | Section 6.2  |
   +--------------------------------------+------------+--------------+
   | quic:recovery_parameters_set         | Base       | Section 7.1  |
   +--------------------------------------+------------+--------------+
   | quic:recovery_metrics_updated        | Core       | Section 7.2  |
   +--------------------------------------+------------+--------------+
   | quic:congestion_state_updated        | Base       | Section 7.3  |
   +--------------------------------------+------------+--------------+
   | quic:packet_lost                     | Core       | Section 7.4  |
   +--------------------------------------+------------+--------------+
   | quic:marked_for_retransmit           | Extra      | Section 7.5  |
   +--------------------------------------+------------+--------------+
   | quic:ecn_state_updated               | Extra      | Section 7.6  |
   +--------------------------------------+------------+--------------+

                           Table 1: QUIC Events

Marx, et al.               Expires 6 May 2027                   [Page 8]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUIC events extend the $ProtocolEventData extension point defined in
   Section 8.2 of [QLOG-MAIN].  Additionally, they allow for direct
   extensibility by their use of per-event extension points via the $$
   CDDL "group socket" syntax, as also described in Section 8.2 of
   [QLOG-MAIN].

   QuicEventData = QUICServerListening /
                   QUICConnectionStarted /
                   QUICConnectionClosed /
                   QUICConnectionIDUpdated /
                   QUICSpinBitUpdated /
                   QUICConnectionStateUpdated /
                   QUICTupleAssigned /
                   QUICMTUUpdated /
                   QUICVersionInformation /
                   QUICALPNInformation /
                   QUICParametersSet /
                   QUICParametersRestored /
                   QUICPacketSent /
                   QUICPacketReceived /
                   QUICPacketDropped /
                   QUICPacketBuffered /
                   QUICPacketsAcked /
                   QUICUDPDatagramsSent /
                   QUICUDPDatagramsReceived /
                   QUICUDPDatagramDropped /
                   QUICStreamStateUpdated /
                   QUICFramesCreated /
                   QUICFramesParsed /
                   QUICStreamDataMoved /
                   QUICDatagramDataMoved /
                   QUICDatagramDropped /
                   QUICConnectionDataBlockedUpdated /
                   QUICStreamDataBlockedUpdated /
                   QUICDatagramDataBlockedUpdated /
                   QUICMigrationStateUpdated /
                   QUICTimerUpdated /
                   QUICKeyUpdated /
                   QUICKeyDiscarded /
                   QUICRecoveryParametersSet /
                   QUICRecoveryMetricsUpdated /
                   QUICCongestionStateUpdated /
                   QUICPacketLost /
                   QUICMarkedForRetransmit /
                   QUICECNStateUpdated

   $ProtocolEventData /= QuicEventData

Marx, et al.               Expires 6 May 2027                   [Page 9]
Internet-Draft       QUIC event definitions for qlog       November 2026

     Figure 1: QuicEventData definition and ProtocolEventData extension

   The concrete QUIC event types are further defined below, their type
   identifier is the heading name.  The subdivisions in sections on
   Connectivity, Transport, Security, and Recovery are purely for
   readability.

4.  Connectivity Events

4.1.  server_listening

   The server_listening event is emitted when the server starts
   accepting connections.  It has Extra importance level.

   QUICServerListening = {
       ? address_v4: IPAddressPort
       ? address_v6: IPAddressPort

       ; the server will always answer client Initial packets with a Retry
       ; packet (no 1-RTT connection setups by choice)
       ? retry_required: bool

       * $$quic-serverlistening-extension
   }

                  Figure 2: QUICServerListening definition

   Some QUIC stacks do not handle sockets directly, so they cannot log
   IP addresses or ports.

4.2.  connection_started

   The connection_started event is emitted when a client attempts a new
   connection, or when a server accepts one.  It overlaps with the
   connection_state_updated event, but it also logs the local and remote
   endpoint information.  It has Base importance level.

   QUICConnectionStarted = {
       local: TupleEndpointInfo
       remote: TupleEndpointInfo

       * $$quic-connectionstarted-extension
   }

                 Figure 3: QUICConnectionStarted definition

Marx, et al.               Expires 6 May 2027                  [Page 10]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Some QUIC stacks do not handle sockets directly, so they cannot log
   IP addresses or ports.  All fields of TupleEndpointInfo (Figure 45)
   are optional, so such a stack can log local and remote with only the
   fields it knows, such as connection_ids.

4.3.  connection_closed

   The connection_closed event is emitted when a connection closes,
   typically because of an error or a timeout.  It has Base importance
   level.

   This event overlaps with the connection_state_updated event and the
   CONNECTION_CLOSE frame.  However, when analyzing large deployments,
   it can be useful to have a single event for each closure, with a
   reason field for more detail.  This event can also log closures due
   to timeouts or explicit application actions, such as racing several
   connections and aborting the slowest, which the other events cannot
   easily capture.

   The connection_closed event is logged when the local endpoint does
   one of the following; see Section 10 of [QUIC-TRANSPORT]:

   *  silently discards the connection after an idle timeout;

   *  sends a CONNECTION_CLOSE frame, and enters the closing state;

   *  receives a CONNECTION_CLOSE frame, and enters the draining state;
      or

   *  receives a Stateless Reset, and enters the draining state.

   Later changes, such as leaving the closing or draining state, are
   logged with the connection_state_updated event.

   QUIC has two kinds of connection error, transport errors and
   application errors, each with defined codes and semantics; see
   Section 20 of [QUIC-TRANSPORT].  An implementation can also have
   internal errors, which it might or might not map to these codes.  So
   this event can carry two levels of error: connection_error or
   application_error for the QUIC error, and internal_code for a more
   specific internal error.

   If an error code has no known string, connection_error or
   application_error can be "unknown", and error_code then holds the
   numerical value without variable-length integer encoding.

Marx, et al.               Expires 6 May 2027                  [Page 11]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICConnectionClosed = {

       ; which side closed the connection
       ? initiator: Initiator
       ? connection_error: $TransportError /
                           CryptoError
       ? application_error: $ApplicationError

       ; if connection_error or application_error === "unknown"
       ? error_code: uint64

       ? internal_code: uint64
       ? reason: text
       ? trigger:
           "idle_timeout" /
           "application" /
           "error" /
           "version_mismatch" /
           ; when received from peer
           "stateless_reset" /
           "aborted" /
           ; when it is unclear what triggered the CONNECTION_CLOSE
           "unspecified"

       * $$quic-connectionclosed-extension
   }

                 Figure 4: QUICConnectionClosed definition

   Implementations SHOULD use the most descriptive trigger value that
   they can determine.  This is often clear at the endpoint that closes
   the connection, but can be less clear at the endpoint that receives
   the CONNECTION_CLOSE frame.

4.4.  connection_id_updated

   The connection_id_updated event is emitted when either endpoint
   updates its current connection ID.  This typically happens rarely
   during a connection, so logging this event is more efficient than
   logging the connection ID in every packet_sent or packet_received
   event.  It has Base importance level.

   The connection_id_updated event is viewed from the perspective of the
   endpoint applying the new ID.  When the endpoint receives a new
   connection ID from the peer, the initiator field is "remote".  When
   the endpoint updates its own connection ID, the initiator field is
   "local".

Marx, et al.               Expires 6 May 2027                  [Page 12]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICConnectionIDUpdated = {
       initiator: Initiator
       ? old: ConnectionID
       ? new: ConnectionID

       * $$quic-connectionidupdated-extension
   }

                Figure 5: QUICConnectionIDUpdated definition

4.5.  spin_bit_updated

   The spin_bit_updated event is emitted when the value of the QUIC
   latency spin bit changes; see Section 17.4 of [QUIC-TRANSPORT].  It
   SHOULD NOT be emitted when the spin bit is set to the value it
   already has.  It has Base importance level.

   QUICSpinBitUpdated = {
       state: bool

       * $$quic-spinbitupdated-extension
   }

                  Figure 6: QUICSpinBitUpdated definition

4.6.  connection_state_updated

   The connection_state_updated event is emitted when the connection
   changes state, to track progress through the QUIC handshake and
   connection close.  It has Base importance level.

   [QUIC-TRANSPORT] does not define a complete set of connection states
   or their transitions, though it names some, such as the closing and
   draining states.  This document defines the states most likely to be
   useful for debugging QUIC connections; the list is not exhaustive.

   QUIC implementations SHOULD log the BaseConnectionStates, and can add
   the GranularConnectionStates when more in-depth debugging is
   required.  Tools SHOULD handle both kinds equally.

   QUICConnectionStateUpdated = {
       ? old: $ConnectionState
       new: $ConnectionState

       * $$quic-connectionstateupdated-extension
   }

   BaseConnectionStates =

Marx, et al.               Expires 6 May 2027                  [Page 13]
Internet-Draft       QUIC event definitions for qlog       November 2026

       ; Initial packet sent/received
       "attempted" /

       ; Handshake packet sent/received
       "handshake_started" /

       ; Both sent a TLS Finished message
       ; and verified the peer's TLS Finished message
       ; 1-RTT packets can be sent
       ; RFC 9001 Section 4.1.1
       "handshake_complete" /

       ; CONNECTION_CLOSE sent/received,
       ; stateless reset received or idle timeout
       "closed"

   GranularConnectionStates =
       ; RFC 9000 Section 8.1
       ; client sent Handshake packet OR
       ; client used connection ID chosen by the server OR
       ; client used valid address validation token
       "peer_validated" /

       ; 1-RTT data can be sent by the server,
       ; but handshake is not done yet
       ; (server has sent TLS Finished; sometimes called 0.5 RTT data)
       "early_write" /

       ; HANDSHAKE_DONE sent/received.
       ; RFC 9001 Section 4.1.2
       "handshake_confirmed" /

       ; CONNECTION_CLOSE sent
       "closing" /

       ; CONNECTION_CLOSE or Stateless Reset received
       "draining" /

       ; draining or closing period done, connection state discarded
       "closed"

   $ConnectionState /= BaseConnectionStates / GranularConnectionStates

              Figure 7: QUICConnectionStateUpdated definition

   The connection_state_updated event overlaps with the
   connection_closed and connection_started events, and with the frames
   logged in events such as packet_received.  Still, it can be useful to

Marx, et al.               Expires 6 May 2027                  [Page 14]
Internet-Draft       QUIC event definitions for qlog       November 2026

   log state transitions separately, especially if they map to an
   internal state machine.  Implementations can therefore use other
   ConnectionState values that match their internal logic.  Tools SHOULD
   handle these custom states in a similar way to the states defined in
   this document.

4.7.  tuple_assigned

   The tuple_assigned event associates a TupleID with the details of a
   network tuple, such as its IP addresses, ports, and connection IDs.
   It has Base importance level.

   As described in Section 7.2 of [QLOG-MAIN], each qlog event can be
   linked to a single network tuple by its top-level tuple field, whose
   value is a TupleID.  Encoding tuple details, such as IP addresses or
   connection IDs, into the TupleID itself can be cumbersome.  This
   event records them separately, so TupleIDs can stay short, and their
   details can be updated as the connection evolves.

   QUICTupleAssigned = {
       tuple_id: TupleID

       ; the information for traffic going towards the remote receiver
       ? tuple_remote: TupleEndpointInfo

       ; the information for traffic coming in at the local endpoint
       ? tuple_local: TupleEndpointInfo

       * $$quic-tupleassigned-extension
   }

                   Figure 8: QUICTupleAssigned definition

   Implementations choose their own tuple_id values.  For example, a
   TupleID can be an incrementing integer, the first Destination
   Connection ID associated with the tuple (or its sequence number), or
   the two endpoint IP addresses or a hash of them.

   The empty string ("") is a valid TupleID, and it is the default for
   events that do not set the tuple field.  So the initial tuple of a
   QUIC connection, on which the handshake occurs (see Section 4.2), is
   implicitly associated with the TupleID "".  Details for this default
   tuple can be logged with a tuple_assigned event whose tuple_id is "".

Marx, et al.               Expires 6 May 2027                  [Page 15]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Because a tuple's details can change during the connection, a TupleID
   can appear in several tuple_assigned events, and the latest one holds
   its current details.  The first tuple_assigned event for a TupleID
   indicates that the TupleID was created, and later ones indicate
   updates.  An event with both tuple_local and tuple_remote omitted
   indicates that the TupleID was abandoned.

4.8.  mtu_updated

   The mtu_updated event indicates that the estimated Path MTU was
   updated.  This happens as part of Path MTU discovery; see Section 14
   of [QUIC-TRANSPORT].  It has Extra importance level.

   QUICMTUUpdated = {
       ? old: uint32
       new: uint32

       ; at some point, MTU discovery stops, as a "good enough"
       ; packet size has been found
       ? done: bool

       * $$quic-mtuupdated-extension
   }

                    Figure 9: QUICMTUUpdated definition

   The done field defaults to false.

5.  Transport Events

5.1.  version_information

   The version_information event supports QUIC version negotiation; see
   Section 6 of [QUIC-TRANSPORT].  It has Core importance level.

   Each QUIC endpoint supports one or more versions.  The client sends
   its first Initial packet using one of them.  A server that does not
   support that version can reply with a Version Negotiation packet,
   which lists the versions the server supports.  This event records the
   versions that each endpoint supports, and the chosen version if there
   is one.

Marx, et al.               Expires 6 May 2027                  [Page 16]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICVersionInformation = {
       ? server_versions: [+ QuicVersion]
       ? client_versions: [+ QuicVersion]
       ? chosen_version: QuicVersion

       * $$quic-versioninformation-extension
   }

                Figure 10: QUICVersionInformation definition

   A client logs this event when it sends its first Initial packet.  The
   event includes client_versions, and chosen_version holds the version
   used in that packet.

   If the client then processes a Version Negotiation packet, it logs
   this event again with client_versions.  The event also includes
   server_versions, which holds the versions from that packet.  If the
   client selects one of them, chosen_version holds it; otherwise,
   chosen_version is absent.

   A Version Negotiation packet can also list reserved versions, which
   an endpoint adds to check that its peer ignores unknown versions; see
   Section 6.3 of [QUIC-TRANSPORT].  Because server_versions holds the
   versions from the packet, it can include reserved versions.

   A server logs this event when it receives a client's first Initial
   packet.  The event includes server_versions.  If the server supports
   the client's version, chosen_version holds the version that the
   server uses for the connection.  Otherwise, chosen_version is absent,
   and client_versions holds the version the client used.

5.2.  alpn_information

   The alpn_information event supports Application-Layer Protocol
   Negotiation (ALPN) over the QUIC transport; see [RFC7301] and
   Section 8.1 of [QUIC-TLS].  It has Core importance level.

   QUIC endpoints are configured with a list of supported ALPN
   identifiers.  During the TLS handshake, the client sends its list,
   and the server chooses one identifier from both lists and sends it
   back.  If no match is found, the connection is closed.

   ALPN identifiers are byte sequences, which are often valid UTF-8.
   The ALPNIdentifier type can hold either form: byte_value holds the
   raw bytes, and string_value holds the identifier as text.
   Implementations SHOULD log at least one form and MAY log both.

Marx, et al.               Expires 6 May 2027                  [Page 17]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICALPNInformation = {
       ? server_alpns: [* ALPNIdentifier]
       ? client_alpns: [* ALPNIdentifier]
       ? chosen_alpn: ALPNIdentifier

       * $$quic-alpninformation-extension
   }

   ALPNIdentifier = {
     ? byte_value: hexstring
     ? string_value: text
   }

                 Figure 11: QUICALPNInformation definition

   A client usually logs this event twice: first with client_alpns when
   it offers its list, then with chosen_alpn when it learns the server's
   choice.  It can instead log a single event with both fields once it
   learns the choice.

   A server logs this event once, after it chooses, with client_alpns,
   server_alpns, and chosen_alpn.

5.3.  parameters_set

   The parameters_set event groups settings from several sources, such
   as transport parameters and the TLS cipher suite, into a single
   event.  This keeps the number of events low, and lets a reader reason
   about what the settings do without needing to know which mechanism
   set each one.  It has Core importance level.

   Most of these settings are set once and never change.  However, they
   are often set at different times during the connection, so a trace
   can contain several parameters_set events with different fields set.

   Some settings have two values: one set by the local endpoint, and one
   requested by the peer.  The initiator field says which side the
   settings in an event come from, so it MUST be correct for every
   setting in that event.  Local and remote settings MUST be logged in
   separate events.  If the local endpoint changes its behavior based on
   the peer's settings, the outcome can be logged with a new event type,
   or with fields added through $$quic-parametersset-extension; see
   Section 8.2 of [QLOG-MAIN].

   The initiator field is required.  Settings that both endpoints
   negotiate, such as tls_cipher, are logged in both the local and the
   remote event.

Marx, et al.               Expires 6 May 2027                  [Page 18]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Each setting starts the connection with its default value, or with no
   value if it has no default.  A parameters_set event that includes a
   setting replaces its previous value; settings that the event omits
   keep their values.

   The grease_quic_bit and reset_stream_at settings are true if the
   transport parameter is present, and default to false.

   Implementations are not required to recognize, process, or support
   every parameter that they receive.  For example, QUIC implementations
   ignore transport parameters that they do not support; see
   Section 7.4.2 of [QUIC-TRANSPORT].  The unknown_parameters field can
   log the raw values of such parameters, for example reserved (GREASE)
   parameters, private extensions, or experiments.

   In the case of connection resumption and 0-RTT, some of the server's
   parameters are stored up-front at the client and used for the initial
   connection startup.  They are later updated with the server's reply.
   In these cases, utilize the separate parameters_restored event to
   indicate the initial values, and this event to indicate the updated
   values, as normal.

   QUICParametersSet = {
       initiator: Initiator

       ; true if valid session ticket was received
       ? resumption_allowed: bool

       ; true if early data extension was enabled on the TLS layer
       ? early_data_enabled: bool

       ; e.g., "AES_128_GCM_SHA256"
       ? tls_cipher: text

       ; RFC9000
       ? original_destination_connection_id: ConnectionID
       ? initial_source_connection_id: ConnectionID
       ? retry_source_connection_id: ConnectionID
       ? stateless_reset_token: StatelessResetToken
       ? disable_active_migration: bool
       ? max_idle_timeout: uint64
       ? max_udp_payload_size: uint64
       ? ack_delay_exponent: uint64
       ? max_ack_delay: uint64
       ? active_connection_id_limit: uint64
       ? initial_max_data: uint64
       ? initial_max_stream_data_bidi_local: uint64
       ? initial_max_stream_data_bidi_remote: uint64

Marx, et al.               Expires 6 May 2027                  [Page 19]
Internet-Draft       QUIC event definitions for qlog       November 2026

       ? initial_max_stream_data_uni: uint64
       ? initial_max_streams_bidi: uint64
       ? initial_max_streams_uni: uint64
       ? preferred_address: PreferredAddress
       ? unknown_parameters: [* UnknownParameter]

       ; RFC9221
       ? max_datagram_frame_size: uint64

       ; RFC9287
       ? grease_quic_bit: bool

       ; draft-ietf-quic-reliable-stream-reset
       ? reset_stream_at: bool

       * $$quic-parametersset-extension
   }

   PreferredAddress = {
       ? address_v4: IPAddressPort
       ? address_v6: IPAddressPort
       connection_id: ConnectionID
       stateless_reset_token: StatelessResetToken
   }

   UnknownParameter = {
       id: uint64
       ? value: hexstring
   }

                  Figure 12: QUICParametersSet definition

5.4.  parameters_restored

   When using QUIC 0-RTT, clients are expected to remember and restore
   the server's transport parameters from the previous connection.  The
   parameters_restored event is used to indicate which parameters were
   restored and to which values when utilizing 0-RTT.  It has Base
   importance level.

   Note that not all transport parameters should be restored (many are
   even prohibited from being re-utilized).  The ones listed here are
   the ones expected to be useful for correct 0-RTT usage.

Marx, et al.               Expires 6 May 2027                  [Page 20]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICParametersRestored = {

       ; RFC9000
       ? disable_active_migration: bool
       ? max_idle_timeout: uint64
       ? max_udp_payload_size: uint64
       ? active_connection_id_limit: uint64
       ? initial_max_data: uint64
       ? initial_max_stream_data_bidi_local: uint64
       ? initial_max_stream_data_bidi_remote: uint64
       ? initial_max_stream_data_uni: uint64
       ? initial_max_streams_bidi: uint64
       ? initial_max_streams_uni: uint64

       ; RFC9221
       ? max_datagram_frame_size: uint64

       ; RFC9287
       ; can only be restored at the client.
       ; servers MUST NOT restore this parameter!
       ? grease_quic_bit: bool

       * $$quic-parametersrestored-extension
   }

                Figure 13: QUICParametersRestored definition

5.5.  packet_sent

   The packet_sent event indicates that a QUIC packet was sent.  It has
   Core importance level.

Marx, et al.               Expires 6 May 2027                  [Page 21]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICPacketSent = {
       header: PacketHeader
       ? frames: [* $QuicFrame]

       ; only if header.packet_type === "stateless_reset"
       ? stateless_reset_token: StatelessResetToken

       ; only if header.packet_type === "version_negotiation"
       ? supported_versions: [+ QuicVersion]
       ? raw: RawInfo
       ? datagram_payload_checksum: uint32
       ? is_mtu_probe_packet: bool

       ? trigger:
         ; RFC 9002 Section 6.1.1
         "retransmit_reordered" /
         ; RFC 9002 Section 6.1.2
         "retransmit_timeout" /
         ; RFC 9002 Section 6.2.4
         "pto_probe" /
         ; RFC 9002 6.2.3
         "retransmit_crypto" /
         ; needed for some CCs to figure out bandwidth allocations
         ; when there are no normal sends
         "cc_bandwidth_probe"

       * $$quic-packetsent-extension
   }

                    Figure 14: QUICPacketSent definition

   The encryption level and packet number space are not logged
   explicitly, because header.packet_type implies them for the packet
   types that have them.

   The datagram_payload_checksum field is described in Section 9.

   The is_mtu_probe_packet field defaults to false.

5.6.  packet_received

   The packet_received event indicates that a QUIC packet was received.
   It has Core importance level.

Marx, et al.               Expires 6 May 2027                  [Page 22]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICPacketReceived = {
       header: PacketHeader
       ? frames: [* $QuicFrame]

       ; only if header.packet_type === "stateless_reset"
       ? stateless_reset_token: StatelessResetToken

       ; only if header.packet_type === "version_negotiation"
       ? supported_versions: [+ QuicVersion]
       ? raw: RawInfo
       ? datagram_payload_checksum: uint32

       ? trigger:
           ; if packet was buffered because it couldn't be
           ; decrypted before
           "keys_available"

       * $$quic-packetreceived-extension
   }

                  Figure 15: QUICPacketReceived definition

   The encryption level and packet number space are not logged
   explicitly, because header.packet_type implies them for the packet
   types that have them.

   The datagram_payload_checksum field is described in Section 9.

5.7.  packet_dropped

   The packet_dropped event indicates that a QUIC packet was dropped.
   It has Base importance level.

Marx, et al.               Expires 6 May 2027                  [Page 23]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICPacketDropped = {

       ; Primarily packet_type should be filled here,
       ; as other fields might not be decryptable or parsable
       ? header: PacketHeader
       ? raw: RawInfo
       ? datagram_payload_checksum: uint32
       ? details: {* text => any}
       ? trigger:
           "internal_error" /
           "rejected" /
           "unsupported" /
           "invalid" /
           "duplicate" /
           "connection_unknown" /
           "decryption_failure" /
           "keys_unavailable" /
           "general"

       * $$quic-packetdropped-extension
   }

                  Figure 16: QUICPacketDropped definition

   The trigger field gives a general reason for dropping the packet, and
   the details field can hold additional implementation-specific
   information.  Some example situations for each trigger value include:

   *  "internal_error": not initialized, out of memory

   *  "rejected": limits reached, DDoS protection, unwilling to track
      more paths

   *  "unsupported": unknown or unsupported version

   *  "invalid": packet parsing or validation error

   *  "duplicate": duplicate packet

   *  "connection_unknown": packet does not relate to a known connection
      or connection ID

   *  "decryption_failure": decryption failed

   *  "keys_unavailable": decryption keys were unavailable

   *  "general": situations not clearly covered in the other categories

Marx, et al.               Expires 6 May 2027                  [Page 24]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Packets dropped as "unsupported" or "connection_unknown" often cannot
   be tied to a connection; see Section 1.3.

   The datagram_payload_checksum field is described in Section 9.

5.8.  packet_buffered

   The packet_buffered event is emitted when a packet is buffered
   because it cannot be processed yet, for example because the keys to
   decrypt it are not yet available.  Its full contents can be logged
   later, in a packet_received event, once it is processed.  It has Base
   importance level.

   QUICPacketBuffered = {

       ; primarily packet_type should be filled here as other elements
       ; might not be available yet
       ? header: PacketHeader
       ? raw: RawInfo
       ? datagram_payload_checksum: uint32
       ? trigger:
           ; indicates the parser cannot keep up, temporarily buffers
           ; packet for later processing
           "backpressure" /
           ; if packet cannot be decrypted because the proper keys were
           ; not yet available
           "keys_unavailable"

       * $$quic-packetbuffered-extension
   }

                  Figure 17: QUICPacketBuffered definition

   The datagram_payload_checksum field is described in Section 9.

5.9.  packets_acked

   The packets_acked event is emitted when one or more sent packets are
   acknowledged by the peer for the first time.  It has Extra importance
   level.

   Successive ACK frames can acknowledge the same packet, but this event
   is emitted only for the first acknowledgment of each packet.  This
   information can also be deduced from received ACK frames, though
   finding the first acknowledgment needs extra processing.
   Implementations that do not log frame contents can use this event
   instead.

Marx, et al.               Expires 6 May 2027                  [Page 25]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICPacketsAcked = {
       ? packet_number_space: $PacketNumberSpace
       ? packet_numbers: [+ uint64]

       * $$quic-packetsacked-extension
   }

                   Figure 18: QUICPacketsAcked definition

   The packet_number_space field defaults to "application_data", the
   packet number space that most packets in a typical QUIC connection
   use.

5.10.  udp_datagrams_sent

   The udp_datagrams_sent event indicates that one or more UDP datagrams
   were passed to the network socket.  It can show how QUIC packet
   buffers are drained to the operating system.  It has Extra importance
   level.

   QUICUDPDatagramsSent = {

       ; to support passing multiple at once
       ? count: uint16

       ; The RawInfo fields do not include the UDP headers,
       ; only the UDP payload
       ? raw: [+ RawInfo]

       ; ECN bits in the IP header
       ? ecn: [+ ECN]

       ? datagram_payload_checksums: [+ uint32]

       * $$quic-udpdatagramssent-extension
   }

                 Figure 19: QUICUDPDatagramsSent definition

   The RawInfo fields exclude UDP headers, because QUIC implementations
   do not always handle UDP directly.

   If an event omits the ecn field, the ECN bits are the same as on the
   last udp_datagrams_sent event.

   The datagram_payload_checksums field is described in Section 9.

Marx, et al.               Expires 6 May 2027                  [Page 26]
Internet-Draft       QUIC event definitions for qlog       November 2026

5.11.  udp_datagrams_received

   The udp_datagrams_received event indicates that one or more UDP
   datagrams were received from the network socket.  It can show how the
   operating system passes datagrams to the user-space stack.  It has
   Extra importance level.

   QUICUDPDatagramsReceived = {

       ; to support passing multiple at once
       ? count: uint16

       ; The RawInfo fields do not include the UDP headers,
       ; only the UDP payload
       ? raw: [+ RawInfo]

       ; ECN bits in the IP header
       ? ecn: [+ ECN]

       ? datagram_payload_checksums: [+ uint32]

       * $$quic-udpdatagramsreceived-extension
   }

               Figure 20: QUICUDPDatagramsReceived definition

   If an event omits the ecn field, the ECN bits are the same as on the
   last udp_datagrams_received event.

   The datagram_payload_checksums field is described in Section 9.

5.12.  udp_datagram_dropped

   The udp_datagram_dropped event indicates that a UDP datagram was
   dropped, typically because it does not contain a valid QUIC packet.
   If the datagram contains a valid QUIC packet that is dropped for
   another reason, the packet_dropped event (Section 5.7) is used
   instead.  It has Extra importance level.

   QUICUDPDatagramDropped = {

       ; The RawInfo fields do not include the UDP headers,
       ; only the UDP payload
       ? raw: RawInfo

       * $$quic-udpdatagramdropped-extension
   }

Marx, et al.               Expires 6 May 2027                  [Page 27]
Internet-Draft       QUIC event definitions for qlog       November 2026

                Figure 21: QUICUDPDatagramDropped definition

5.13.  stream_state_updated

   The stream_state_updated event is emitted when the state of a QUIC
   stream changes; see Section 3 of [QUIC-TRANSPORT].  Most state
   changes can be inferred from the frames that are sent and received,
   but an explicit event can be easier to use.  It has Base importance
   level.

   QUIC stream IDs encode whether a stream is unidirectional or
   bidirectional (see Section 2.1 of [QUIC-TRANSPORT]), but the optional
   stream_type field states it directly.

   Section 3 of [QUIC-TRANSPORT] describes the sending and receiving
   parts of a stream, each with its own state machine.  The stream_side
   field says which part's state changed.  If both parts change state at
   the same time, for example when both become "closed", two events with
   different stream_side values SHOULD be logged.

Marx, et al.               Expires 6 May 2027                  [Page 28]
Internet-Draft       QUIC event definitions for qlog       November 2026

   StreamType = "unidirectional" /
                "bidirectional"

   QUICStreamStateUpdated = {
       stream_id: uint64
       ? stream_type: StreamType
       ? old: $StreamState
       new: $StreamState
       stream_side: "sending" /
                    "receiving"
       ? trigger:
         ; stream state change was initiated by a local action
         "local" /
         ; stream state change was initiated by a remote action
         "remote"

       * $$quic-streamstateupdated-extension
   }

   BaseStreamStates =  "idle" /
                       "open" /
                       "closed"

   GranularStreamStates =
       ; bidirectional stream states, RFC 9000 Section 3.4.
       "half_closed_local" /
       "half_closed_remote" /
       ; sending-side stream states, RFC 9000 Section 3.1.
       "ready" /
       "send" /
       "data_sent" /
       "reset_sent" /
       ; receive-side stream states, RFC 9000 Section 3.2.
       "receive" /
       "size_known" /
       "data_read" /
       "reset_read" /
       ; both-side states
       "data_received" /
       "reset_received" /
       ; qlog-defined: memory actually freed
       "destroyed"

   $StreamState /= BaseStreamStates / GranularStreamStates

                Figure 22: QUICStreamStateUpdated definition

Marx, et al.               Expires 6 May 2027                  [Page 29]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUIC implementations SHOULD log the BaseStreamStates, and can add the
   GranularStreamStates when more in-depth debugging is required.  Tools
   SHOULD handle both kinds equally.

   The trigger field can show which endpoint initiated a state change,
   for example when a stream is closed because of a RESET_STREAM or
   STOP_SENDING frame.

5.14.  Frame-Related Events

   While the packet_sent (Section 5.5) and packet_received (Section 5.6)
   events can convey all frames contained in a single QUIC packet, some
   implementations might not be able or willing to include frame
   information at the moment either event is logged.

   The frames_created and frames_parsed events log frames independently
   of packets.

   A qlog trace can contain both packet- and frame-related events.
   However, it is RECOMMENDED that implementations avoid generating
   events with duplicate or redundant frame information, since doing so
   inflates the size of logs.

   Where an implementation logs both packet- and frame-related events,
   the optional packet_numbers field in frame-related events can be used
   to link frames to packets explicitly.  The field is an array so that
   a single event can log frames that belong to different packets.  The
   frames and packet_numbers arrays are mapped to each other by the
   position and order of their entries.  If the packet_numbers field is
   logged, every frame MUST have a corresponding packet number at the
   same index.

   For example, an instance of the frames_parsed event that represents
   four STREAM frames received over two packets can be serialized as:

  "frames":[
    {"frame_type":"stream","stream_id":0,"offset":0,"raw":{"length":5}},
    {"frame_type":"stream","stream_id":0,"offset":5,"raw":{"length":5}},
    {"frame_type":"stream","stream_id":1,"offset":0,"raw":{"length":9}},
    {"frame_type":"stream","stream_id":1,"offset":9,"raw":{"length":9}}
  ],
  "packet_numbers":[
    1,
    1,
    2,
    2
  ]

Marx, et al.               Expires 6 May 2027                  [Page 30]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Frame-related events omit information that is available in the
   packet_received or packet_sent event, such as the packet's encryption
   level.  Use cases that need such information are better served by
   those events.

   Extensions can use frame-related events to log information that is
   not available when a packet event is logged, for example because
   frame processing was deferred.

5.14.1.  frames_created

   The frames_created event indicates that a set of QUIC frames was
   created.  It has Extra importance level.

   QUICFramesCreated = {
       frames: [* $QuicFrame]
       ? packet_numbers: [* uint64]

       * $$quic-framescreated-extension
   }

                  Figure 23: QUICFramesCreated definition

5.14.2.  frames_parsed

   The frames_parsed event indicates that a set of QUIC frames was
   parsed.  It has Extra importance level.

   QUICFramesParsed = {
       frames: [* $QuicFrame]
       ? packet_numbers: [* uint64]

       * $$quic-framesparsed-extension
   }

                   Figure 24: QUICFramesParsed definition

5.15.  stream_data_moved

   The stream_data_moved event indicates that QUIC stream data moved
   between layers.  It has Base importance level.

   For example, data can move from an application protocol such as
   HTTP/3 to QUIC stream buffers, or the other way.  Logging these moves
   can show the flow of data, how long data stays in each buffer, and
   the overhead introduced by each layer.

Marx, et al.               Expires 6 May 2027                  [Page 31]
Internet-Draft       QUIC event definitions for qlog       November 2026

   This event can also show whether received stream data is passed to
   the application protocol immediately or in batches.  Data can be
   passed, for example, once per received packet, or in a batch after
   all received packets are processed.  This can help identify
   bottlenecks, flow control issues, or scheduling problems.

   The raw.length field gives the number of bytes moved.  Because this
   event covers stream data only, there are no packet or frame headers,
   and raw.length MUST reflect that.

   The additional_info field can log information about the stream state.
   For example, an application that moves data into the transport and
   ends the stream at the same time can log "fin_set".  A transport that
   has received an instruction to reset a stream can tell the
   application with "stream_reset".  In both cases, raw.length can be
   omitted or be zero.

   This event covers only data in QUIC streams.  For data in QUIC
   datagrams, see the datagram_data_moved event (Section 5.16).

   QUICStreamDataMoved = {
       ? stream_id: uint64
       ? offset: uint64

       ? from: $DataLocation
       ? to: $DataLocation

       ? additional_info: $DataMovedAdditionalInfo

       ? raw: RawInfo

       * $$quic-streamdatamoved-extension
   }

   $DataLocation /=  "application" /
                     "transport" /
                     "network"

   $DataMovedAdditionalInfo /= "fin_set" /
                               "stream_reset"

                 Figure 25: QUICStreamDataMoved definition

5.16.  datagram_data_moved

   The datagram_data_moved event indicates that QUIC datagram data (see
   [QUIC-DATAGRAM]) moved between layers.  It has Base importance level.

Marx, et al.               Expires 6 May 2027                  [Page 32]
Internet-Draft       QUIC event definitions for qlog       November 2026

   For example, data can move from an application protocol such as
   WebTransport to QUIC buffers, or the other way.  Logging these moves
   can show the flow of data, how long data stays in each buffer, and
   the overhead introduced by each layer.

   This event can also show whether received datagram data is passed to
   the application protocol immediately or in batches.  Data can be
   passed, for example, once per received packet, or in a batch after
   all received packets are processed.  This can help identify
   bottlenecks or scheduling problems.

   The raw.length field gives the number of bytes moved.  Because this
   event covers datagram data only, there are no packet or frame
   headers, and raw.length MUST reflect that.

   This event covers only data in QUIC datagrams.  For data in QUIC
   streams, see the stream_data_moved event (Section 5.15).

   QUICDatagramDataMoved = {
       ? from: $DataLocation
       ? to: $DataLocation
       ? raw: RawInfo

       * $$quic-datagramdatamoved-extension
   }

                Figure 26: QUICDatagramDataMoved definition

5.17.  datagram_dropped

   The datagram_dropped event indicates that QUIC DATAGRAM data (see
   [RFC9221]) was discarded locally, before sending or after reception.
   It has Base importance level.

   The direction field identifies the sending or receiving side, and
   trigger indicates the reason for discarding the data.  The raw.length
   field MUST count discarded payload bytes, excluding packet and frame
   headers.

   Received DATAGRAM data can be discarded while its packet is still
   acknowledged.  For drops of entire QUIC packets, use packet_dropped
   (Section 5.7).

Marx, et al.               Expires 6 May 2027                  [Page 33]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICDatagramDropped = {
       ? direction: "sending" /
                    "receiving"
       ? raw: RawInfo
       ? trigger:
           ; insufficient space in a send or receive buffer
           "buffer_full" /
           ; datagram data exceeds the maximum payload size
           "too_large" /
           text

       * $$quic-datagramdropped-extension
   }

                 Figure 27: QUICDatagramDropped definition

5.18.  connection_data_blocked_updated

   The connection_data_blocked_updated event indicates that the QUIC
   connection became blocked or unblocked for sending data.  It has
   Extra importance level.

   Depending on the reason, a blocked connection cannot send stream
   data, datagram data, or both, until that reason is resolved.  The
   stream_data_blocked_updated and datagram_data_blocked_updated events
   give more detail for each type of data.

   QUICConnectionDataBlockedUpdated = {
       ? old: $BlockedState
       new: $BlockedState

       ? reason: $BlockedReason

       * $$quic-connectiondatablockedupdated-extension
   }

   $BlockedState /= "blocked" /
                  "unblocked"

   $BlockedReason /= "scheduling" /
                     "pacing" /
                     "amplification_protection" /
                     "congestion_control" /
                     "connection_flow_control" /
                     "stream_flow_control" /
                     "stream_id" /
                     "application"

Marx, et al.               Expires 6 May 2027                  [Page 34]
Internet-Draft       QUIC event definitions for qlog       November 2026

           Figure 28: QUICConnectionDataBlockedUpdated definition

5.19.  stream_data_blocked_updated

   The stream_data_blocked_updated event indicates that a QUIC stream
   became blocked or unblocked for sending.  It has Extra importance
   level.

   QUICStreamDataBlockedUpdated = {
       ? old: $BlockedState
       new: $BlockedState

       stream_id: uint64

       ? reason: $BlockedReason

       * $$quic-streamdatablockedupdated-extension
   }

             Figure 29: QUICStreamDataBlockedUpdated definition

5.20.  datagram_data_blocked_updated

   The datagram_data_blocked_updated event indicates that QUIC datagrams
   became blocked or unblocked for sending.  It has Extra importance
   level.

   QUICDatagramDataBlockedUpdated = {
       ? old: $BlockedState
       new: $BlockedState

       ? reason: $BlockedReason

       * $$quic-datagramdatablockedupdated-extension
   }

            Figure 30: QUICDatagramDataBlockedUpdated definition

5.21.  migration_state_updated

   The migration_state_updated event logs the progress of a connection
   migration by a client; see Section 9 of [QUIC-TRANSPORT].  It has
   Extra importance level.

   Most details of a migration can be inferred from PATH_CHALLENGE and
   PATH_RESPONSE frames, together with tuple_assigned events.  However,
   it can be useful to log the progress of the migration, and any
   decisions made, in a single event.

Marx, et al.               Expires 6 May 2027                  [Page 35]
Internet-Draft       QUIC event definitions for qlog       November 2026

   The MigrationState values follow the steps in Section 9 of
   [QUIC-TRANSPORT]: the probing_* values cover probing a new path
   (Section 9.1 of [QUIC-TRANSPORT]), and the migration_* values cover
   migrating the connection (Section 9.2 of [QUIC-TRANSPORT]).

   Implementations that log per-path information in
   migration_state_updated events SHOULD also emit tuple_assigned
   events, to serve as the ground truth for tuple information.

   QUICMigrationStateUpdated = {
       ? old: MigrationState
       new: MigrationState

       ? tuple_id: TupleID

       ; the information for traffic going towards the remote receiver
       ? tuple_remote: TupleEndpointInfo

       ; the information for traffic coming in at the local endpoint
       ? tuple_local: TupleEndpointInfo

       * $$quic-migrationstateupdated-extension
   }

   ; Note that MigrationState does not describe a full state machine
   ; These entries are not necessarily chronological,
   ; nor will they always all appear during
   ; a connection migration attempt.
   MigrationState =
       ; probing packets are sent, migration not initiated yet
       "probing_started" /
       ; did not get reply to probing packets,
       ; discarding path as an option
       "probing_abandoned" /
       ; received reply to probing packets, path is migration candidate
       "probing_successful" /
       ; non-probing packets are sent, attempting migration
       "migration_started" /
       ; something went wrong during the migration, abandoning attempt
       "migration_abandoned" /
       ; new path is now fully used, old path is discarded
       "migration_complete"

              Figure 31: QUICMigrationStateUpdated definition

Marx, et al.               Expires 6 May 2027                  [Page 36]
Internet-Draft       QUIC event definitions for qlog       November 2026

5.22.  timer_updated

   The timer_updated event is emitted when a timer changes state.  It
   has Extra importance level.

   The event_type field takes one of three values:

   *  "set": the timer is set, and delta gives the time until it
      triggers

   *  "expired": the timer expired

   *  "cancelled": the timer was cancelled

   An update to an active timer's timeout is logged as a new "set"
   event.

   The recovery timer types correspond to timers in Section 6 of
   [QUIC-RECOVERY] and Appendix A.8 of [QUIC-RECOVERY]:

   *  "ack": the time threshold loss detection timeout

   *  "pto": the probe timeout

   *  "loss_timeout": the single, multi-modal loss detection timer that
      covers both

   QUIC uses a variety of timers, and how they are used can depend on
   the implementation.  Implementers can add fields to this event
   through $$quic-timerupdated-extension, or add timer types through
   $TimerType.

Marx, et al.               Expires 6 May 2027                  [Page 37]
Internet-Draft       QUIC event definitions for qlog       November 2026

   ; a non-exhaustive list of typically employed timers
   $TimerType /= "ack" /
                 "pto" /
                 "loss_timeout" /
                 "path_validation" /
                 "handshake_timeout" /
                 "idle_timeout"

   QUICTimerUpdated = {
       ? timer_type: $TimerType

       ; to disambiguate in case there are multiple timers
       ; of the same type
       ? timer_id: uint64

       ; if used for recovery timers, this can be useful information
       ? packet_number_space: $PacketNumberSpace
       event_type: "set" /
                   "expired" /
                   "cancelled"

       ; if event_type === "set": delta time is in ms from
       ; this event's timestamp until when the timer should trigger
       ? delta: float32

       * $$quic-timerupdated-extension
   }

                   Figure 32: QUICTimerUpdated definition

6.  Security Events

6.1.  key_updated

   The key_updated event indicates that a key was installed or updated.
   It has Base importance level.

   This happens when TLS provides new keys during the handshake, and at
   each 1-RTT key update; see Section 6 of [QUIC-TLS].

Marx, et al.               Expires 6 May 2027                  [Page 38]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICKeyUpdated = {
       key_type: $KeyType
       ? old: hexstring
       ? new: hexstring

       ; needed for 1RTT key updates
       ? key_phase: uint64
       ? trigger:
           ; (e.g., initial, handshake and 0-RTT keys
           ; are generated by TLS)
           "tls" /
           "remote_update" /
           "local_update"

       * $$quic-keyupdated-extension
   }

                    Figure 33: QUICKeyUpdated definition

   The key_phase field holds the full key phase, which identifies the
   generation of keys; it corresponds to @M and @N in Figure 9 of
   Section 6 of [QUIC-TLS].  The Key Phase bit in the packet header is
   the least significant bit of this value.

6.2.  key_discarded

   The key_discarded event indicates that a key was discarded.  It has
   Base importance level.

   Keys are discarded, for example, when the connection moves to a new
   encryption level during the handshake, or after a key update; see
   Section 4.9 of [QUIC-TLS].

   QUICKeyDiscarded = {
       key_type: $KeyType
       ? key: hexstring

       ; needed for 1RTT key updates
       ? key_phase: uint64
       ? trigger:
           ; (e.g., initial, handshake and 0-RTT keys
           ; are generated by TLS)
           "tls" /
           "remote_update" /
           "local_update"

       * $$quic-keydiscarded-extension
   }

Marx, et al.               Expires 6 May 2027                  [Page 39]
Internet-Draft       QUIC event definitions for qlog       November 2026

                   Figure 34: QUICKeyDiscarded definition

7.  Recovery Events

   Most of the events in this section are kept generic to support
   different recovery approaches and congestion control algorithms.  The
   old, new, and trigger fields of congestion_state_updated, for
   instance, are free text, so their values depend on the algorithm.

   Tools that process these events SHOULD try to handle such values even
   when they don't recognize them.  For example, a tool that plots
   congestion states on a timeline can label an unknown state with the
   value of the new field.

7.1.  recovery_parameters_set

   The recovery_parameters_set event groups initial parameters from both
   loss detection and congestion control into a single event.  It has
   Base importance level.

   These parameters are typically set once and never change.
   Implementations that change them during the connection MAY emit the
   recovery_parameters_set event more than once.

   The reordering_threshold field contains the packet threshold for loss
   detection, or "disabled" if packet-threshold loss detection is
   disabled.

Marx, et al.               Expires 6 May 2027                  [Page 40]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUICRecoveryParametersSet = {

       ; Loss detection, see RFC 9002 Appendix A.2
       ; in amount of packets
       ? reordering_threshold: uint16 / "disabled"

       ; as RTT multiplier
       ? time_threshold: float32

       ; in ms
       timer_granularity: uint16

       ; in ms
       ? initial_rtt:float32

       ; congestion control, see RFC 9002 Appendix B.2
       ; in bytes. Note that this could be updated after pmtud
       ? max_datagram_size: uint32

       ; in bytes
       ? initial_congestion_window: uint64

       ; Note that this could change when max_datagram_size changes
       ; in bytes
       ? minimum_congestion_window: uint64
       ? loss_reduction_factor: float32

       ; as PTO multiplier
       ? persistent_congestion_threshold: uint16

       * $$quic-recoveryparametersset-extension
   }

              Figure 35: QUICRecoveryParametersSet definition

   Parameters that this document does not define, such as those of other
   loss detection and recovery algorithms, can be added through $$quic-
   recoveryparametersset-extension.

7.2.  recovery_metrics_updated

   The recovery_metrics_updated event is emitted when one or more of the
   observable recovery metrics change value.  It has Core importance
   level.

Marx, et al.               Expires 6 May 2027                  [Page 41]
Internet-Draft       QUIC event definitions for qlog       November 2026

   Implementations SHOULD group all metric updates that happen at or
   around the same time into a single recovery_metrics_updated event.
   For example, if min_rtt and smoothed_rtt change at the same time,
   they are logged in one event, not two.  Each event is only guaranteed
   to contain at least one of the listed metrics.

   QUICRecoveryMetricsUpdated = {

       ; Loss detection, see RFC 9002 Appendix A.3
       ; all following rtt fields are expressed in ms
       ? min_rtt: float32
       ? smoothed_rtt: float32
       ? latest_rtt: float32
       ? rtt_variance: float32
       ? pto_count: uint16

       ; Congestion control, see RFC 9002 Appendix B.2.
       ; in bytes
       ? congestion_window: uint64
       ? bytes_in_flight: uint64

       ; in bytes
       ? ssthresh: uint64

       ; qlog defined
       ; sum of all packet number spaces
       ? packets_in_flight: uint64

       ; in bits per second
       ? pacing_rate: uint64

       * $$quic-recoverymetricsupdated-extension
   }

              Figure 36: QUICRecoveryMetricsUpdated definition

   To make logging easier, implementations MAY log values that are the
   same as previously reported values; for example, two consecutive
   recovery_metrics_updated events can report the same min_rtt.
   However, implementations SHOULD try to log only values that changed.

   Metrics that this document does not define, such as those of other
   loss detection and recovery algorithms, can be added through $$quic-
   recoverymetricsupdated-extension.

Marx, et al.               Expires 6 May 2027                  [Page 42]
Internet-Draft       QUIC event definitions for qlog       November 2026

7.3.  congestion_state_updated

   The congestion_state_updated event indicates when the congestion
   controller enters a new state that changes its behavior.  It has Base
   importance level.

   This document does not define values for the event's fields.
   Congestion control algorithms have different states and different
   causes for moving between them, and stacks can implement the same
   algorithm differently.  For example, the NewReno controller in
   Section 7.3 of [QUIC-RECOVERY] has three states: slow start,
   recovery, and congestion avoidance.

   QUICCongestionStateUpdated = {
       ? old: text
       new: text
       ? trigger: text

       * $$quic-congestionstateupdated-extension
   }

              Figure 37: QUICCongestionStateUpdated definition

   The trigger field SHOULD be logged if a state change can have more
   than one cause.  For example, NewReno enters recovery when it detects
   packet loss or when the ECN-CE count increases, so the trigger field
   shows which of the two caused the change.

7.4.  packet_lost

   The packet_lost event is emitted when loss detection declares a
   packet lost.  It has Core importance level.

   QUICPacketLost = {

       ; should include at least the packet_type and packet_number
       ? header: PacketHeader

       ? frames: [* $QuicFrame]
       ? is_mtu_probe_packet: bool
       ? trigger:
           "reordering_threshold" /
           "time_threshold" /
           "pto_expired"

       * $$quic-packetlost-extension
   }

Marx, et al.               Expires 6 May 2027                  [Page 43]
Internet-Draft       QUIC event definitions for qlog       November 2026

                    Figure 38: QUICPacketLost definition

   The frames field lists the frames that the lost packet carried.  It
   is optional, because not all implementations keep sent packets in
   full.  The data that is then marked for retransmission can be logged
   with the marked_for_retransmit event (Section 7.5).

   The is_mtu_probe_packet field marks a packet that was sent as a Path
   MTU probe.  The loss of such a packet is not a reliable sign of
   congestion; see Section 14.4 of [QUIC-TRANSPORT].  It defaults to
   false.

   The trigger field SHOULD be logged.  Its value shows how loss
   detection declared the packet lost:

   *  reordering_threshold: the packet threshold was exceeded; see
      Section 6.1.1 of [QUIC-RECOVERY].

   *  time_threshold: the time threshold was exceeded; see Section 6.1.2
      of [QUIC-RECOVERY].

   *  pto_expired: the probe timeout expired, and the sender declared
      the packet lost instead of sending a probe; see Section 6.2.4 of
      [QUIC-RECOVERY].

7.5.  marked_for_retransmit

   The marked_for_retransmit event indicates which data was marked for
   retransmission after packet loss was detected.  It has Extra
   importance level.

   This single event covers all types of retransmittable data, which it
   logs using the existing QUIC frame definitions.

   A packet_lost event (Section 7.4) records that a packet was declared
   lost, and can list the frames it carried.  A marked_for_retransmit
   event records what the implementation then marks for retransmission.
   The two can differ, because not every frame is retransmitted (ACK and
   PADDING frames never are), and retransmitted data need not be sent in
   the same frames; see Section 13.3 of [QUIC-TRANSPORT].

   An implementation that retransmits the frames of a lost packet
   unchanged can log them here, or skip this event and use the frames in
   the packet_lost event instead.  An implementation with more complex
   logic, such as one that marks ranges of a stream's send buffer as in
   flight, or one that does not keep sent frames in full, can log frames
   that describe the data it marked for retransmission.  These frames
   need not match any frame that was sent or will be sent.

Marx, et al.               Expires 6 May 2027                  [Page 44]
Internet-Draft       QUIC event definitions for qlog       November 2026

   If an implementation logs packet_sent events, tools can infer much of
   this data from them.  For example, overlapping stream offsets and
   lengths show when data was retransmitted.

   QUICMarkedForRetransmit = {
       frames: [+ $QuicFrame]

       * $$quic-markedforretransmit-extension
   }

               Figure 39: QUICMarkedForRetransmit definition

7.6.  ecn_state_updated

   The ecn_state_updated event indicates a progression in the ECN state
   machine as described in Appendix A.4 of [QUIC-TRANSPORT].  It has
   Extra importance level.

   QUICECNStateUpdated = {
      ? old: ECNState
       new: ECNState
       ? trigger: text

       * $$quic-ecnstateupdated-extension
   }

   ECNState =
     ; ECN testing in progress
     "testing" /
     ; ECN state unknown, waiting for acknowledgements
     ; for testing packets
     "unknown" /
     ; ECN testing failed
     "failed" /
     ; testing was successful
     "capable"

                 Figure 40: QUICECNStateUpdated definition

   The trigger field can be used to log why the state changed, for
   example which ECN validation check in Section 13.4.2 of
   [QUIC-TRANSPORT] failed.

8.  QUIC Data Type Definitions

8.1.  QuicVersion

   QuicVersion = hexstring

Marx, et al.               Expires 6 May 2027                  [Page 45]
Internet-Draft       QUIC event definitions for qlog       November 2026

                     Figure 41: QuicVersion definition

8.2.  ConnectionID

   ConnectionID = hexstring

                     Figure 42: ConnectionID definition

8.3.  Initiator

   Initiator = "local" /
               "remote"

                      Figure 43: Initiator definition

8.4.  IPAddressPort

   ; an IP address can either be a "human readable" form
   ; (e.g., "127.0.0.1" for v4 or
   ; "2001:0db8:85a3:0000:0000:8a2e:0370:7334" for v6) or
   ; use a raw byte-form (as the string forms can be ambiguous).
   ; Additionally, the IP address and port pair can be logged as an
   ; application-defined redacted string for privacy or security reasons.
   IPAddressPort = {
       ip: text / hexstring
       port: uint16
   } / text

                    Figure 44: IPAddressPort definition

8.5.  TupleEndpointInfo

   TupleEndpointInfo describes one half, or direction, of a four-tuple.
   A full tuple has two halves: the server sends to the client's IP
   address and port, and the client sends to the server's IP address and
   port.  Each direction uses its own destination connection ID.

   Structures that log tuple information SHOULD therefore include two
   TupleEndpointInfo instances, one for each half of the tuple.

Marx, et al.               Expires 6 May 2027                  [Page 46]
Internet-Draft       QUIC event definitions for qlog       November 2026

   TupleEndpointInfo = {
       ? address_v4: IPAddressPort
       ? address_v6: IPAddressPort

       ; Even though usually only a single ConnectionID
       ; is associated with a given tuple/path at a time,
       ; there are situations where there can be an overlap
       ; or a need to keep track of previous ConnectionIDs
       ? connection_ids: [+ ConnectionID]

       * $$quic-tupleendpointinfo-extension
   }

                  Figure 45: TupleEndpointInfo definition

8.6.  PacketType

   $PacketType /=  "initial" /
                   "handshake" /
                   "0RTT" /
                   "1RTT" /
                   "retry" /
                   "version_negotiation" /
                   "stateless_reset" /
                   "unknown"

                      Figure 46: PacketType definition

8.7.  PacketNumberSpace

   $PacketNumberSpace /= "initial" /
                         "handshake" /
                         "application_data"

                  Figure 47: PacketNumberSpace definition

8.8.  PacketHeader

   If a packet type has no known $PacketType string, packet_type can be
   "unknown", and packet_type_bytes then holds the numerical value
   without variable-length integer encoding.

   PacketHeader omits the fixed bit and the reserved bits because QUIC
   version 1 gives them fixed values; see Section 17 of
   [QUIC-TRANSPORT].  Their values can be logged in the raw.data field
   of the event that logs the PacketHeader.

Marx, et al.               Expires 6 May 2027                  [Page 47]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QUIC extensions that use these bits, such as the QUIC Bit greasing
   extension ([GREASEBIT]), can log that use with new events, similar to
   spin_bit_updated, or with fields added to PacketHeader through
   $$quic-packetheader-extension.

   For long header packets of type initial, handshake, and 0RTT, the
   length field of the packet header is logged in the qlog raw.length
   field, and the value signifies the length of the packet number plus
   the payload.

   PacketHeader = {
       packet_type: $PacketType

       ; only if packet_type === "unknown"
       ? packet_type_bytes: uint64

       ; only if packet_type === "1RTT"
       ? spin_bit: bool

       ; only if packet_type === "1RTT", and if the key phase was
       ; determined from the key_phase_bit
       ? key_phase: uint64

       ; only if packet_type === "1RTT", and if key_phase is not set
       ? key_phase_bit: bool

       ; only if packet_type === "initial" || "handshake" || "0RTT" ||
       ;                         "1RTT"
       ? packet_number_length: uint8

       ; only if packet_type === "initial" || "handshake" || "0RTT" ||
       ;                         "1RTT"
       ? packet_number: uint64

       ; only if packet_type === "initial" || "retry"
       ? token: Token

       ; only if present in the header.
       ; if correctly using connection_id_updated events,
       ; dcid can be skipped for 1RTT packets
       ? version: QuicVersion
       ? scil: uint8
       ? dcil: uint8
       ? scid: ConnectionID
       ? dcid: ConnectionID

       * $$quic-packetheader-extension
   }

Marx, et al.               Expires 6 May 2027                  [Page 48]
Internet-Draft       QUIC event definitions for qlog       November 2026

                     Figure 48: PacketHeader definition

8.9.  Token

   Token = {
       ? type: $TokenType

       ; decoded fields included in the token
       ; (typically: peer's IP address, creation time)
       ? details: {
         * text => any
       }
       ? raw: RawInfo

       * $$quic-token-extension
   }

   $TokenType /= "retry" /
                 "resumption"

                        Figure 49: Token definition

   The token carried in an Initial packet is either a token from a Retry
   packet, or one that the server provided earlier in a NEW_TOKEN frame,
   for address validation in a later connection; see Section 8.1.3 of
   [QUIC-TRANSPORT].  Both kinds typically encode metadata that the
   server uses to check the token, but the metadata and its format are
   implementation-specific.  The details field can log that metadata.

8.10.  StatelessResetToken

   ; always 16 bytes
   StatelessResetToken = hexstring

                 Figure 50: StatelessResetToken definition

   The stateless reset token is defined in Section 10.3 of
   [QUIC-TRANSPORT].

8.11.  KeyType

Marx, et al.               Expires 6 May 2027                  [Page 49]
Internet-Draft       QUIC event definitions for qlog       November 2026

   $KeyType /= "server_initial_secret" /
               "client_initial_secret" /
               "server_handshake_secret" /
               "client_handshake_secret" /
               "server_0rtt_secret" /
               "client_0rtt_secret" /
               "server_1rtt_secret" /
               "client_1rtt_secret"

                       Figure 51: KeyType definition

8.12.  ECN

   ECN holds the ECN codepoint carried in the IP header; see
   Section 13.4 of [QUIC-TRANSPORT].

   ECN = "Not-ECT" / "ECT(1)" / "ECT(0)" / "CE"

                         Figure 52: ECN definition

8.13.  QUIC Frames

   The generic $QuicFrame is defined here as a CDDL "type socket"
   extension point.  It can be extended to support additional QUIC frame
   types.

   ; The QuicFrame is any key-value map (e.g., JSON object)
   $QuicFrame /= {
       * text => any
   }

                Figure 53: QuicFrame type socket definition

   The QUIC frame types defined in this document are as follows:

Marx, et al.               Expires 6 May 2027                  [Page 50]
Internet-Draft       QUIC event definitions for qlog       November 2026

   QuicBaseFrames =  PaddingFrame /
                     PingFrame /
                     AckFrame /
                     ResetStreamFrame /
                     ResetStreamAtFrame /
                     StopSendingFrame /
                     CryptoFrame /
                     NewTokenFrame /
                     StreamFrame /
                     MaxDataFrame /
                     MaxStreamDataFrame /
                     MaxStreamsFrame /
                     DataBlockedFrame /
                     StreamDataBlockedFrame /
                     StreamsBlockedFrame /
                     NewConnectionIDFrame /
                     RetireConnectionIDFrame /
                     PathChallengeFrame /
                     PathResponseFrame /
                     ConnectionCloseFrame /
                     HandshakeDoneFrame /
                     UnknownFrame /
                     DatagramFrame

   $QuicFrame /= QuicBaseFrames

                    Figure 54: QuicBaseFrames definition

8.13.1.  PaddingFrame

   A PADDING frame is a single byte with the value 0, so each padding
   byte is its own frame; see Section 19.1 of [QUIC-TRANSPORT].  Logging
   each one as a separate PaddingFrame could add hundreds of entries to
   a single packet event, for example when a client pads an Initial
   packet to 1200 bytes.  Implementations SHOULD instead log a single
   PaddingFrame for the packet, and set its raw.payload_length field to
   the number of PADDING frames in the packet.

   PaddingFrame = {
       frame_type: "padding"
       ? raw: RawInfo
   }

                     Figure 55: PaddingFrame definition

8.13.2.  PingFrame

Marx, et al.               Expires 6 May 2027                  [Page 51]
Internet-Draft       QUIC event definitions for qlog       November 2026

   PingFrame = {
       frame_type: "ping"
       ? raw: RawInfo
   }

                      Figure 56: PingFrame definition

8.13.3.  AckFrame

   ; either a single number (e.g., [1]) or two numbers (e.g., [1,2]).
   ; For two numbers:
   ; the first number is "from": lowest packet number in interval
   ; the second number is "to": up to and including the highest
   ; packet number in the interval
   AckRange = [1*2 uint64]

   AckFrame = {
       frame_type: "ack"

       ; in ms
       ? ack_delay: float32

       ; e.g., looks like [[1,2],[4,5], [7], [10,22]] serialized
       ? acked_ranges: [+ AckRange]

       ; ECN (explicit congestion notification) related fields
       ; (not always present)
       ? ect1: uint64
       ? ect0: uint64
       ? ce: uint64
       ? raw: RawInfo
   }

                       Figure 57: AckFrame definition

   The ranges in acked_ranges do not have to be in order; for example,
   [[5,9],[1,4]] is valid.

   The two numbers in a range can be equal; for example, [120,120] means
   that packet 120 was acknowledged.  In that case, implementations
   SHOULD log [120] instead, and tools MUST handle both forms.

8.13.4.  ResetStreamFrame

   If an error code has no known ApplicationError string, error can be
   "unknown", and error_code then holds the numerical value without
   variable-length integer encoding.

Marx, et al.               Expires 6 May 2027                  [Page 52]
Internet-Draft       QUIC event definitions for qlog       November 2026

   ResetStreamFrame = {
       frame_type: "reset_stream"
       stream_id: uint64
       error: $ApplicationError

       ; if error === "unknown"
       ? error_code: uint64

       ; in bytes
       final_size: uint64
       ? raw: RawInfo
   }

                   Figure 58: ResetStreamFrame definition

8.13.5.  ResetStreamAtFrame

   The RESET_STREAM_AT frame is defined in Section 4 of
   [RESET-STREAM-AT].

   If an error code has no known ApplicationError string, error can be
   "unknown", and error_code then holds the numerical value without
   variable-length integer encoding.

   ResetStreamAtFrame = {
       frame_type: "reset_stream_at"
       stream_id: uint64
       error: $ApplicationError

       ; if error === "unknown"
       ? error_code: uint64

       ; in bytes
       final_size: uint64

       ; in bytes
       reliable_size: uint64

       ? raw: RawInfo
   }

                  Figure 59: ResetStreamAtFrame definition

8.13.6.  StopSendingFrame

   If an error code has no known ApplicationError string, error can be
   "unknown", and error_code then holds the numerical value without
   variable-length integer encoding.

Marx, et al.               Expires 6 May 2027                  [Page 53]
Internet-Draft       QUIC event definitions for qlog       November 2026

   StopSendingFrame = {
       frame_type: "stop_sending"
       stream_id: uint64
       error: $ApplicationError

       ; if error === "unknown"
       ? error_code: uint64

       ? raw: RawInfo
   }

                   Figure 60: StopSendingFrame definition

8.13.7.  CryptoFrame

   The length field of the CRYPTO frame MUST be logged in the qlog
   raw.length field.  The other sub-fields of the raw field are
   optional.

   CryptoFrame = {
       frame_type: "crypto"
       offset: uint64
       raw: RawInfo
   }

                     Figure 61: CryptoFrame definition

8.13.8.  NewTokenFrame

   NewTokenFrame = {
     frame_type: "new_token"
     token: Token
     ? raw: RawInfo
   }

                    Figure 62: NewTokenFrame definition

8.13.9.  StreamFrame

   If the STREAM frame contains a length field, it MUST be logged in the
   qlog raw.length field.  If it does not, the implementation MAY
   calculate the actual frame byte length itself and log that in
   raw.length if necessary.

   The offset field defaults to 0, and the fin field defaults to false.

Marx, et al.               Expires 6 May 2027                  [Page 54]
Internet-Draft       QUIC event definitions for qlog       November 2026

   StreamFrame = {
       frame_type: "stream"
       stream_id: uint64
       ? offset: uint64
       ? fin: bool
       ? raw: RawInfo
   }

                     Figure 63: StreamFrame definition

8.13.10.  MaxDataFrame

   MaxDataFrame = {
     frame_type: "max_data"
     maximum: uint64
     ? raw: RawInfo
   }

                     Figure 64: MaxDataFrame definition

8.13.11.  MaxStreamDataFrame

   MaxStreamDataFrame = {
     frame_type: "max_stream_data"
     stream_id: uint64
     maximum: uint64
     ? raw: RawInfo
   }

                  Figure 65: MaxStreamDataFrame definition

8.13.12.  MaxStreamsFrame

   MaxStreamsFrame = {
     frame_type: "max_streams"
     stream_type: StreamType
     maximum: uint64
     ? raw: RawInfo
   }

                   Figure 66: MaxStreamsFrame definition

8.13.13.  DataBlockedFrame

Marx, et al.               Expires 6 May 2027                  [Page 55]
Internet-Draft       QUIC event definitions for qlog       November 2026

   DataBlockedFrame = {
     frame_type: "data_blocked"
     limit: uint64
     ? raw: RawInfo
   }

                   Figure 67: DataBlockedFrame definition

8.13.14.  StreamDataBlockedFrame

   StreamDataBlockedFrame = {
     frame_type: "stream_data_blocked"
     stream_id: uint64
     limit: uint64
     ? raw: RawInfo
   }

                Figure 68: StreamDataBlockedFrame definition

8.13.15.  StreamsBlockedFrame

   StreamsBlockedFrame = {
     frame_type: "streams_blocked"
     stream_type: StreamType
     limit: uint64
     ? raw: RawInfo
   }

                 Figure 69: StreamsBlockedFrame definition

8.13.16.  NewConnectionIDFrame

   NewConnectionIDFrame = {
     frame_type: "new_connection_id"
     sequence_number: uint64
     retire_prior_to: uint64

     ; mainly used if e.g., for privacy reasons the full
     ; connection_id cannot be logged
     ? connection_id_length: uint8
     connection_id: ConnectionID
     ? stateless_reset_token: StatelessResetToken
     ? raw: RawInfo
   }

                 Figure 70: NewConnectionIDFrame definition

Marx, et al.               Expires 6 May 2027                  [Page 56]
Internet-Draft       QUIC event definitions for qlog       November 2026

8.13.17.  RetireConnectionIDFrame

   RetireConnectionIDFrame = {
     frame_type: "retire_connection_id"
     sequence_number: uint64
     ? raw: RawInfo
   }

               Figure 71: RetireConnectionIDFrame definition

8.13.18.  PathChallengeFrame

   PathChallengeFrame = {
     frame_type: "path_challenge"

     ; always 8 bytes
     ? data: hexstring
     ? raw: RawInfo
   }

                  Figure 72: PathChallengeFrame definition

8.13.19.  PathResponseFrame

   PathResponseFrame = {
     frame_type: "path_response"

     ; always 8 bytes
     ? data: hexstring
     ? raw: RawInfo
   }

                  Figure 73: PathResponseFrame definition

8.13.20.  ConnectionCloseFrame

   If an error code has no known string, error can be "unknown", and
   error_code then holds the numerical value without variable-length
   integer encoding.

   The trigger_frame_type field logs the Frame Type field, which only
   the transport variant of CONNECTION_CLOSE (type 0x1c) carries; see
   Section 19.19 of [QUIC-TRANSPORT].  A known frame type is logged as
   its frame type string, such as "stream".  An unknown frame type is
   logged as the numerical value without variable-length integer
   encoding.

Marx, et al.               Expires 6 May 2027                  [Page 57]
Internet-Draft       QUIC event definitions for qlog       November 2026

   The reason phrase in a CONNECTION_CLOSE frame is a byte sequence,
   which RFC 9000 recommends be UTF-8; see Section 19.19 of
   [QUIC-TRANSPORT].  The reason field holds the reason phrase as text,
   and reason_bytes holds the raw bytes, for example when the value is
   not UTF-8 or when an endpoint does not want to decode it.
   Implementations SHOULD log at least one form and MAY log both.

   ErrorSpace = "transport" /
                "application"

   ConnectionCloseFrame = {
       frame_type: "connection_close"
       ? error_space: ErrorSpace
       ? error: $TransportError / CryptoError /
                $ApplicationError

       ; if error === "unknown"
       ? error_code: uint64

       ? reason: text
       ? reason_bytes: hexstring

       ; when error_space === "transport"
       ? trigger_frame_type: uint64 /
                             text
       ? raw: RawInfo
   }

                 Figure 74: ConnectionCloseFrame definition

8.13.21.  HandshakeDoneFrame

   HandshakeDoneFrame = {
     frame_type: "handshake_done"
     ? raw: RawInfo
   }

                  Figure 75: HandshakeDoneFrame definition

8.13.22.  UnknownFrame

   The frame_type_bytes field holds the numerical value of the frame
   type without variable-length integer encoding.

Marx, et al.               Expires 6 May 2027                  [Page 58]
Internet-Draft       QUIC event definitions for qlog       November 2026

   UnknownFrame = {
       frame_type: "unknown"
       frame_type_bytes: uint64
       ? raw: RawInfo
   }

                     Figure 76: UnknownFrame definition

8.13.23.  DatagramFrame

   The QUIC DATAGRAM frame is defined in Section 4 of [QUIC-DATAGRAM].

   If the DATAGRAM frame contains a length field, it MUST be logged in
   the qlog raw.length field.  If it does not, the implementation MAY
   calculate the actual datagram byte length itself and log that in
   raw.length if necessary.

   DatagramFrame = {
       frame_type: "datagram"
       ? raw: RawInfo
   }

                    Figure 77: DatagramFrame definition

8.14.  TransportError

   The generic $TransportError is defined here as a CDDL "type socket"
   extension point.  It can be extended to support additional transport
   errors.

Marx, et al.               Expires 6 May 2027                  [Page 59]
Internet-Draft       QUIC event definitions for qlog       November 2026

   $TransportError /= "no_error" /
                    "internal_error" /
                    "connection_refused" /
                    "flow_control_error" /
                    "stream_limit_error" /
                    "stream_state_error" /
                    "final_size_error" /
                    "frame_encoding_error" /
                    "transport_parameter_error" /
                    "connection_id_limit_error" /
                    "protocol_violation" /
                    "invalid_token" /
                    "application_error" /
                    "crypto_buffer_exceeded" /
                    "key_update_error" /
                    "aead_limit_reached" /
                    "no_viable_path" /
                    "unknown"
                    ; there is no value to reflect CRYPTO_ERROR
                    ; use the CryptoError type instead

                    Figure 78: TransportError definition

8.15.  ApplicationError

   Application errors are defined by the application protocol that runs
   on top of QUIC, such as HTTP/3, so this document cannot list them.
   $ApplicationError is instead defined as a CDDL "type socket"
   extension point, with a single "unknown" value.

   $ApplicationError /= "unknown"

                   Figure 79: ApplicationError definition

   Event schemas for application protocols MUST add their error strings
   by extending the $ApplicationError socket; see Section 8.2 of
   [QLOG-MAIN].

8.16.  CryptoError

   RFC 9001 converts a TLS alert into a QUIC error code by adding the
   alert's AlertDescription value to 0x0100; see Section 4.8 of
   [QUIC-TLS].

Marx, et al.               Expires 6 May 2027                  [Page 60]
Internet-Draft       QUIC event definitions for qlog       November 2026

   A fixed list of strings does not fit this range well, so a
   CryptoError value is crypto_error_ followed by the resulting QUIC
   error code in lowercase hexadecimal, from crypto_error_0x100 to
   crypto_error_0x1ff.  For example, a handshake_failure alert, which is
   0x0128 in QUIC, is logged as crypto_error_0x128.

   ; all strings from "crypto_error_0x100" to "crypto_error_0x1ff"
   CryptoError = text .regexp "crypto_error_0x1[0-9a-f][0-9a-f]"

                     Figure 80: CryptoError definition

9.  Handling Packet Coalescing

   Multiple QUIC packets can be coalesced into a single UDP datagram,
   especially during the handshake; see Section 12.2 of
   [QUIC-TRANSPORT].  Neither QUIC nor UDP provides a way to tell which
   packets shared a datagram.

   To let tools match QUIC packet events to UDP datagram events, the
   optional datagram_payload_checksum field carries a 32-bit CRC32c of
   the UDP payload, calculated as described in Section 11.3 of
   [RFC9868].  The UDP datagram events carry one checksum per datagram,
   in their datagram_payload_checksums field.

10.  Security and Privacy Considerations

   The security and privacy considerations discussed in Section 14 of
   [QLOG-MAIN] apply to this document as well.

11.  IANA Considerations

   This document registers a new entry in the "qlog event schema URIs"
   registry, which was created in Section 15 of [QLOG-MAIN]:

   Event schema URI:  urn:ietf:params:qlog:events:quic

   Namespace:  quic

   Event Types:  server_listening, connection_started,
      connection_closed, connection_id_updated, spin_bit_updated,
      connection_state_updated, tuple_assigned, mtu_updated,
      version_information, alpn_information, parameters_set,
      parameters_restored, packet_sent, packet_received, packet_dropped,
      packet_buffered, packets_acked, udp_datagrams_sent,
      udp_datagrams_received, udp_datagram_dropped,
      stream_state_updated, frames_created, frames_parsed,
      stream_data_moved, datagram_data_moved, datagram_dropped,
      connection_data_blocked_updated, stream_data_blocked_updated,

Marx, et al.               Expires 6 May 2027                  [Page 61]
Internet-Draft       QUIC event definitions for qlog       November 2026

      datagram_data_blocked_updated, migration_state_updated,
      timer_updated, key_updated, key_discarded,
      recovery_parameters_set, recovery_metrics_updated,
      congestion_state_updated, packet_lost, marked_for_retransmit,
      ecn_state_updated

   Description:  Event definitions related to the QUIC transport
      protocol.

   Reference:  This document

12.  References

12.1.  Normative References

   [CDDL]     Birkholz, H., Vigano, C., and C. Bormann, "Concise Data
              Definition Language (CDDL): A Notational Convention to
              Express Concise Binary Object Representation (CBOR) and
              JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
              June 2019, <https://www.rfc-editor.org/rfc/rfc8610>.

   [GREASEBIT]
              Thomson, M., "Greasing the QUIC Bit", RFC 9287,
              DOI 10.17487/RFC9287, August 2022,
              <https://www.rfc-editor.org/rfc/rfc9287>.

   [QLOG-MAIN]
              Marx, R., Niccolini, L., Seemann, M., and L. Pardue,
              "qlog: Structured Logging for Network Protocols", Work in
              Progress, Internet-Draft, draft-ietf-quic-qlog-main-
              schema-14, 6 July 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-quic-
              qlog-main-schema-14>.

   [QUIC-DATAGRAM]
              Pauly, T., Kinnear, E., and D. Schinazi, "An Unreliable
              Datagram Extension to QUIC", RFC 9221,
              DOI 10.17487/RFC9221, March 2022,
              <https://www.rfc-editor.org/rfc/rfc9221>.

   [QUIC-RECOVERY]
              Iyengar, J., Ed. and I. Swett, Ed., "QUIC Loss Detection
              and Congestion Control", RFC 9002, DOI 10.17487/RFC9002,
              May 2021, <https://www.rfc-editor.org/rfc/rfc9002>.

   [QUIC-TLS] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure
              QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021,
              <https://www.rfc-editor.org/rfc/rfc9001>.

Marx, et al.               Expires 6 May 2027                  [Page 62]
Internet-Draft       QUIC event definitions for qlog       November 2026

   [QUIC-TRANSPORT]
              Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based
              Multiplexed and Secure Transport", RFC 9000,
              DOI 10.17487/RFC9000, May 2021,
              <https://www.rfc-editor.org/rfc/rfc9000>.

   [RESET-STREAM-AT]
              Seemann, M. and K. Oku, "QUIC Stream Resets with Partial
              Delivery", Work in Progress, Internet-Draft, draft-ietf-
              quic-reliable-stream-reset-11, 6 September 2026,
              <https://datatracker.ietf.org/doc/html/draft-ietf-quic-
              reliable-stream-reset-11>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC9221]  Pauly, T., Kinnear, E., and D. Schinazi, "An Unreliable
              Datagram Extension to QUIC", RFC 9221,
              DOI 10.17487/RFC9221, March 2022,
              <https://www.rfc-editor.org/rfc/rfc9221>.

   [RFC9868]  Touch, J. and C. Heard, Ed., "Transport Options for UDP",
              RFC 9868, DOI 10.17487/RFC9868, October 2025,
              <https://www.rfc-editor.org/rfc/rfc9868>.

12.2.  Informative References

   [RFC7301]  Friedl, S., Popov, A., Langley, A., and E. Stephan,
              "Transport Layer Security (TLS) Application-Layer Protocol
              Negotiation Extension", RFC 7301, DOI 10.17487/RFC7301,
              July 2014, <https://www.rfc-editor.org/rfc/rfc7301>.

Acknowledgements

   Much of the initial work by Robin Marx was done at the Hasselt and KU
   Leuven Universities.

   Thanks to Jana Iyengar, Brian Trammell, Dmitri Tikhonov, Stephen
   Petrides, Jari Arkko, Marcus Ihlar, Victor Vasiliev, Mirja
   Kuehlewind, Jeremy Laine, Kazu Yamamoto, Christian Huitema, Hugo
   Landau, Will Hawkins, Mathis Engelbart, Kazuho Oku, and Jonathan
   Lennox for their feedback and suggestions.

Marx, et al.               Expires 6 May 2027                  [Page 63]
Internet-Draft       QUIC event definitions for qlog       November 2026

Change Log

   This section is to be removed before publishing as an RFC.

Since draft-ietf-qlog-quic-events-13:

   *  Added datagram_dropped (#550)

   *  Wide range of editorial and consistency changes

Since draft-ietf-qlog-quic-events-12:

   *  Split frames_processed into 3 events (#513)

   *  Wide range of editorial changes

Since draft-ietf-qlog-quic-events-11:

   *  Updated several fields to be uint64 per QUIC spec

   *  Renamed error and error_code fields and logic (#473)

   *  Clarified parameters_set usage (#493)

   *  Replaced all length fields with raw.length (#495)

   *  Change loss_timer_updated to timer_updated (#496)

   *  Renamed path_assigned to tuple_assigned (#491)

   *  Reworked stream_state_updated (#497)

   *  Renamed owner to initiator (#498)

   *  Split up flags in PacketHeader (#478)

Since draft-ietf-qlog-quic-events-09:

   *  Several editorial changes

   *  Reworked QUICConnectionStarted to use PathEndpointInfo (#453)

   *  Consistent use of RawInfo and _bytes fields to log raw data (#450)

Since draft-ietf-qlog-quic-events-08:

   *  Removed individual categories and put every event in the single
      quic event schema namespace.  Major change (#439)

Marx, et al.               Expires 6 May 2027                  [Page 64]
Internet-Draft       QUIC event definitions for qlog       November 2026

   *  Renamed recovery:metrics_updated to quic:recovery_metrics_updated
      and recovery:parameters_set to quic:recovery_parameters_set (#439)

   *  Added unknown_parameters field to parameters_set (#438)

   *  Added extra parameters to parameters_restored (#441)

Since draft-ietf-qlog-quic-events-07:

   *  TODO (we forgot...)

Since draft-ietf-qlog-quic-events-06:

   *  Added PathAssigned and MigrationStateUpdated events (#336)

   *  Added extension points to parameters_set and parameters_restored
      (#400)

   *  Removed error_code_value from connection_closed (#386, #392)

   *  Renamed generation to key_phase for key_updated and key_discarded
      (#390)

   *  Removed retry_token from packet_sent and packet_received (#389)

   *  Updated ALPN handling (#385)

   *  Added key_unavailable trigger to packet_dropped (#381)

   *  Updated several uint32 to uint64

   *  ProtocolEventBody is now called ProtocolEventData (#352)

   *  Editorial changes (#402, #404, #394, #393)

Since draft-ietf-qlog-quic-events-05:

   *  SecurityKeyUpdated: the new key is no longer mandatory to log
      (#294)

   *  Added ECN related events and metadata (#263)

Since draft-ietf-qlog-quic-events-04:

   *  Updated guidance on logging events across connections (#279)

   *  Renamed 'transport' category to 'quic' (#302)

Marx, et al.               Expires 6 May 2027                  [Page 65]
Internet-Draft       QUIC event definitions for qlog       November 2026

   *  Added support for multiple packet numbers in
      'quic:frames_processed' (#307)

   *  Added definitions for RFC9287 (QUIC GREASE Bit extension) (#311)

   *  Added definitions for RFC9221 (QUIC Datagram Frame extension)
      (#310)

   *  (Temporarily) removed definitions for connection migration events
      (#317)

   *  Editorial and formatting changes (#298, #299, #304, #306, #327)

Since draft-ietf-qlog-quic-events-03:

   *  Ensured consistent use of RawInfo to indicate raw wire bytes
      (#243)

   *  Renamed UnknownFrame:raw_frame_type to :frame_type_value (#54)

   *  Renamed ConnectionCloseFrame:raw_error_code to :error_code_value
      (#54)

   *  Changed triggers for packet_dropped (#278)

   *  Added entries to TransportError enum (#285)

   *  Changed minimum_congestion_window to uint64 (#288)

Since draft-ietf-qlog-quic-events-02:

   *  Renamed key_retired to key_discarded (#185)

   *  Added fields and events for DPLPMTUD (#135)

   *  Made packet_number optional in PacketHeader (#244)

   *  Removed connection_retried event placeholder (#255)

   *  Changed QuicFrame to a CDDL plug type (#257)

   *  Moved data definitions out of the appendix into separate sections

   *  Added overview Table of Contents

Marx, et al.               Expires 6 May 2027                  [Page 66]
Internet-Draft       QUIC event definitions for qlog       November 2026

Since draft-ietf-qlog-quic-events-01:

   *  Added Stateless Reset Token type (#122)

Since draft-ietf-qlog-quic-events-00:

   *  Change the data definition language from TypeScript to CDDL (#143)

Since draft-marx-qlog-event-definitions-quic-h3-02:

   *  These changes were done in preparation of the adoption of the
      drafts by the QUIC working group (#137)

   *  Split QUIC and HTTP/3 events into two separate documents

   *  Moved RawInfo, Importance, Generic events and Simulation events to
      the main schema document.

   *  Changed to/from value options of the data_moved event

Since draft-marx-qlog-event-definitions-quic-h3-01:

   Major changes:

   *  Moved data_moved from http to transport.  Also made the "from" and
      "to" fields flexible strings instead of an enum (#111,#65)

   *  Moved packet_type fields to PacketHeader.  Moved packet_size field
      out of PacketHeader to RawInfo:length (#40)

   *  Made events that need to log packet_type and packet_number use a
      header field instead of logging these fields individually

   *  Added support for logging retry, stateless reset and initial
      tokens (#94,#86,#117)

   *  Moved separate general event categories into a single category
      "generic" (#47)

   *  Added "transport:connection_closed" event (#43,#85,#78,#49)

   *  Added version_information and alpn_information events
      (#85,#75,#28)

   *  Added parameters_restored events to help clarify 0-RTT behaviour
      (#88)

   Smaller changes:

Marx, et al.               Expires 6 May 2027                  [Page 67]
Internet-Draft       QUIC event definitions for qlog       November 2026

   *  Merged loss_timer events into one loss_timer_updated event

   *  Field data types are now strongly defined (#10,#39,#36,#115)

   *  Renamed qpack instruction_received and instruction_sent to
      instruction_created and instruction_parsed (#114)

   *  Updated qpack:dynamic_table_updated.update_type.  It now has the
      value "inserted" instead of "added" (#113)

   *  Updated qpack:dynamic_table_updated.  It now has an "owner" field
      to differentiate encoder vs decoder state (#112)

   *  Removed push_allowed from http:parameters_set (#110)

   *  Removed explicit trigger field indications from events, since this
      was moved to be a generic property of the "data" field (#80)

   *  Updated transport:connection_id_updated to be more in line with
      other similar events.  Also dropped importance from Core to Base
      (#45)

   *  Added length property to PaddingFrame (#34)

   *  Added packet_number field to transport:frames_processed (#74)

   *  Added a way to generically log packet header flags (first 8 bits)
      to PacketHeader

   *  Added additional guidance on which events to log in which
      situations (#53)

   *  Added "simulation:scenario" event to help indicate simulation
      details

   *  Added "packets_acked" event (#107)

   *  Added "datagram_ids" to the datagram_X and packet_X events to
      allow tracking of coalesced QUIC packets (#91)

   *  Extended connection_state_updated with more fine-grained states
      (#49)

Since draft-marx-qlog-event-definitions-quic-h3-00:

   *  Event and category names are now all lowercase

   *  Added many new events and their definitions

Marx, et al.               Expires 6 May 2027                  [Page 68]
Internet-Draft       QUIC event definitions for qlog       November 2026

   *  "type" fields have been made more specific (especially important
      for PacketType fields, which are now called packet_type instead of
      type)

   *  Events are given an importance indicator (issue #22)

   *  Event names are more consistent and use past tense (issue #21)

   *  Triggers have been redefined as properties of the "data" field and
      updated for most events (issue #23)

Authors' Addresses

   Robin Marx (editor)
   Akamai
   Email: rmarx@akamai.com

   Luca Niccolini (editor)
   Meta
   Email: lniccolini@meta.com

   Marten Seemann (editor)
   Email: martenseemann@gmail.com

   Lucas Pardue (editor)
   Apple
   Email: lucas@lucaspardue.com

Marx, et al.               Expires 6 May 2027                  [Page 69]