1use std::collections::HashMap;
5use tracing::{debug, trace};
6
7use crate::{ConnectionId, Frame};
8
9use super::{ConnectionInfo, FrameInfo, LogEvent, NatTraversalInfo, TransportParamInfo, logger};
10
11#[derive(Debug, Clone, Copy)]
13pub enum ConnectionEventType {
14 Initiated,
15 HandshakeStarted,
16 HandshakeCompleted,
17 Established,
18 Migrated,
19 Closed,
20 Lost,
21 Stalled,
22}
23
24#[derive(Debug, Clone, Copy)]
26pub enum FrameEventType {
27 Sent,
28 Received,
29 Dropped,
30 Retransmitted,
31 Acknowledged,
32}
33
34#[derive(Debug, Clone, Copy)]
36pub enum TransportParamEventType {
37 Sent,
38 Received,
39 Negotiated,
40 Rejected,
41 Invalid,
42}
43
44#[derive(Debug, Clone, Copy)]
46pub enum NatTraversalEventType {
47 Started,
48 CandidateDiscovered,
49 CandidateValidated,
50 HolePunchingStarted,
51 HolePunchingSucceeded,
52 HolePunchingFailed,
53 Completed,
54 Failed,
55}
56
57pub fn log_connection_event(event_type: ConnectionEventType, conn_info: &ConnectionInfo) {
59 let message = match event_type {
60 ConnectionEventType::Initiated => "connection.initiated",
61 ConnectionEventType::HandshakeStarted => "connection.handshake_started",
62 ConnectionEventType::HandshakeCompleted => "connection.handshake_completed",
63 ConnectionEventType::Established => "connection.established",
64 ConnectionEventType::Migrated => "connection.migrated",
65 ConnectionEventType::Closed => "connection.closed",
66 ConnectionEventType::Lost => "connection.lost",
67 ConnectionEventType::Stalled => "connection.stalled",
68 };
69
70 let mut fields = HashMap::new();
71 fields.insert("conn_id".to_string(), format!("{:?}", conn_info.id));
72 fields.insert("remote_addr".to_string(), conn_info.remote_addr.to_string());
73 fields.insert("role".to_string(), format!("{:?}", conn_info.role));
74 fields.insert("event_type".to_string(), format!("{event_type:?}"));
75
76 let level = match event_type {
77 ConnectionEventType::Lost | ConnectionEventType::Stalled => tracing::Level::WARN,
78 ConnectionEventType::Closed => tracing::Level::DEBUG,
79 _ => tracing::Level::INFO,
80 };
81
82 logger().log_event(LogEvent {
83 timestamp: crate::Instant::now(),
84 level,
85 target: "ant_quic::connection".to_string(),
86 message: message.to_string(),
87 fields,
88 span_id: None,
89 });
90}
91
92pub fn log_frame_event(event_type: FrameEventType, frame_info: &FrameInfo) {
94 let message = match event_type {
95 FrameEventType::Sent => "frame.sent",
96 FrameEventType::Received => "frame.received",
97 FrameEventType::Dropped => "frame.dropped",
98 FrameEventType::Retransmitted => "frame.retransmitted",
99 FrameEventType::Acknowledged => "frame.acknowledged",
100 };
101
102 let mut fields = HashMap::new();
103 fields.insert(
104 "frame_type".to_string(),
105 format!("{:?}", frame_info.frame_type),
106 );
107 fields.insert("size".to_string(), frame_info.size.to_string());
108 if let Some(pn) = frame_info.packet_number {
109 fields.insert("packet_number".to_string(), pn.to_string());
110 }
111 fields.insert("event_type".to_string(), format!("{event_type:?}"));
112
113 let level = match event_type {
114 FrameEventType::Dropped => tracing::Level::WARN,
115 _ => tracing::Level::TRACE,
116 };
117
118 logger().log_event(LogEvent {
119 timestamp: crate::Instant::now(),
120 level,
121 target: "ant_quic::frame".to_string(),
122 message: message.to_string(),
123 fields,
124 span_id: None,
125 });
126}
127
128pub fn log_transport_param_event(
130 event_type: TransportParamEventType,
131 param_info: &TransportParamInfo,
132) {
133 let message = match event_type {
134 TransportParamEventType::Sent => "transport_param.sent",
135 TransportParamEventType::Received => "transport_param.received",
136 TransportParamEventType::Negotiated => "transport_param.negotiated",
137 TransportParamEventType::Rejected => "transport_param.rejected",
138 TransportParamEventType::Invalid => "transport_param.invalid",
139 };
140
141 let mut fields = HashMap::new();
142 fields.insert("param_id".to_string(), format!("{:?}", param_info.param_id));
143 fields.insert("side".to_string(), format!("{:?}", param_info.side));
144 if let Some(value) = ¶m_info.value {
145 fields.insert("value_len".to_string(), value.len().to_string());
146 }
147 fields.insert("event_type".to_string(), format!("{event_type:?}"));
148
149 let level = match event_type {
150 TransportParamEventType::Rejected | TransportParamEventType::Invalid => {
151 tracing::Level::WARN
152 }
153 _ => tracing::Level::DEBUG,
154 };
155
156 logger().log_event(LogEvent {
157 timestamp: crate::Instant::now(),
158 level,
159 target: "ant_quic::transport_params".to_string(),
160 message: message.to_string(),
161 fields,
162 span_id: None,
163 });
164}
165
166pub fn log_nat_traversal_event(event_type: NatTraversalEventType, nat_info: &NatTraversalInfo) {
168 let message = match event_type {
169 NatTraversalEventType::Started => "nat_traversal.started",
170 NatTraversalEventType::CandidateDiscovered => "nat_traversal.candidate_discovered",
171 NatTraversalEventType::CandidateValidated => "nat_traversal.candidate_validated",
172 NatTraversalEventType::HolePunchingStarted => "nat_traversal.hole_punching_started",
173 NatTraversalEventType::HolePunchingSucceeded => "nat_traversal.hole_punching_succeeded",
174 NatTraversalEventType::HolePunchingFailed => "nat_traversal.hole_punching_failed",
175 NatTraversalEventType::Completed => "nat_traversal.completed",
176 NatTraversalEventType::Failed => "nat_traversal.failed",
177 };
178
179 let mut fields = HashMap::new();
180 fields.insert("role".to_string(), format!("{:?}", nat_info.role));
181 fields.insert("remote_addr".to_string(), nat_info.remote_addr.to_string());
182 fields.insert(
183 "candidate_count".to_string(),
184 nat_info.candidate_count.to_string(),
185 );
186 fields.insert("event_type".to_string(), format!("{event_type:?}"));
187
188 let level = match event_type {
189 NatTraversalEventType::HolePunchingFailed | NatTraversalEventType::Failed => {
190 tracing::Level::WARN
191 }
192 NatTraversalEventType::HolePunchingSucceeded | NatTraversalEventType::Completed => {
193 tracing::Level::INFO
194 }
195 _ => tracing::Level::DEBUG,
196 };
197
198 logger().log_event(LogEvent {
199 timestamp: crate::Instant::now(),
200 level,
201 target: "ant_quic::nat_traversal".to_string(),
202 message: message.to_string(),
203 fields,
204 span_id: None,
205 });
206}
207
208pub fn log_error_with_context(error: &dyn std::error::Error, context: super::ErrorContext) {
210 let mut fields = HashMap::new();
211 fields.insert("component".to_string(), context.component.to_string());
212 fields.insert("operation".to_string(), context.operation.to_string());
213
214 if let Some(conn_id) = context.connection_id {
215 fields.insert("conn_id".to_string(), format!("{conn_id:?}"));
216 }
217
218 let mut error_chain = Vec::new();
220 let mut current_error: &dyn std::error::Error = error;
221 error_chain.push(current_error.to_string());
222
223 while let Some(source) = current_error.source() {
224 error_chain.push(source.to_string());
225 current_error = source;
226 }
227
228 fields.insert("error_chain".to_string(), error_chain.join(" -> "));
229
230 for (key, value) in context.additional_fields {
231 fields.insert(key.to_string(), value.to_string());
232 }
233
234 logger().log_event(LogEvent {
235 timestamp: crate::Instant::now(),
236 level: tracing::Level::ERROR,
237 target: format!("ant_quic::{}", context.component),
238 message: error.to_string(),
239 fields,
240 span_id: None,
241 });
242}
243
244pub(crate) fn log_frame_details(frame: &Frame, direction: &str, conn_id: &ConnectionId) {
246 trace!(
247 target: "ant_quic::frame::details",
248 conn_id = ?conn_id,
249 direction = direction,
250 frame_type = ?frame.ty(),
251 "Processing frame"
252 );
253
254 match frame {
255 Frame::ObservedAddress(addr) => {
256 debug!(
257 target: "ant_quic::frame::observed_address",
258 conn_id = ?conn_id,
259 sequence_number = addr.sequence_number.0,
260 address = ?addr.address,
261 "OBSERVED_ADDRESS frame"
262 );
263 }
264 Frame::AddAddress(addr) => {
265 debug!(
266 target: "ant_quic::frame::add_address",
267 conn_id = ?conn_id,
268 sequence = addr.sequence.0,
269 address = ?addr.address,
270 priority = addr.priority.0,
271 "ADD_ADDRESS frame"
272 );
273 }
274 Frame::PunchMeNow(punch) => {
275 debug!(
276 target: "ant_quic::frame::punch_me_now",
277 conn_id = ?conn_id,
278 paired_with_sequence_number = punch.paired_with_sequence_number.0,
279 round = punch.round.0,
280 "PUNCH_ME_NOW frame"
281 );
282 }
283 _ => {
284 trace!(
285 target: "ant_quic::frame::other",
286 conn_id = ?conn_id,
287 frame_type = ?frame.ty(),
288 "Standard QUIC frame"
289 );
290 }
291 }
292}
293
294pub fn log_packet_event(
296 event: &str,
297 conn_id: &ConnectionId,
298 packet_number: u64,
299 size: usize,
300 details: Vec<(&str, &str)>,
301) {
302 let mut fields = HashMap::new();
303 fields.insert("conn_id".to_string(), format!("{conn_id:?}"));
304 fields.insert("packet_number".to_string(), packet_number.to_string());
305 fields.insert("size".to_string(), size.to_string());
306
307 for (key, value) in details {
308 fields.insert(key.to_string(), value.to_string());
309 }
310
311 logger().log_event(LogEvent {
312 timestamp: crate::Instant::now(),
313 level: tracing::Level::TRACE,
314 target: "ant_quic::packet".to_string(),
315 message: event.to_string(),
316 fields,
317 span_id: None,
318 });
319}
320
321pub fn log_stream_event(
323 event: &str,
324 conn_id: &ConnectionId,
325 stream_id: crate::StreamId,
326 details: Vec<(&str, &str)>,
327) {
328 let mut fields = HashMap::new();
329 fields.insert("conn_id".to_string(), format!("{conn_id:?}"));
330 fields.insert("stream_id".to_string(), format!("{stream_id}"));
331
332 for (key, value) in details {
333 fields.insert(key.to_string(), value.to_string());
334 }
335
336 logger().log_event(LogEvent {
337 timestamp: crate::Instant::now(),
338 level: tracing::Level::DEBUG,
339 target: "ant_quic::stream".to_string(),
340 message: event.to_string(),
341 fields,
342 span_id: None,
343 });
344}