use std::sync::Once;
use tracing_subscriber::FmtSubscriber;
use {std::env, tracing::Level};
static INIT: Once = Once::new();
pub fn setup_logger() {
INIT.call_once(|| {
let log_level = env::var("LOGLEVEL")
.unwrap_or_else(|_| "INFO".to_string())
.to_uppercase();
let level = match log_level.as_str() {
"DEBUG" => Level::DEBUG,
"ERROR" => Level::ERROR,
"WARN" => Level::WARN,
"TRACE" => Level::TRACE,
_ => Level::INFO,
};
let subscriber = FmtSubscriber::builder().with_max_level(level).finish();
if tracing::subscriber::set_global_default(subscriber).is_ok() {
tracing::debug!("Log level set to: {}", level);
}
});
}
#[allow(unused_variables)]
pub fn setup_logger_with_level(log_level: &str) {
INIT.call_once(|| {
let log_level = log_level.to_uppercase();
let level = match log_level.as_str() {
"DEBUG" => Level::DEBUG,
"ERROR" => Level::ERROR,
"WARN" => Level::WARN,
"TRACE" => Level::TRACE,
_ => Level::INFO,
};
let subscriber = FmtSubscriber::builder().with_max_level(level).finish();
if tracing::subscriber::set_global_default(subscriber).is_ok() {
tracing::debug!("Log level set to: {}", level);
}
});
}
#[cfg(test)]
mod tests_setup_logger {
use super::*;
use std::sync::Mutex;
use tracing::subscriber::with_default;
use tracing_subscriber::Layer;
use tracing_subscriber::layer::{Context, SubscriberExt};
use tracing_subscriber::registry;
static TEST_MUTEX: Mutex<()> = Mutex::new(());
#[derive(Clone)]
struct TestLayer {
level: std::sync::Arc<Mutex<Option<Level>>>,
}
impl<S> Layer<S> for TestLayer
where
S: tracing::Subscriber,
{
fn on_event(&self, event: &tracing::Event<'_>, _ctx: Context<'_, S>) {
let mut level = self.level.lock().unwrap();
*level = Some(*event.metadata().level());
}
}
fn create_test_layer() -> (TestLayer, std::sync::Arc<Mutex<Option<Level>>>) {
let level = std::sync::Arc::new(Mutex::new(None));
(
TestLayer {
level: level.clone(),
},
level,
)
}
#[test]
fn test_default_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::remove_var("LOGLEVEL");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::info!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
}
#[test]
fn test_debug_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::set_var("LOGLEVEL", "DEBUG");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::debug!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::DEBUG));
unsafe {
env::remove_var("LOGLEVEL");
}
}
#[test]
fn test_error_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::set_var("LOGLEVEL", "ERROR");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::error!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::ERROR));
unsafe {
env::remove_var("LOGLEVEL");
}
}
#[test]
fn test_warn_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::set_var("LOGLEVEL", "WARN");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::warn!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::WARN));
unsafe {
env::remove_var("LOGLEVEL");
}
}
#[test]
fn test_trace_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::set_var("LOGLEVEL", "TRACE");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::trace!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::TRACE));
unsafe {
env::remove_var("LOGLEVEL");
}
}
#[test]
fn test_invalid_log_level() {
let _lock = TEST_MUTEX.lock().unwrap();
unsafe {
env::set_var("LOGLEVEL", "INVALID");
}
let (layer, level) = create_test_layer();
let subscriber = registry().with(layer);
with_default(subscriber, || {
tracing::info!("Test log");
});
assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
unsafe {
env::remove_var("LOGLEVEL");
}
}
}