Heuristics and Algorithms to Prioritize Protocol deploYment M. Kühlewind Internet-Draft Ericsson Intended status: Informational 6 July 2026 Expires: 7 January 2027 Happy Eyeballs v3 (HEv3) Event Logging with qlog draft-kuehlewind-happy-qlog-00 Abstract This document specifies a qlog extension for Happy Eyeballs v3 (HEv3), enabling logging of dual-stack and multi-protocol connection racing behavior. It defines a dedicated event schema, event names, and data structures that capture DNS resolution timing, SVCB/HTTPS service discovery, candidate sorting and grouping, connection attempt scheduling and racing, NAT64 prefix discovery, success/failure outcomes, and summary metrics. About This Document This note is to be removed before publishing as an RFC. The latest revision of this draft can be found at https://mirjak.github.io/draft-happy-glog/draft-kuehlewind-happy- glog.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-kuehlewind-happy-qlog/. Discussion of this document takes place on the Heuristics and Algorithms to Prioritize Protocol deploYment Working Group mailing list (mailto:happy@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/happy/. Subscribe at https://www.ietf.org/mailman/listinfo/happy/. Source for this draft and an issue tracker can be found at https://github.com/mirjak/draft-happy-glog. 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/. Kühlewind Expires 7 January 2027 [Page 1] Internet-Draft HEv3 qlog July 2026 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 7 January 2027. 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 . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 3 3. Event Schema Definition . . . . . . . . . . . . . . . . . . . 3 3.1. Draft Event Schema Identification . . . . . . . . . . . . 3 4. HE Data Types . . . . . . . . . . . . . . . . . . . . . . . . 4 4.1. Attempt Target . . . . . . . . . . . . . . . . . . . . . 4 4.2. Policy . . . . . . . . . . . . . . . . . . . . . . . . . 5 4.3. DNS Result . . . . . . . . . . . . . . . . . . . . . . . 6 5. Event Definitions . . . . . . . . . . . . . . . . . . . . . . 7 5.1. Event: config_set . . . . . . . . . . . . . . . . . . . . 7 5.2. Event: dns_query_started . . . . . . . . . . . . . . . . 8 5.3. Event: dns_query_finished . . . . . . . . . . . . . . . . 9 5.4. Event: nat64_prefix_discovered . . . . . . . . . . . . . 9 5.5. Event: candidate_discovered . . . . . . . . . . . . . . . 10 5.6. Event: candidates_sorted . . . . . . . . . . . . . . . . 10 5.7. Event: candidate_removed . . . . . . . . . . . . . . . . 11 5.8. Event: candidates_resorted . . . . . . . . . . . . . . . 12 5.9. Event: attempt_scheduled . . . . . . . . . . . . . . . . 13 5.10. Event: attempt_started . . . . . . . . . . . . . . . . . 13 5.11. Event: attempt_pended . . . . . . . . . . . . . . . . . . 14 5.12. Event: attempt_resumed . . . . . . . . . . . . . . . . . 14 5.13. Event: attempt_outcome . . . . . . . . . . . . . . . . . 15 5.14. Event: next_attempt_timer_set . . . . . . . . . . . . . . 15 5.15. Event: next_attempt_timer_fired . . . . . . . . . . . . . 16 5.16. Event: next_attempt_timer_canceled . . . . . . . . . . . 16 Kühlewind Expires 7 January 2027 [Page 2] Internet-Draft HEv3 qlog July 2026 5.17. Event: connection_selected . . . . . . . . . . . . . . . 16 5.18. Event: connection_aborted . . . . . . . . . . . . . . . . 17 5.19. Event: metrics . . . . . . . . . . . . . . . . . . . . . 17 5.20. Conformance Requirements . . . . . . . . . . . . . . . . 18 6. Correlation with transport protocols . . . . . . . . . . . . 18 7. Security Considerations . . . . . . . . . . . . . . . . . . . 19 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19 9. Normative References . . . . . . . . . . . . . . . . . . . . 19 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 20 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 20 1. Introduction Happy Eyeballs helps applications reduce connection latency on dual- stack networks. Happy Eyeballs v3 (HEv3) extends racing from IPv4/ IPv6 to include TCP+TLS and QUIC/HTTP3, and incorporates SVCB/HTTPS service discovery. Detailed logging of HEv3 behavior enables operators and developers to diagnose connection establishment failures and identify network issues that would otherwise be hidden by the racing algorithm. This document defines a qlog event schema that provides logging and visibility into HEv3 decision-making and timing. 2. Conventions and Definitions 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. 3. Event Schema Definition This document proposes a qlog schema for HEv3 using the newly defined event schema urn:ietf:params:qlog:events:hev3. 3.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:hev3. Until such an RFC exists, implementations MUST NOT identify themselves using this URI. Kühlewind Expires 7 January 2027 [Page 3] Internet-Draft HEv3 qlog July 2026 Implementations of draft versions of the event schema MUST append the string "-" and the corresponding draft number to the URI. For example, draft 01 of this document is identified using the URI urn:ietf:params:qlog:events:hev3-01. The namespace identifier itself is not affected by this requirement. 4. HE Data Types 4.1. Attempt Target HEAttemptTarget = { address: text port: uint16 family: "ipv4" / "ipv6" interface: text ? path_id: text ? alpn: [+ text] ? service_name: text ? service_priority: uint32 ? ech_offered: bool ? * $he-attempttarget-extension } The following fields are defined: * address: The IP address of the target endpoint. * port: The destination port number. * family: The address family, either "ipv4" or "ipv6". * interface: The local network interface used for this attempt. * path_id: An implementation-defined identifier for the network path. * alpn: The negotiated ALPN set for this target derived from SVCB records. * service_name: The SVCB ServiceMode TargetName this target originates from. * service_priority: The SVCB SvcPriority value for this target's service. * ech_offered: Whether ECH will be attempted on this connection. Kühlewind Expires 7 January 2027 [Page 4] Internet-Draft HEv3 qlog July 2026 4.2. Policy HEPolicy = { resolution_delay_ms: uint32 ? preferred_address_family_count: uint32 ? connection_attempt_delay_ms: uint32 ? min_connection_attempt_delay_ms: uint32 ? max_connection_attempt_delay_ms: uint32 ? max_parallel_attempts: uint32 ? last_resort_local_synthesis_delay_ms: uint32 ? preferred_family: "ipv4" / "ipv6" / "auto" ? success_definition: "tcp_connected" / "tls_handshake_complete" / "quic_1rtt_ready" ? use_historical_rtt: bool ? * $he-policy-extension } The fields correspond to the configurable values defined in Section 9 of HEv3: * resolution_delay_ms: Time to wait for preferred-family and SVCB/ HTTPS records after receiving initial answers (recommended 50ms). * preferred_address_family_count: Number of addresses of the preferred family attempted before trying the other family (recommended 1). * connection_attempt_delay_ms: Delay between connection attempts in the absence of RTT data (recommended 250ms). * min_connection_attempt_delay_ms: Floor for the connection attempt delay (recommended 100ms, must not be less than 10ms). * max_connection_attempt_delay_ms: Ceiling for the connection attempt delay (recommended 2s). * max_parallel_attempts: Maximum number of connection attempts allowed in parallel. * last_resort_local_synthesis_delay_ms: Time to wait before querying A records for local NAT64 synthesis when AAAA attempts are failing on IPv6-only networks (recommended 2s). * preferred_family: The address family assumed to have better connectivity. Kühlewind Expires 7 January 2027 [Page 5] Internet-Draft HEv3 qlog July 2026 * success_definition: What constitutes a successful connection establishment. * use_historical_rtt: Whether historical RTT data is used to order destinations and adjust attempt delays. If omitted, success_definition defaults to: * tcp_connected for plain TCP stacks * tls_handshake_complete for TCP+TLS stacks * quic_1rtt_ready for QUIC stacks 4.3. DNS Result DNS results can represent either address records (A/AAAA) or service records (SVCB/HTTPS). HEDNSResult = HEDNSAddressResult / HEDNSServiceResult HEDNSAddressResult = { type: "address" address: text family: "ipv4" / "ipv6" ttl_s: uint32 ? * $he-dnsaddressresult-extension } HEDNSServiceResult = { type: "service" mode: "alias" / "servicemode" target_name: text priority: uint32 ? alpn: [+ text] ? no_default_alpn: bool ? ech_config: text ? ipv4hint: [+ text] ? ipv6hint: [+ text] ? ttl_s: uint32 ? * $he-dnsserviceresult-extension } The mode field distinguishes AliasMode records (which require a follow-up query) from ServiceMode records that carry usable service parameters. Kühlewind Expires 7 January 2027 [Page 6] Internet-Draft HEv3 qlog July 2026 The following fields are defined for HEDNSAddressResult: * type: Always "address" for this variant. * address: The resolved IP address. * family: The address family, either "ipv4" or "ipv6". * ttl_s: The DNS TTL in seconds. The following fields are defined for HEDNSServiceResult: * type: Always "service" for this variant. * mode: Either "alias" (AliasMode, requires follow-up query) or "servicemode" (carries usable parameters). * target_name: The SVCB TargetName (use "." for the owner name). * priority: The SVCB SvcPriority value. * alpn: The list of supported application protocols from the alpn key. * no_default_alpn: Whether the no-default-alpn key is present. * ech_config: Base64-encoded ECHConfigList from the ech key. * ipv4hint: IPv4 address hints from the ipv4hint key. * ipv6hint: IPv6 address hints from the ipv6hint key. * ttl_s: The DNS TTL in seconds. 5. Event Definitions Each event uses: name: "hev3:" with the type identifier defined below in the section headings. All events include a he_session_id field that uniquely identifies the Happy Eyeballs session. This allows correlation of all events belonging to a single connection establishment attempt. 5.1. Event: config_set Logged when the HE policy is configured or updated during a session. Kühlewind Expires 7 January 2027 [Page 7] Internet-Draft HEv3 qlog July 2026 HEConfigSet = { he_session_id: text policy: HEPolicy reason: "startup" / "app_config" / "network_change" * $$he-configset-extension } The policy field contains the policy configuration. The reason field indicates what triggered the configuration: * "startup": Default policy applied at application start. * "app_config": Policy provided by the application. * "network_change": Policy updated in response to a network transition. The first occurrence of this event in a session represents the initial configuration; typical reasons are "startup" or "app_config". Subsequent occurrences represent policy updates. 5.2. Event: dns_query_started Logged when a DNS query is initiated as part of hostname resolution. HEDNSQueryStarted = { he_session_id: text dns_id: text hostname: text qtypes: [+ "A" / "AAAA" / "SVCB" / "HTTPS"] bootstrap_hint: text ? * $$he-dnsquerystarted-extension } The dns_id uniquely identifies this query within the session and is used to correlate with the corresponding dns_query_finished event. The hostname is the name being resolved. The qtypes array lists the DNS record types being queried. The bootstrap_hint field optionally contains an address hint used to reach the DNS resolver itself. Kühlewind Expires 7 January 2027 [Page 8] Internet-Draft HEv3 qlog July 2026 5.3. Event: dns_query_finished Logged when a DNS query completes with results, an error, or a negative response. HEDNSQueryFinished = { he_session_id: text dns_id: text hostname: text results: [* HEDNSResult] answer_type: "positive" / "negative" / "error" ? error_code: text ? error_message: text ? duration_ms: uint32 dnssec_validated: bool ? is_alias_follow: bool ? * $$he-dnsqueryfinished-extension } The answer_type field distinguishes positive (non-empty) from negative (empty, no error) and error responses, which is significant for HEv3's async resolution logic (Section 4.2). The dnssec_validated field indicates whether the response was cryptographically validated, relevant for determining whether SVCB- dependent handshakes must be pended (Section 6.3). The is_alias_follow field is set to true when this query was triggered by an AliasMode SVCB/HTTPS record requiring a follow-up resolution. 5.4. Event: nat64_prefix_discovered Logged when the client discovers a NAT64 prefix for use on an IPv6-only network (Section 8 of HEv3). HENat64PrefixDiscovered = { he_session_id: text prefix: text prefix_length: uint32 source: "pref64_ra" / "rfc7050_discovery" / "dns64_inferred" * $$he-nat64prefixdiscovered-extension } The source field indicates how the prefix was obtained: * "pref64_ra": Learned from a Router Advertisement (RFC 8781). Kühlewind Expires 7 January 2027 [Page 9] Internet-Draft HEv3 qlog July 2026 * "rfc7050_discovery": Discovered via the well-known name lookup (RFC 7050). * "dns64_inferred": Inferred from DNS64 behavior on the network. 5.5. Event: candidate_discovered HECandidateDiscovered = { he_session_id: text source: "dns" / "svcb_hint" / "nat64_synthesis" target: HEAttemptTarget group_id: text ? supersedes: text ? * $$he-candidatediscovered-extension } The source value "dns" indicates the address came from A or AAAA records. The "svcb_hint" value indicates the address came from ipv4hint or ipv6hint parameters in a SVCB/HTTPS record. The "nat64_synthesis" value indicates a locally synthesized IPv6 address for NAT64 traversal. The group_id field identifies which protocol/priority group this candidate belongs to (per Section 5.1 and 5.2 of HEv3). The supersedes field contains the address of an SVCB hint that this candidate replaces once authoritative A/AAAA records arrive (per Section 7 of HEv3). 5.6. Event: candidates_sorted Logged once sufficient DNS answers have been received (per Section 4.2 of HEv3) and the implementation has applied the three- level sorting algorithm (Section 5). This event captures the full grouped and ordered candidate list before racing begins. Kühlewind Expires 7 January 2027 [Page 10] Internet-Draft HEv3 qlog July 2026 HECandidatesSorted = { he_session_id: text groups: [+ HECandidateGroup] * $$he-candidatessorted-extension } HECandidateGroup = { group_id: text alpn: [+ text] ? ech_available: bool ? service_priority: uint32 ? candidates: [+ HEAttemptTarget] } The groups array is ordered by priority. Within each group: * alpn captures the application protocol set that defines this group (Section 5.1 of HEv3). * ech_available indicates whether ECH configuration is available for endpoints in this group (Section 5.1 of HEv3). * service_priority reflects the SVCB SvcPriority value for this group (Section 5.2 of HEv3). Groups with equal priority are shuffled randomly. * candidates is ordered per Section 5.3 of HEv3: RFC 6724 destination address selection, historical RTT preferences, and address family interleaving applied. For simple cases without SVCB records, a single group with all candidates is sufficient. 5.7. Event: candidate_removed Logged when a candidate address is removed from the list during connection setup (per Section 7 of HEv3). HECandidateRemoved = { he_session_id: text target: HEAttemptTarget reason: "ttl_expired" / "svcb_hint_replaced" / "dns_negative" / "alpn_mismatch" had_active_attempt: bool ? * $$he-candidateremoved-extension } Kühlewind Expires 7 January 2027 [Page 11] Internet-Draft HEv3 qlog July 2026 The reason field indicates why the candidate was removed: * "ttl_expired": The DNS TTL for this address expired before an attempt was started. * "svcb_hint_replaced": Authoritative A/AAAA records arrived and this hint address was absent from them (Section 7.3 of SVCB). * "dns_negative": A previously positive record was replaced by a negative response (e.g., via DNS push notification). * "alpn_mismatch": The SVCB ALPN set does not contain protocols the client supports (Section 6.2 of HEv3). The had_active_attempt field indicates whether an in-progress attempt exists for this target; per HEv3 Section 7, such attempts are not canceled. 5.8. Event: candidates_resorted Logged when the candidate list is re-sorted due to new addresses arriving mid-race (per Section 7 of HEv3). Re-sorting ensures that address family interleaving and priority rules are maintained correctly regardless of when addresses arrive. HECandidatesResorted = { he_session_id: text reason: "new_addresses" / "new_svcb" / "dns_push" new_order: [+ HEAttemptTarget] * $$he-candidatesresorted-extension } The reason field captures why re-sorting occurred: * "new_addresses": New A/AAAA records arrived (e.g., delayed IPv4 after an IPv6-only start). * "new_svcb": New SVCB/HTTPS ServiceMode records changed grouping or priorities. * "dns_push": A DNS push notification added addresses. The new_order array contains the full re-sorted candidate list as HEAttemptTarget elements. Position in the array implies the new rank. Only pending candidates (those not yet attempted or currently in progress) are included. Kühlewind Expires 7 January 2027 [Page 12] Internet-Draft HEv3 qlog July 2026 5.9. Event: attempt_scheduled Logged when a connection attempt is scheduled to start after a delay. HEAttemptScheduled = { he_session_id: text attempt_id: text target: HEAttemptTarget scheduled_after_ms: uint32 reason: "policy_timer" / "dns_completed" / "resolution_delay_expired" / "last_resort_synthesis" * $$he-attemptscheduled-extension } The attempt_id uniquely identifies this attempt within the session. The scheduled_after_ms field indicates the delay before the attempt will start. The reason field indicates what triggered scheduling: * "policy_timer": The Next Connection Attempt Timer fired. * "dns_completed": DNS resolution completed, enabling the first attempt. * "resolution_delay_expired": The Resolution Delay timer expired (Section 4.2 of HEv3). * "last_resort_synthesis": The Last Resort Local Synthesis Delay expired, triggering a fallback A query and NAT64 synthesis (Section 8.4 of HEv3). 5.10. Event: attempt_started Logged when a connection attempt begins (i.e., the first packet is sent). HEAttemptStarted = { he_session_id: text attempt_id: text target: HEAttemptTarget transport: "tcp" / "quic" ref_event_id: text ? * $$he-attemptstarted-extension } Kühlewind Expires 7 January 2027 [Page 13] Internet-Draft HEv3 qlog July 2026 The transport field indicates the transport protocol used for this attempt. The ref_event_id field may reference a related event in another qlog event schema; QUIC implementations should set it to the relevant connectivity:connection_started event. 5.11. Event: attempt_pended Logged when a connection attempt's TLS handshake must be paused until SVCB/HTTPS responses are received, as required by Section 6.3 of HEv3 (e.g., when DNS is cryptographically protected and ECH configuration is expected from SVCB records). HEAttemptPended = { he_session_id: text attempt_id: text reason: "awaiting_svcb" / "awaiting_ech_config" / "dnssec_validation" waiting_for: text ? * $$he-attemptpended-extension } The waiting_for field may reference the dns_id of the outstanding SVCB/HTTPS query. 5.12. Event: attempt_resumed Logged when a previously pended attempt resumes its handshake. HEAttemptResumed = { he_session_id: text attempt_id: text reason: "svcb_received" / "timeout" / "policy_override" * $$he-attemptresumed-extension } The reason field indicates what unblocked the attempt: * "svcb_received": The awaited SVCB/HTTPS response arrived. * "timeout": A timeout expired while waiting; proceeding without the expected information. * "policy_override": The implementation decided to proceed despite not receiving the expected response (e.g., opportunistic ECH). Kühlewind Expires 7 January 2027 [Page 14] Internet-Draft HEv3 qlog July 2026 5.13. Event: attempt_outcome Logged when a connection attempt reaches a terminal state. HEAttemptOutcome = { he_session_id: text attempt_id: text result: "success" / "failure" / "timeout" / "canceled" error_code: text ? connect_duration_ms: uint32 ? * $$he-attemptoutcome-extension } The result field indicates the outcome: * "success": The connection was established per the success_definition in the policy. * "failure": The attempt failed (e.g., connection refused, TLS error). * "timeout": The attempt timed out without completing. * "canceled": The attempt was canceled because another attempt succeeded. The error_code field contains a protocol-specific error code on failure. The connect_duration_ms field records the time from attempt start to outcome. 5.14. Event: next_attempt_timer_set Logged when the Next Connection Attempt Timer is set or adjusted. This timer controls when the next connection attempt begins (Section 6 of HEv3). HENextAttemptTimerSet = { he_session_id: text delay_ms: uint32 reason: "initial" / "rtt_based" / "handshake_progress" ? * $$he-nextattemptimerset-extension } The reason field captures why the delay was chosen: * "initial": Using the configured Connection Attempt Delay. Kühlewind Expires 7 January 2027 [Page 15] Internet-Draft HEv3 qlog July 2026 * "rtt_based": Delay derived from historical RTT data or estimated retransmission timeout. * "handshake_progress": Timer extended after partial handshake completion (e.g., TCP connected, waiting for TLS — per Section 6.1 of HEv3). 5.15. Event: next_attempt_timer_fired Logged when the timer fires and the next connection attempt is triggered. HENextAttemptTimerFired = { he_session_id: text * $$he-nextattemptimerfired-extension } 5.16. Event: next_attempt_timer_canceled Logged when the timer is canceled before firing. HENextAttemptTimerCanceled = { he_session_id: text reason: "success" / "abort" / "list_exhausted" * $$he-nextattemptimercanceled-extension } The reason field indicates why the timer was canceled: * "success": A connection attempt succeeded. * "abort": The HE session was aborted. * "list_exhausted": All candidates have been attempted. 5.17. Event: connection_selected Logged when a successful connection attempt is chosen as the winning connection for this HE session. Kühlewind Expires 7 January 2027 [Page 16] Internet-Draft HEv3 qlog July 2026 HEConnectionSelected = { he_session_id: text attempt_id: text ref_event_id: text ? * $$he-connectionselected-extension } The attempt_id identifies which attempt won. The ref_event_id field may reference the corresponding transport-level event (e.g., a QUIC connectivity:connection_started or TLS handshake_complete). 5.18. Event: connection_aborted Logged when the entire HE session fails without establishing any connection. HEConnectionAborted = { he_session_id: text reason: text * $$he-connectionaborted-extension } The reason field contains a human-readable or implementation-defined description of why the session was aborted (e.g., "all attempts failed", "no addresses resolved", "user canceled"). 5.19. Event: metrics Logged at the end of an HE session to provide summary statistics. HEMetrics = { he_session_id: text outcome: "success" / "aborted" total_duration_ms: uint32 tt_first_success_ms: uint32 ? first_success_family: "ipv4" / "ipv6" ? first_success_transport: "tcp" / "quic" ? attempts_total: uint32 attempts_success: uint32 attempts_failure: uint32 * $$he-metrics-extension } The fields capture end-to-end session statistics: Kühlewind Expires 7 January 2027 [Page 17] Internet-Draft HEv3 qlog July 2026 * outcome: Whether the session established a connection ("success") or failed entirely ("aborted"). * total_duration_ms: Total time from session start to final outcome (connection selected or session aborted). * tt_first_success_ms: Time from session start to the first successful connection attempt (i.e., time-to-first-byte readiness). * first_success_family: The address family of the first successful attempt. * first_success_transport: The transport protocol of the first successful attempt. * attempts_total: Total number of connection attempts initiated. * attempts_success: Number of attempts that completed successfully. * attempts_failure: Number of attempts that failed, timed out, or were canceled. When outcome is "aborted", the fields tt_first_success_ms, first_success_family, and first_success_transport are not present. 5.20. Conformance Requirements * Every attempt_started MUST have exactly one attempt_outcome. * connection_selected MUST reference an attempt whose result is "success". * Exactly one metrics event SHOULD appear per HE session. 6. Correlation with transport protocols TCP/TLS implementation can correlate HE events with: * tls:handshake_started * tls:handshake_complete * TCP state transitions (if available in logs) TBD Kühlewind Expires 7 January 2027 [Page 18] Internet-Draft HEv3 qlog July 2026 7. Security Considerations TBD 8. IANA Considerations This document registers a new entry in the "qlog event schema URIs" registry (created in {Section 15 of QLOG-MAIN}): Event schema URI: urn:ietf:params:qlog:events:hev3 Namespace: hev3 Event Types: config_set, dns_query_started, dns_query_finished, nat64_prefix_discovered, candidate_discovered, candidates_sorted, candidate_removed, candidates_resorted, attempt_scheduled, attempt_started, attempt_pended, attempt_resumed, attempt_outcome, next_attempt_timer_set, next_attempt_timer_fired, next_attempt_timer_canceled, connection_selected, connection_aborted, metrics Description: Event definitions for logging HEv3 events Reference: This document 9. Normative References [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, . [HEV3] Pauly, T., Schinazi, D., Jaju, N., and K. Ishibashi, "Happy Eyeballs Version 3: Better Connectivity Using Concurrency", Work in Progress, Internet-Draft, draft- ietf-happy-happyeyeballs-v3-04, 1 July 2026, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . Kühlewind Expires 7 January 2027 [Page 19] Internet-Draft HEv3 qlog July 2026 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . Acknowledgments Author's Address Mirja Kühlewind Ericsson Email: mirja.kuehlewind@ericsson.com Kühlewind Expires 7 January 2027 [Page 20]