mod appender;
mod combine;
mod filter;
use thiserror::Error;
use uninode::UniNode;
use tracing::subscriber::SetGlobalDefaultError;
use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::fmt::Layer as FmtLayer;
use tracing_subscriber::layer::{Layer, SubscriberExt};
use tracing_subscriber::registry::Registry;
use self::appender::create_appender;
use self::combine::CombinedLayer;
use self::filter::{create_level_filter, create_target_filter, Filtered};
pub type DynLayer = Box<dyn Layer<Registry> + Send + Sync + 'static>;
#[derive(Error, Debug)]
pub enum LoggerError {
#[error(transparent)]
Tracing(#[from] SetGlobalDefaultError),
#[error("Not defined logger appender")]
NotDefineAppender,
#[error("Not define path option")]
InvalidOuputPath,
#[error("Unknown logger appender [{0}]")]
UnknownAppender(String),
}
pub fn create_fmt_layer(cfg: &UniNode) -> Result<DynLayer, LoggerError> {
let appender = create_appender(cfg)?;
let layer = FmtLayer::new()
.with_span_events(FmtSpan::CLOSE)
.with_ansi(true)
.with_target(true)
.with_level(true)
.with_thread_ids(true)
.with_writer(appender);
let level = cfg.find_str("level").unwrap_or("undefined");
let level_filter = create_level_filter(level);
match cfg.find("targets") {
Some(targets) => {
let target_filter = create_target_filter(targets);
let layer = Filtered::new(layer, target_filter);
let layer = Filtered::new(layer, level_filter);
Ok(Box::new(layer))
}
None => Ok(Box::new(Filtered::new(layer, level_filter))),
}
}
pub fn logger_init(cfg: &UniNode) -> Result<(), LoggerError> {
let mut layers = Vec::new();
let mut sub = Registry::default();
if cfg.is_array() {
for cfg in cfg.as_array().unwrap() {
let mut layer = create_fmt_layer(cfg)?;
layer.on_layer(&mut sub);
layers.push(layer);
}
} else {
let mut layer = create_fmt_layer(cfg)?;
layer.on_layer(&mut sub);
layers.push(layer);
}
let layer = CombinedLayer::new(layers);
let sub = sub.with(layer);
tracing::subscriber::set_global_default(sub).map_err(LoggerError::from)
}