pub use crate::logger_handle::LogSpecSubscriber;
use crate::{
logger::{create_specfile_watcher, synchronize_subscriber_with_specfile},
writers::{FileLogWriterBuilder, FileLogWriterHandle},
};
use crate::{FlexiLoggerError, LogSpecification};
use notify_debouncer_mini::{notify::RecommendedWatcher, Debouncer};
use std::path::{Path, PathBuf};
use tracing_subscriber::{EnvFilter, FmtSubscriber};
#[cfg(feature = "specfile_without_notification")]
pub fn subscribe_to_specfile<P: AsRef<Path>>(
specfile: P,
reloader: Box<dyn Fn(LogSpecification) + Send + Sync>,
initial_logspec: LogSpecification,
) -> Result<Option<Debouncer<RecommendedWatcher>>, FlexiLoggerError> {
let specfile = specfile.as_ref();
let mut subscriber = TraceLogSpecSubscriber::new(reloader, initial_logspec);
synchronize_subscriber_with_specfile(&mut subscriber, specfile)?;
if cfg!(feature = "specfile") {
Ok(Some(create_specfile_watcher(specfile, subscriber)?))
} else {
Ok(None)
}
}
#[cfg(feature = "specfile_without_notification")]
struct TraceLogSpecSubscriber {
initial_logspec: LogSpecification,
update: Box<(dyn Fn(LogSpecification) + Send + Sync)>,
}
impl TraceLogSpecSubscriber {
#[must_use]
pub fn new(
update: Box<(dyn Fn(LogSpecification) + Send + Sync)>,
initial_logspec: LogSpecification,
) -> Self {
Self {
initial_logspec,
update,
}
}
}
#[cfg(feature = "specfile_without_notification")]
impl LogSpecSubscriber for TraceLogSpecSubscriber {
fn set_new_spec(&mut self, logspec: LogSpecification) -> Result<(), FlexiLoggerError> {
(self.update)(logspec);
Ok(())
}
fn initial_spec(&self) -> Result<LogSpecification, FlexiLoggerError> {
Ok(self.initial_logspec.clone())
}
}
pub struct SpecFileNotifier(Option<Debouncer<RecommendedWatcher>>);
pub fn setup_tracing(
initial_logspec: LogSpecification,
o_specfile: Option<&PathBuf>,
flwb: FileLogWriterBuilder,
) -> Result<(FileLogWriterHandle, SpecFileNotifier), FlexiLoggerError> {
struct LogSpecAsFilter(pub LogSpecification);
impl From<LogSpecAsFilter> for EnvFilter {
fn from(wrapped_logspec: LogSpecAsFilter) -> Self {
Self::new(wrapped_logspec.0.to_string())
}
}
let (file_writer, fw_handle) = flwb.try_build_with_handle()?;
let subscriber_builder = FmtSubscriber::builder()
.with_writer(move || file_writer.clone())
.with_env_filter(LogSpecAsFilter(initial_logspec.clone()))
.with_filter_reloading();
let spec_file_notifier = SpecFileNotifier(match o_specfile {
Some(specfile) => {
let reload_handle = Box::new(subscriber_builder.reload_handle());
subscribe_to_specfile(
specfile,
Box::new(move |logspec| {
{ reload_handle.reload(LogSpecAsFilter(logspec)) }.unwrap();
}),
initial_logspec,
)?
}
None => None,
});
tracing::subscriber::set_global_default(subscriber_builder.finish())?;
Ok((fw_handle, spec_file_notifier))
}