ferrite_logging/
lib.rs

1use std::str::FromStr;
2use tracing::{instrument, Level};
3use tracing_subscriber::{
4    fmt::{self, format::FmtSpan},
5    layer::SubscriberExt,
6    util::SubscriberInitExt,
7    Layer,
8    Registry,
9};
10
11// Export our new metrics module
12pub mod metrics;
13pub use metrics::PerformanceMetrics;
14
15#[derive(Debug, Clone, Copy)]
16pub enum LogLevel {
17    Trace,
18    Debug,
19    Info,
20    Warn,
21    Error,
22}
23impl FromStr for LogLevel {
24    type Err = String;
25
26    fn from_str(s: &str) -> Result<Self, Self::Err> {
27        match s.to_lowercase().as_str() {
28            "trace" => Ok(LogLevel::Trace),
29            "debug" => Ok(LogLevel::Debug),
30            "info" => Ok(LogLevel::Info),
31            "warn" => Ok(LogLevel::Warn),
32            "error" => Ok(LogLevel::Error),
33            _ => Err(format!("Invalid log level: {}", s)),
34        }
35    }
36}
37
38impl From<LogLevel> for Level {
39    fn from(level: LogLevel) -> Self {
40        match level {
41            LogLevel::Trace => Level::TRACE,
42            LogLevel::Debug => Level::DEBUG,
43            LogLevel::Info => Level::INFO,
44            LogLevel::Warn => Level::WARN,
45            LogLevel::Error => Level::ERROR,
46        }
47    }
48}
49
50#[derive(Debug)]
51pub struct LogConfig {
52    pub level:        LogLevel,
53    pub enable_tracy: bool,
54    // Adding new configuration options for performance logging
55    pub log_spans:    bool,
56}
57
58impl Default for LogConfig {
59    fn default() -> Self {
60        Self {
61            level:        LogLevel::Info,
62            enable_tracy: false,
63            log_spans:    true,
64        }
65    }
66}
67
68#[instrument]
69pub fn init(config: LogConfig) {
70    let level = Level::from(config.level);
71    let filter = tracing_subscriber::filter::LevelFilter::from_level(level);
72
73    let fmt_layer = fmt::layer()
74        .with_line_number(true)
75        .with_thread_ids(true)
76        .with_file(true)
77        .with_timer(fmt::time::UtcTime::rfc_3339())
78        .with_span_events(FmtSpan::EXIT)
79        .with_filter(filter.clone());
80
81    let registry = Registry::default().with(fmt_layer);
82
83    if config.enable_tracy {
84        // Create the tracy layer with the correct configuration
85        let tracy_layer =
86            tracing_tracy::TracyLayer::default().with_filter(filter);
87
88        registry
89            .with(tracy_layer)
90            .try_init()
91            .expect("Failed to initialize logging with tracy");
92
93        // After initialization, we can use tracy-client directly for frame
94        // marking
95        tracy_client::frame_mark();
96    } else {
97        registry
98            .try_init()
99            .expect("Failed to initialize logging");
100    }
101}
102
103#[instrument]
104pub fn get_log_level_from_env() -> LogLevel {
105    std::env::var("RUST_LOG")
106        .ok()
107        .and_then(|s| s.parse().ok())
108        .unwrap_or(LogLevel::Info)
109}