ant_quic/logging/
components.rs

1/// Component-specific logging functions
2///
3/// Provides specialized logging for different components of the QUIC stack
4use std::collections::HashMap;
5use tracing::{debug, trace};
6
7use crate::{ConnectionId, Frame};
8
9use super::{ConnectionInfo, FrameInfo, LogEvent, NatTraversalInfo, TransportParamInfo, logger};
10
11/// Connection event types
12#[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/// Frame event types
25#[derive(Debug, Clone, Copy)]
26pub enum FrameEventType {
27    Sent,
28    Received,
29    Dropped,
30    Retransmitted,
31    Acknowledged,
32}
33
34/// Transport parameter event types
35#[derive(Debug, Clone, Copy)]
36pub enum TransportParamEventType {
37    Sent,
38    Received,
39    Negotiated,
40    Rejected,
41    Invalid,
42}
43
44/// NAT traversal event types
45#[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
57/// Log a connection event
58pub 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
92/// Log a frame event
93pub 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
128/// Log a transport parameter event
129pub 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) = &param_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
166/// Log a NAT traversal event
167pub 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
208/// Log error with full context
209pub 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    // Add error chain
219    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
244/// Log detailed frame information
245pub(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
294/// Log packet-level events
295pub 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
321/// Log stream events
322pub 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}