use tracing::Level;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
pub fn is_verbose_enabled() -> bool {
std::env::var("VERBOSE").is_ok() || std::env::args().any(|arg| arg == "--verbose")
}
#[derive(Debug, Clone, Default)]
pub struct LoggerOptions {
pub verbose: bool,
}
pub fn init_logger(options: LoggerOptions) {
let level = if options.verbose {
Level::DEBUG
} else {
Level::ERROR
};
let filter = EnvFilter::from_default_env().add_directive(level.into());
let subscriber = fmt::layer().with_target(true).with_level(true);
tracing_subscriber::registry()
.with(filter)
.with(subscriber)
.try_init()
.ok(); }
#[derive(Debug, Clone)]
pub struct Logger {
verbose: bool,
}
impl Logger {
pub fn new(options: LoggerOptions) -> Self {
Self {
verbose: options.verbose,
}
}
pub fn debug<F>(&self, mut message_fn: F)
where
F: FnMut() -> String,
{
if self.verbose {
let msg = message_fn();
tracing::debug!("{}", msg);
}
}
pub fn error(&self, message: &str) {
tracing::error!("{}", message);
}
pub fn info(&self, message: &str) {
tracing::info!("{}", message);
}
pub fn warn(&self, message: &str) {
tracing::warn!("{}", message);
}
pub fn is_verbose(&self) -> bool {
self.verbose
}
}
impl Default for Logger {
fn default() -> Self {
Self {
verbose: is_verbose_enabled(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn logger_default_is_not_verbose() {
std::env::remove_var("VERBOSE");
let logger = Logger::default();
assert!(!logger.is_verbose() || is_verbose_enabled());
}
#[test]
fn logger_can_be_created_with_verbose_true() {
let logger = Logger::new(LoggerOptions { verbose: true });
assert!(logger.is_verbose());
}
#[test]
fn logger_can_be_created_with_verbose_false() {
let logger = Logger::new(LoggerOptions { verbose: false });
assert!(!logger.is_verbose());
}
#[test]
fn logger_options_default_is_not_verbose() {
let options = LoggerOptions::default();
assert!(!options.verbose);
}
#[test]
fn debug_message_fn_not_called_when_not_verbose() {
let logger = Logger::new(LoggerOptions { verbose: false });
let mut was_called = false;
logger.debug(|| {
was_called = true;
"test message".to_string()
});
assert!(!was_called);
}
#[test]
fn debug_message_fn_called_when_verbose() {
let logger = Logger::new(LoggerOptions { verbose: true });
let mut was_called = false;
logger.debug(|| {
was_called = true;
"test message".to_string()
});
assert!(was_called);
}
}