use std::{fs, io, path::Path};
use tracing::{
level_filters::LevelFilter,
subscriber::{set_default, DefaultGuard},
};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{fmt, layer::SubscriberExt};
pub struct LoggerBuilder {
output_file: Option<String>,
with_stdio: bool,
filter: LevelFilter,
}
impl Default for LoggerBuilder {
fn default() -> Self {
Self {
output_file: None,
with_stdio: true,
filter: LevelFilter::TRACE,
}
}
}
impl LoggerBuilder {
pub const fn new() -> Self {
LoggerBuilder {
output_file: None,
with_stdio: false,
filter: LevelFilter::TRACE,
}
}
pub fn test_name(mut self, test_name: &str) -> io::Result<Self> {
fs::create_dir_all("../logs")?;
self.output_file = Some(format!("../logs/{test_name}.log"));
Ok(self)
}
pub fn file<P: AsRef<Path>>(mut self, path: P) -> Self {
self.output_file = Some(path.as_ref().to_string_lossy().to_string());
self
}
pub fn stdio(mut self) -> Self {
self.with_stdio = true;
self
}
pub fn filter(mut self, filter: LevelFilter) -> Self {
self.filter = filter;
self
}
pub fn build(self) -> io::Result<(Option<WorkerGuard>, DefaultGuard)> {
let (worker_guard, default_guard) = match self.output_file {
Some(output_file) => {
let (file_writer, guard) =
tracing_appender::non_blocking(fs::File::create(output_file)?);
let thread_guard = match self.with_stdio {
true => set_default(
fmt::Subscriber::builder()
.compact()
.pretty()
.with_file(true)
.with_line_number(true)
.with_max_level(self.filter)
.with_target(false)
.finish()
.with(
fmt::Layer::default()
.compact()
.with_ansi(false)
.with_file(true)
.with_line_number(true)
.with_target(false)
.with_writer(file_writer),
),
),
false => set_default(
fmt::Subscriber::builder()
.compact()
.with_ansi(false)
.with_file(true)
.with_line_number(true)
.with_target(false)
.with_writer(file_writer)
.with_max_level(self.filter)
.finish(),
),
};
(Some(guard), thread_guard)
}
None => (
None,
set_default(
fmt::Subscriber::builder()
.compact()
.pretty()
.with_file(true)
.with_line_number(true)
.with_max_level(self.filter)
.with_target(false)
.finish(),
),
),
};
Ok((worker_guard, default_guard))
}
}