dango 0.1.1

Application skeleton
Documentation
//
// Copyright © 2022, Oleg Lelenkov
// License: BSD 3-Clause
// Authors: Oleg Lelenkov
//

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)
}