1use std::collections::HashMap;
14use std::net::SocketAddr;
15use std::sync::atomic::{AtomicU64, Ordering};
16use std::sync::{Arc, Mutex};
17
18use tracing::{Level, Span, debug, error, info, trace, warn};
19use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
20
21use crate::{
22 ConnectionId, Duration, Instant, Side, connection::nat_traversal::NatTraversalRole,
23 frame::FrameType, transport_parameters::TransportParameterId,
24};
25
26#[cfg(test)]
27mod tests;
28
29mod components;
30mod filters;
31mod formatters;
32mod lifecycle;
33pub mod metrics;
35mod structured;
36
37pub use components::*;
38pub use filters::*;
39pub use formatters::*;
40pub use lifecycle::*;
41pub use metrics::*;
42pub use structured::*;
43
44static LOGGER: once_cell::sync::OnceCell<Arc<Logger>> = once_cell::sync::OnceCell::new();
46
47pub fn init_logging(config: LoggingConfig) -> Result<(), LoggingError> {
49 let logger = Arc::new(Logger::new(config)?);
50
51 LOGGER
52 .set(logger.clone())
53 .map_err(|_| LoggingError::AlreadyInitialized)?;
54
55 let env_filter = EnvFilter::from_default_env().add_directive("ant_quic=debug".parse().unwrap());
57
58 if logger.use_json() {
59 let fmt_layer = tracing_subscriber::fmt::layer()
60 .json()
61 .with_target(true)
62 .with_thread_ids(true)
63 .with_level(true);
64
65 tracing_subscriber::registry()
66 .with(env_filter)
67 .with(fmt_layer)
68 .init();
69 } else {
70 let fmt_layer = tracing_subscriber::fmt::layer()
71 .with_target(true)
72 .with_thread_ids(true)
73 .with_level(true);
74
75 tracing_subscriber::registry()
76 .with(env_filter)
77 .with(fmt_layer)
78 .init();
79 }
80
81 info!("ant-quic logging system initialized");
82 Ok(())
83}
84
85pub fn logger() -> Arc<Logger> {
87 LOGGER.get().cloned().unwrap_or_else(|| {
88 let config = LoggingConfig::default();
90 let logger = Arc::new(Logger::new(config).expect("Failed to create default logger"));
91 let _ = LOGGER.set(logger.clone());
92 logger
93 })
94}
95
96pub struct Logger {
98 config: LoggingConfig,
99 metrics_collector: Arc<MetricsCollector>,
100 event_buffer: Arc<Mutex<Vec<LogEvent>>>,
101 rate_limiter: Arc<RateLimiter>,
102}
103
104impl Logger {
105 pub fn new(config: LoggingConfig) -> Result<Self, LoggingError> {
107 let rate_limit = config.rate_limit_per_second;
108 let buffer_size = config.event_buffer_size;
109 Ok(Self {
110 config,
111 metrics_collector: Arc::new(MetricsCollector::new()),
112 event_buffer: Arc::new(Mutex::new(Vec::with_capacity(buffer_size))),
113 rate_limiter: Arc::new(RateLimiter::new(rate_limit, Duration::from_secs(1))),
114 })
115 }
116
117 fn use_json(&self) -> bool {
119 self.config.json_output
120 }
121
122 pub fn log_event(&self, event: LogEvent) {
124 if !self.rate_limiter.should_log(event.level) {
125 return;
126 }
127
128 if let Ok(mut buffer) = self.event_buffer.lock() {
130 if buffer.len() < 10000 {
131 buffer.push(event.clone());
132 }
133 }
134
135 match event.level {
137 Level::ERROR => error!("{} - {}", event.target, event.message),
138 Level::WARN => warn!("{} - {}", event.target, event.message),
139 Level::INFO => info!("{} - {}", event.target, event.message),
140 Level::DEBUG => debug!("{} - {}", event.target, event.message),
141 Level::TRACE => trace!("{} - {}", event.target, event.message),
142 }
143
144 self.metrics_collector.record_event(&event);
146 }
147
148 pub fn recent_events(&self, count: usize) -> Vec<LogEvent> {
150 match self.event_buffer.lock() {
151 Ok(buffer) => buffer.iter().rev().take(count).cloned().collect(),
152 _ => Vec::new(),
153 }
154 }
155
156 pub fn metrics_summary(&self) -> MetricsSummary {
158 self.metrics_collector.summary()
159 }
160}
161
162#[derive(Debug, Clone)]
164pub struct LoggingConfig {
165 pub json_output: bool,
167 pub rate_limit_per_second: u64,
169 pub component_levels: HashMap<String, Level>,
171 pub collect_metrics: bool,
173 pub event_buffer_size: usize,
175}
176
177impl Default for LoggingConfig {
178 fn default() -> Self {
179 Self {
180 json_output: false,
181 rate_limit_per_second: 1000,
182 component_levels: HashMap::new(),
183 collect_metrics: true,
184 event_buffer_size: 10000,
185 }
186 }
187}
188
189#[derive(Debug, Clone)]
191pub struct LogEvent {
192 pub timestamp: Instant,
194 pub level: Level,
196 pub target: String,
198 pub message: String,
200 pub fields: HashMap<String, String>,
202 pub span_id: Option<String>,
204}
205
206#[derive(Debug, Clone, Copy)]
208pub enum ConnectionRole {
209 Client,
211 Server,
213}
214
215#[derive(Debug, Clone)]
217pub struct ConnectionInfo {
218 pub id: ConnectionId,
220 pub remote_addr: SocketAddr,
222 pub role: ConnectionRole,
224}
225
226#[derive(Debug)]
228pub struct FrameInfo {
229 pub frame_type: FrameType,
231 pub size: usize,
233 pub packet_number: Option<u64>,
235}
236
237#[derive(Debug)]
239pub struct TransportParamInfo {
240 pub(crate) param_id: TransportParameterId,
241 pub value: Option<Vec<u8>>,
243 pub side: Side,
245}
246
247#[derive(Debug)]
249pub struct NatTraversalInfo {
250 pub role: NatTraversalRole,
252 pub remote_addr: SocketAddr,
254 pub candidate_count: usize,
256}
257
258#[derive(Debug, Default)]
260pub struct ErrorContext {
261 pub component: &'static str,
263 pub operation: &'static str,
265 pub connection_id: Option<ConnectionId>,
267 pub additional_fields: Vec<(&'static str, &'static str)>,
269}
270
271#[derive(Debug, Default)]
273pub struct WarningContext {
274 pub component: &'static str,
276 pub details: Vec<(&'static str, &'static str)>,
278}
279
280#[derive(Debug, Default)]
282pub struct InfoContext {
283 pub component: &'static str,
285 pub details: Vec<(&'static str, &'static str)>,
287}
288
289#[derive(Debug, Default)]
291pub struct DebugContext {
292 pub component: &'static str,
294 pub details: Vec<(&'static str, &'static str)>,
296}
297
298#[derive(Debug, Default)]
300pub struct TraceContext {
301 pub component: &'static str,
303 pub details: Vec<(&'static str, &'static str)>,
305}
306
307#[derive(Debug, thiserror::Error)]
309pub enum LoggingError {
310 #[error("Logging system already initialized")]
312 AlreadyInitialized,
313 #[error("Failed to initialize tracing subscriber: {0}")]
315 SubscriberError(String),
316}
317
318pub struct RateLimiter {
320 max_events: u64,
322 window: Duration,
324 events_in_window: AtomicU64,
326 window_start: Mutex<Instant>,
328}
329
330impl RateLimiter {
331 pub fn new(max_events: u64, window: Duration) -> Self {
333 Self {
334 max_events,
335 window,
336 events_in_window: AtomicU64::new(0),
337 window_start: Mutex::new(Instant::now()),
338 }
339 }
340
341 pub fn should_log(&self, level: Level) -> bool {
343 if level == Level::ERROR {
345 return true;
346 }
347
348 let now = Instant::now();
349 let mut window_start = self.window_start.lock().unwrap();
350
351 if now.duration_since(*window_start) > self.window {
353 *window_start = now;
354 self.events_in_window.store(0, Ordering::Relaxed);
355 }
356
357 let current = self.events_in_window.fetch_add(1, Ordering::Relaxed);
359 current < self.max_events
360 }
361}
362
363pub fn log_error(message: &str, context: ErrorContext) {
367 let mut fields = HashMap::new();
368 fields.insert("component".to_string(), context.component.to_string());
369 fields.insert("operation".to_string(), context.operation.to_string());
370
371 if let Some(conn_id) = context.connection_id {
372 fields.insert("conn_id".to_string(), format!("{conn_id:?}"));
373 }
374
375 for (key, value) in context.additional_fields {
376 fields.insert(key.to_string(), value.to_string());
377 }
378
379 logger().log_event(LogEvent {
380 timestamp: Instant::now(),
381 level: Level::ERROR,
382 target: format!("ant_quic::{}", context.component),
383 message: message.to_string(),
384 fields,
385 span_id: None,
386 });
387}
388
389pub fn log_warning(message: &str, context: WarningContext) {
391 let mut fields = HashMap::new();
392 fields.insert("component".to_string(), context.component.to_string());
393
394 for (key, value) in context.details {
395 fields.insert(key.to_string(), value.to_string());
396 }
397
398 logger().log_event(LogEvent {
399 timestamp: Instant::now(),
400 level: Level::WARN,
401 target: format!("ant_quic::{}", context.component),
402 message: message.to_string(),
403 fields,
404 span_id: None,
405 });
406}
407
408pub fn log_info(message: &str, context: InfoContext) {
410 let mut fields = HashMap::new();
411 fields.insert("component".to_string(), context.component.to_string());
412
413 for (key, value) in context.details {
414 fields.insert(key.to_string(), value.to_string());
415 }
416
417 logger().log_event(LogEvent {
418 timestamp: Instant::now(),
419 level: Level::INFO,
420 target: format!("ant_quic::{}", context.component),
421 message: message.to_string(),
422 fields,
423 span_id: None,
424 });
425}
426
427pub fn log_debug(message: &str, context: DebugContext) {
429 let mut fields = HashMap::new();
430 fields.insert("component".to_string(), context.component.to_string());
431
432 for (key, value) in context.details {
433 fields.insert(key.to_string(), value.to_string());
434 }
435
436 logger().log_event(LogEvent {
437 timestamp: Instant::now(),
438 level: Level::DEBUG,
439 target: format!("ant_quic::{}", context.component),
440 message: message.to_string(),
441 fields,
442 span_id: None,
443 });
444}
445
446pub fn log_trace(message: &str, context: TraceContext) {
448 let mut fields = HashMap::new();
449 fields.insert("component".to_string(), context.component.to_string());
450
451 for (key, value) in context.details {
452 fields.insert(key.to_string(), value.to_string());
453 }
454
455 logger().log_event(LogEvent {
456 timestamp: Instant::now(),
457 level: Level::TRACE,
458 target: format!("ant_quic::{}", context.component),
459 message: message.to_string(),
460 fields,
461 span_id: None,
462 });
463}
464
465pub fn create_connection_span(conn_id: &ConnectionId) -> Span {
467 tracing::span!(
468 Level::DEBUG,
469 "connection",
470 conn_id = %format!("{:?}", conn_id),
471 )
472}
473
474pub fn create_frame_span(frame_type: FrameType) -> Span {
476 tracing::span!(
477 Level::TRACE,
478 "frame",
479 frame_type = ?frame_type,
480 )
481}