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