1use std::collections::HashMap;
7use std::net::SocketAddr;
8use std::sync::atomic::{AtomicU64, Ordering};
9use std::sync::{Arc, Mutex};
10
11use tracing::{Level, Span, debug, error, info, trace, warn};
12use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
13
14use crate::{
15 ConnectionId, Duration, Instant, Side, connection::nat_traversal::NatTraversalRole,
16 frame::FrameType, transport_parameters::TransportParameterId,
17};
18
19#[cfg(test)]
20mod tests;
21
22mod components;
23mod filters;
24mod formatters;
25mod lifecycle;
26pub mod metrics;
27mod structured;
28
29pub use components::*;
30pub use filters::*;
31pub use formatters::*;
32pub use lifecycle::*;
33pub use metrics::*;
34pub use structured::*;
35
36static LOGGER: once_cell::sync::OnceCell<Arc<Logger>> = once_cell::sync::OnceCell::new();
38
39pub fn init_logging(config: LoggingConfig) -> Result<(), LoggingError> {
41 let logger = Arc::new(Logger::new(config)?);
42
43 LOGGER
44 .set(logger.clone())
45 .map_err(|_| LoggingError::AlreadyInitialized)?;
46
47 let env_filter = EnvFilter::from_default_env().add_directive("ant_quic=debug".parse().unwrap());
49
50 if logger.use_json() {
51 let fmt_layer = tracing_subscriber::fmt::layer()
52 .json()
53 .with_target(true)
54 .with_thread_ids(true)
55 .with_level(true);
56
57 tracing_subscriber::registry()
58 .with(env_filter)
59 .with(fmt_layer)
60 .init();
61 } else {
62 let fmt_layer = tracing_subscriber::fmt::layer()
63 .with_target(true)
64 .with_thread_ids(true)
65 .with_level(true);
66
67 tracing_subscriber::registry()
68 .with(env_filter)
69 .with(fmt_layer)
70 .init();
71 }
72
73 info!("ant-quic logging system initialized");
74 Ok(())
75}
76
77pub fn logger() -> Arc<Logger> {
79 LOGGER.get().cloned().unwrap_or_else(|| {
80 let config = LoggingConfig::default();
82 let logger = Arc::new(Logger::new(config).expect("Failed to create default logger"));
83 let _ = LOGGER.set(logger.clone());
84 logger
85 })
86}
87
88pub struct Logger {
90 config: LoggingConfig,
91 metrics_collector: Arc<MetricsCollector>,
92 event_buffer: Arc<Mutex<Vec<LogEvent>>>,
93 rate_limiter: Arc<RateLimiter>,
94}
95
96impl Logger {
97 pub fn new(config: LoggingConfig) -> Result<Self, LoggingError> {
99 let rate_limit = config.rate_limit_per_second;
100 let buffer_size = config.event_buffer_size;
101 Ok(Self {
102 config,
103 metrics_collector: Arc::new(MetricsCollector::new()),
104 event_buffer: Arc::new(Mutex::new(Vec::with_capacity(buffer_size))),
105 rate_limiter: Arc::new(RateLimiter::new(rate_limit, Duration::from_secs(1))),
106 })
107 }
108
109 fn use_json(&self) -> bool {
111 self.config.json_output
112 }
113
114 pub fn log_event(&self, event: LogEvent) {
116 if !self.rate_limiter.should_log(event.level) {
117 return;
118 }
119
120 if let Ok(mut buffer) = self.event_buffer.lock() {
122 if buffer.len() < 10000 {
123 buffer.push(event.clone());
124 }
125 }
126
127 match event.level {
129 Level::ERROR => error!("{} - {}", event.target, event.message),
130 Level::WARN => warn!("{} - {}", event.target, event.message),
131 Level::INFO => info!("{} - {}", event.target, event.message),
132 Level::DEBUG => debug!("{} - {}", event.target, event.message),
133 Level::TRACE => trace!("{} - {}", event.target, event.message),
134 }
135
136 self.metrics_collector.record_event(&event);
138 }
139
140 pub fn recent_events(&self, count: usize) -> Vec<LogEvent> {
142 match self.event_buffer.lock() {
143 Ok(buffer) => buffer.iter().rev().take(count).cloned().collect(),
144 _ => Vec::new(),
145 }
146 }
147
148 pub fn metrics_summary(&self) -> MetricsSummary {
150 self.metrics_collector.summary()
151 }
152}
153
154#[derive(Debug, Clone)]
156pub struct LoggingConfig {
157 pub json_output: bool,
159 pub rate_limit_per_second: u64,
161 pub component_levels: HashMap<String, Level>,
163 pub collect_metrics: bool,
165 pub event_buffer_size: usize,
167}
168
169impl Default for LoggingConfig {
170 fn default() -> Self {
171 Self {
172 json_output: false,
173 rate_limit_per_second: 1000,
174 component_levels: HashMap::new(),
175 collect_metrics: true,
176 event_buffer_size: 10000,
177 }
178 }
179}
180
181#[derive(Debug, Clone)]
183pub struct LogEvent {
184 pub timestamp: Instant,
185 pub level: Level,
186 pub target: String,
187 pub message: String,
188 pub fields: HashMap<String, String>,
189 pub span_id: Option<String>,
190}
191
192#[derive(Debug, Clone, Copy)]
194pub enum ConnectionRole {
195 Client,
196 Server,
197}
198
199#[derive(Debug, Clone)]
201pub struct ConnectionInfo {
202 pub id: ConnectionId,
203 pub remote_addr: SocketAddr,
204 pub role: ConnectionRole,
205}
206
207#[derive(Debug)]
209pub struct FrameInfo {
210 pub frame_type: FrameType,
211 pub size: usize,
212 pub packet_number: Option<u64>,
213}
214
215#[derive(Debug)]
217pub struct TransportParamInfo {
218 pub(crate) param_id: TransportParameterId,
219 pub value: Option<Vec<u8>>,
220 pub side: Side,
221}
222
223#[derive(Debug)]
225pub struct NatTraversalInfo {
226 pub role: NatTraversalRole,
227 pub remote_addr: SocketAddr,
228 pub candidate_count: usize,
229}
230
231#[derive(Debug, Default)]
233pub struct ErrorContext {
234 pub component: &'static str,
235 pub operation: &'static str,
236 pub connection_id: Option<ConnectionId>,
237 pub additional_fields: Vec<(&'static str, &'static str)>,
238}
239
240#[derive(Debug, Default)]
242pub struct WarningContext {
243 pub component: &'static str,
244 pub details: Vec<(&'static str, &'static str)>,
245}
246
247#[derive(Debug, Default)]
249pub struct InfoContext {
250 pub component: &'static str,
251 pub details: Vec<(&'static str, &'static str)>,
252}
253
254#[derive(Debug, Default)]
256pub struct DebugContext {
257 pub component: &'static str,
258 pub details: Vec<(&'static str, &'static str)>,
259}
260
261#[derive(Debug, Default)]
263pub struct TraceContext {
264 pub component: &'static str,
265 pub details: Vec<(&'static str, &'static str)>,
266}
267
268#[derive(Debug, thiserror::Error)]
270pub enum LoggingError {
271 #[error("Logging system already initialized")]
272 AlreadyInitialized,
273 #[error("Failed to initialize tracing subscriber: {0}")]
274 SubscriberError(String),
275}
276
277pub struct RateLimiter {
279 max_events: u64,
280 window: Duration,
281 events_in_window: AtomicU64,
282 window_start: Mutex<Instant>,
283}
284
285impl RateLimiter {
286 pub fn new(max_events: u64, window: Duration) -> Self {
287 Self {
288 max_events,
289 window,
290 events_in_window: AtomicU64::new(0),
291 window_start: Mutex::new(Instant::now()),
292 }
293 }
294
295 pub fn should_log(&self, level: Level) -> bool {
296 if level == Level::ERROR {
298 return true;
299 }
300
301 let now = Instant::now();
302 let mut window_start = self.window_start.lock().unwrap();
303
304 if now.duration_since(*window_start) > self.window {
306 *window_start = now;
307 self.events_in_window.store(0, Ordering::Relaxed);
308 }
309
310 let current = self.events_in_window.fetch_add(1, Ordering::Relaxed);
312 current < self.max_events
313 }
314}
315
316pub fn log_error(message: &str, context: ErrorContext) {
320 let mut fields = HashMap::new();
321 fields.insert("component".to_string(), context.component.to_string());
322 fields.insert("operation".to_string(), context.operation.to_string());
323
324 if let Some(conn_id) = context.connection_id {
325 fields.insert("conn_id".to_string(), format!("{conn_id:?}"));
326 }
327
328 for (key, value) in context.additional_fields {
329 fields.insert(key.to_string(), value.to_string());
330 }
331
332 logger().log_event(LogEvent {
333 timestamp: Instant::now(),
334 level: Level::ERROR,
335 target: format!("ant_quic::{}", context.component),
336 message: message.to_string(),
337 fields,
338 span_id: None,
339 });
340}
341
342pub fn log_warning(message: &str, context: WarningContext) {
344 let mut fields = HashMap::new();
345 fields.insert("component".to_string(), context.component.to_string());
346
347 for (key, value) in context.details {
348 fields.insert(key.to_string(), value.to_string());
349 }
350
351 logger().log_event(LogEvent {
352 timestamp: Instant::now(),
353 level: Level::WARN,
354 target: format!("ant_quic::{}", context.component),
355 message: message.to_string(),
356 fields,
357 span_id: None,
358 });
359}
360
361pub fn log_info(message: &str, context: InfoContext) {
363 let mut fields = HashMap::new();
364 fields.insert("component".to_string(), context.component.to_string());
365
366 for (key, value) in context.details {
367 fields.insert(key.to_string(), value.to_string());
368 }
369
370 logger().log_event(LogEvent {
371 timestamp: Instant::now(),
372 level: Level::INFO,
373 target: format!("ant_quic::{}", context.component),
374 message: message.to_string(),
375 fields,
376 span_id: None,
377 });
378}
379
380pub fn log_debug(message: &str, context: DebugContext) {
382 let mut fields = HashMap::new();
383 fields.insert("component".to_string(), context.component.to_string());
384
385 for (key, value) in context.details {
386 fields.insert(key.to_string(), value.to_string());
387 }
388
389 logger().log_event(LogEvent {
390 timestamp: Instant::now(),
391 level: Level::DEBUG,
392 target: format!("ant_quic::{}", context.component),
393 message: message.to_string(),
394 fields,
395 span_id: None,
396 });
397}
398
399pub fn log_trace(message: &str, context: TraceContext) {
401 let mut fields = HashMap::new();
402 fields.insert("component".to_string(), context.component.to_string());
403
404 for (key, value) in context.details {
405 fields.insert(key.to_string(), value.to_string());
406 }
407
408 logger().log_event(LogEvent {
409 timestamp: Instant::now(),
410 level: Level::TRACE,
411 target: format!("ant_quic::{}", context.component),
412 message: message.to_string(),
413 fields,
414 span_id: None,
415 });
416}
417
418pub fn create_connection_span(conn_id: &ConnectionId) -> Span {
420 tracing::span!(
421 Level::DEBUG,
422 "connection",
423 conn_id = %format!("{:?}", conn_id),
424 )
425}
426
427pub fn create_frame_span(frame_type: FrameType) -> Span {
429 tracing::span!(
430 Level::TRACE,
431 "frame",
432 frame_type = ?frame_type,
433 )
434}