quinn_proto/connection/
qlog.rs1#![allow(unused_variables)]
3
4#[cfg(feature = "qlog")]
5use std::sync::{Arc, Mutex};
6
7#[cfg(feature = "qlog")]
8use qlog::{
9 events::{
10 Event, EventData,
11 quic::{
12 PacketHeader, PacketLost, PacketLostTrigger, PacketReceived, PacketSent, PacketType,
13 },
14 },
15 streamer::QlogStreamer,
16};
17#[cfg(feature = "qlog")]
18use tracing::warn;
19
20use crate::{
21 ConnectionId, Instant,
22 connection::{PathData, SentPacket},
23 packet::SpaceId,
24};
25
26#[cfg(feature = "qlog")]
28#[derive(Clone)]
29pub struct QlogStream(pub(crate) Arc<Mutex<QlogStreamer>>);
30
31#[cfg(feature = "qlog")]
32impl QlogStream {
33 fn emit_event(&self, orig_rem_cid: ConnectionId, event: EventData, now: Instant) {
34 let mut event = Event::with_time(0.0, event);
36 event.group_id = Some(orig_rem_cid.to_string());
37
38 let mut qlog_streamer = self.0.lock().unwrap();
39 if let Err(e) = qlog_streamer.add_event_with_instant(event, now) {
40 warn!("could not emit qlog event: {e}");
41 }
42 }
43}
44
45#[derive(Clone, Default)]
47pub(crate) struct QlogSink {
48 #[cfg(feature = "qlog")]
49 stream: Option<QlogStream>,
50}
51
52impl QlogSink {
53 pub(crate) fn is_enabled(&self) -> bool {
54 #[cfg(feature = "qlog")]
55 {
56 self.stream.is_some()
57 }
58 #[cfg(not(feature = "qlog"))]
59 {
60 false
61 }
62 }
63
64 pub(super) fn emit_recovery_metrics(
65 &self,
66 pto_count: u32,
67 path: &mut PathData,
68 now: Instant,
69 orig_rem_cid: ConnectionId,
70 ) {
71 #[cfg(feature = "qlog")]
72 {
73 let Some(stream) = self.stream.as_ref() else {
74 return;
75 };
76
77 let Some(metrics) = path.qlog_recovery_metrics(pto_count) else {
78 return;
79 };
80
81 stream.emit_event(orig_rem_cid, EventData::MetricsUpdated(metrics), now);
82 }
83 }
84
85 pub(super) fn emit_packet_lost(
86 &self,
87 pn: u64,
88 info: &SentPacket,
89 lost_send_time: Instant,
90 space: SpaceId,
91 now: Instant,
92 orig_rem_cid: ConnectionId,
93 ) {
94 #[cfg(feature = "qlog")]
95 {
96 let Some(stream) = self.stream.as_ref() else {
97 return;
98 };
99
100 let event = PacketLost {
101 header: Some(PacketHeader {
102 packet_number: Some(pn),
103 packet_type: packet_type(space, false),
104 length: Some(info.size),
105 ..Default::default()
106 }),
107 frames: None,
108 trigger: Some(match info.time_sent <= lost_send_time {
109 true => PacketLostTrigger::TimeThreshold,
110 false => PacketLostTrigger::ReorderingThreshold,
111 }),
112 };
113
114 stream.emit_event(orig_rem_cid, EventData::PacketLost(event), now);
115 }
116 }
117
118 pub(super) fn emit_packet_sent(
119 &self,
120 pn: u64,
121 len: usize,
122 space: SpaceId,
123 is_0rtt: bool,
124 now: Instant,
125 orig_rem_cid: ConnectionId,
126 ) {
127 #[cfg(feature = "qlog")]
128 {
129 let Some(stream) = self.stream.as_ref() else {
130 return;
131 };
132
133 let event = PacketSent {
134 header: PacketHeader {
135 packet_number: Some(pn),
136 packet_type: packet_type(space, is_0rtt),
137 length: Some(len as u16),
138 ..Default::default()
139 },
140 ..Default::default()
141 };
142
143 stream.emit_event(orig_rem_cid, EventData::PacketSent(event), now);
144 }
145 }
146
147 pub(super) fn emit_packet_received(
148 &self,
149 pn: u64,
150 space: SpaceId,
151 is_0rtt: bool,
152 now: Instant,
153 orig_rem_cid: ConnectionId,
154 ) {
155 #[cfg(feature = "qlog")]
156 {
157 let Some(stream) = self.stream.as_ref() else {
158 return;
159 };
160
161 let event = PacketReceived {
162 header: PacketHeader {
163 packet_number: Some(pn),
164 packet_type: packet_type(space, is_0rtt),
165 ..Default::default()
166 },
167 ..Default::default()
168 };
169
170 stream.emit_event(orig_rem_cid, EventData::PacketReceived(event), now);
171 }
172 }
173}
174
175#[cfg(feature = "qlog")]
176impl From<Option<QlogStream>> for QlogSink {
177 fn from(stream: Option<QlogStream>) -> Self {
178 Self { stream }
179 }
180}
181
182#[cfg(feature = "qlog")]
183fn packet_type(space: SpaceId, is_0rtt: bool) -> PacketType {
184 match space {
185 SpaceId::Initial => PacketType::Initial,
186 SpaceId::Handshake => PacketType::Handshake,
187 SpaceId::Data if is_0rtt => PacketType::ZeroRtt,
188 SpaceId::Data => PacketType::OneRtt,
189 }
190}