#[macro_export]
macro_rules! trace {
() => {{
println!();
}};
($($x:tt)*) => {{
#[cfg(debug_assertions)]
println!("\x1b[95m[ TRACE] - {}\x1b[0m", format_args!($($x)*));
#[cfg(not(debug_assertions))]
log::trace!($($x)*);
}};
}
#[macro_export]
macro_rules! debug {
() => {{
println!();
}};
($($x:tt)*) => {{
#[cfg(debug_assertions)]
println!("\x1b[96m[ DEBUG] - {}\x1b[0m", format_args!($($x)*));
#[cfg(not(debug_assertions))]
log::debug!($($x)*);
}};
}
#[macro_export]
macro_rules! info {
() => {{
println!();
}};
($($x:tt)*) => {{
#[cfg(debug_assertions)]
println!("\x1b[32m[ INFO] - {}\x1b[0m", format_args!($($x)*));
#[cfg(not(debug_assertions))]
log::info!($($x)*);
}};
}
#[macro_export]
macro_rules! warn {
() => {{
println!();
}};
($($x:tt)*) => {{
#[cfg(debug_assertions)]
println!("\x1b[33m[ WARN] - {}\x1b[0m", format_args!($($x)*));
#[cfg(not(debug_assertions))]
log::warn!($($x)*);
}};
}
#[macro_export]
macro_rules! error {
() => {{
println!();
}};
($($x:tt)*) => {{
#[cfg(debug_assertions)]
println!("\x1b[31m[ ERROR] - {}\x1b[0m", format_args!($($x)*));
#[cfg(not(debug_assertions))]
log::error!($($x)*);
}};
}
#[cfg(feature = "log4rs")]
pub use log4rs::Log4rsConfig;
#[cfg(feature = "log4rs")]
mod log4rs {
use chrono::Local;
use log::LevelFilter;
use log4rs::{
append::{
console::{ConsoleAppender, Target},
file::FileAppender,
},
config::{Appender, Root},
encode::pattern::PatternEncoder,
filter::threshold::ThresholdFilter,
};
#[derive(Default, Debug)]
pub struct Log4rsConfig<'a> {
root_level: Option<LevelFilter>,
console_level: Option<LevelFilter>,
filename: Option<&'a str>,
filepath: Option<&'a str>,
file_level: Option<LevelFilter>,
pattern: Option<&'a str>,
}
#[allow(dead_code)]
impl<'a> Log4rsConfig<'a> {
#[inline]
pub fn set_root_level(&mut self, level: LevelFilter) -> &mut Self {
self.root_level = Some(level);
self
}
#[inline]
pub fn set_console_level(&mut self, filter: LevelFilter) -> &mut Self {
self.console_level = Some(filter);
self
}
#[inline]
pub fn set_file_level(&mut self, filter: LevelFilter) -> &mut Self {
self.file_level = Some(filter);
self
}
#[inline]
pub fn set_filename(&mut self, filename: &'a str) -> &mut Self {
self.filename = Some(filename);
self
}
#[inline]
pub fn set_filepath(&mut self, filepath: &'a str) -> &mut Self {
self.filepath = Some(filepath);
self
}
#[inline]
pub fn set_pattern(&mut self, pattern: &'a str) -> &mut Self {
self.pattern = Some(pattern);
self
}
pub fn initialize(&self) -> Result<(), Box<dyn std::error::Error>> {
let mut builder = log4rs::config::Config::builder();
let pattern = self.pattern.unwrap_or("{d} [{l}] {t}[{L}]: {m}{n}");
let mut root = Root::builder();
let console = ConsoleAppender::builder()
.encoder(Box::new(PatternEncoder::new(pattern)))
.target(Target::Stderr)
.build();
builder = builder.appender(
Appender::builder()
.filter(Box::new(ThresholdFilter::new(
self.console_level.unwrap_or(LevelFilter::Debug),
)))
.build("console", Box::new(console)),
);
root = root.appender("console");
if let Some(filename) = self.filename {
let filepath = self.filepath.unwrap_or("logs");
std::fs::create_dir_all(filepath)?;
let file = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new(pattern)))
.append(false)
.build(format!(
"{}/{}-{}.log",
filepath,
filename,
Local::now().format("%Y-%m-%d %H_%M_%S")
))?;
builder = builder.appender(
Appender::builder()
.filter(Box::new(ThresholdFilter::new(
self.file_level.unwrap_or(LevelFilter::Debug),
)))
.build("file", Box::new(file)),
);
root = root.appender("file");
}
let config =
builder.build(root.build(self.root_level.unwrap_or(LevelFilter::Trace)))?;
let _handle = log4rs::init_config(config)?;
Ok(())
}
}
}