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}