rstructor/
logging.rs

1//! Logging functionality for rstructor
2//!
3//! This module provides utilities for configuring and working with logging
4//! through the `tracing` crate.
5
6use tracing::Level;
7use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
8
9/// Log levels supported by rstructor.
10///
11/// These map to the tracing level hierarchy: ERROR, WARN, INFO, DEBUG, TRACE.
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum LogLevel {
14    /// Error logs only - highest priority messages for critical failures
15    Error,
16    /// Warning and error logs - indicate potential issues
17    Warn,
18    /// Info, warning, and error logs - normal operational messages
19    Info,
20    /// Debug, info, warning, and error logs - detailed information for troubleshooting
21    Debug,
22    /// Trace, debug, info, warning, and error logs - highly detailed diagnostics
23    Trace,
24}
25
26impl LogLevel {
27    /// Convert to the corresponding tracing level
28    fn to_tracing_level(self) -> Level {
29        match self {
30            LogLevel::Error => Level::ERROR,
31            LogLevel::Warn => Level::WARN,
32            LogLevel::Info => Level::INFO,
33            LogLevel::Debug => Level::DEBUG,
34            LogLevel::Trace => Level::TRACE,
35        }
36    }
37}
38
39/// Initialize logging for rstructor with a specific log level.
40///
41/// This function sets up the tracing subscriber with the specified log level.
42/// It's typically called once at the start of your application.
43///
44/// # Examples
45///
46/// ```no_run
47/// use rstructor::logging::{init_logging, LogLevel};
48///
49/// // Initialize with info level logs
50/// init_logging(LogLevel::Info);
51///
52/// // Now tracing macros will work
53/// tracing::info!("Application starting");
54/// tracing::debug!("This won't be shown with INFO level");
55/// ```
56///
57/// # Environment Variable
58///
59/// You can override the logging level by setting the `RSTRUCTOR_LOG` environment variable:
60///
61/// ```bash
62/// RSTRUCTOR_LOG=debug cargo run
63/// ```
64///
65/// This will take precedence over the level passed to `init_logging()`.
66pub fn init_logging(level: LogLevel) {
67    // Check if RSTRUCTOR_LOG environment variable is set
68    let env_filter = EnvFilter::try_from_env("RSTRUCTOR_LOG").unwrap_or_else(|_| {
69        // If not set, use the provided level
70        EnvFilter::new(format!("rstructor={}", level.to_tracing_level()))
71    });
72
73    // Create a subscriber with a custom filter and formatter
74    tracing_subscriber::registry()
75        .with(fmt::layer().with_target(true))
76        .with(env_filter)
77        .init();
78
79    // Log initialization
80    tracing::info!("rstructor logging initialized at level: {:?}", level);
81}
82
83/// Initialize logging with custom environment filter
84///
85/// This allows for more granular control over what gets logged.
86///
87/// # Examples
88///
89/// ```no_run
90/// use rstructor::logging::init_logging_with_filter;
91///
92/// // Initialize with a custom filter string
93/// init_logging_with_filter("rstructor=debug,rstructor::backend=trace");
94/// ```
95pub fn init_logging_with_filter(filter: &str) {
96    let env_filter = EnvFilter::try_new(filter).unwrap_or_else(|_| {
97        tracing::warn!("Invalid filter string: {}, using default (info)", filter);
98        EnvFilter::new("rstructor=info")
99    });
100
101    tracing_subscriber::registry()
102        .with(fmt::layer().with_target(true))
103        .with(env_filter)
104        .init();
105
106    tracing::info!(
107        "rstructor logging initialized with custom filter: {}",
108        filter
109    );
110}