1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
pub mod config;
pub mod utils;

use std::str::FromStr;
use thiserror::Error;
use tracing::subscriber::set_global_default;
use tracing::Subscriber;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_appender::rolling::RollingFileAppender;
use tracing_subscriber::{fmt::Layer, layer::SubscriberExt, EnvFilter};

#[derive(Error, Debug)]
pub enum LoggerError {
    #[error("LoggerConfigurationError: [{message}]")]
    LoggerConfigurationError { message: String },
}

impl From<log::SetLoggerError> for LoggerError {
    fn from(error: log::SetLoggerError) -> Self {
        LoggerError::LoggerConfigurationError {
            message: format!("{}", error),
        }
    }
}

impl From<std::io::Error> for LoggerError {
    fn from(error: std::io::Error) -> Self {
        LoggerError::LoggerConfigurationError {
            message: format!("{}", error),
        }
    }
}

pub fn setup_logger(
    logger_config: &config::LoggerConfig,
) -> Result<Option<WorkerGuard>, LoggerError> {
    if logger_config.stdout_output.stdout_enabled || logger_config.file_output.file_output_enabled {
        let env_filter = EnvFilter::from_str(&logger_config.env_filter).map_err(|err| {
            LoggerError::LoggerConfigurationError {
                message: format!(
                    "Cannot parse the env_filter: [{}]. err: {}",
                    logger_config.env_filter, err
                ),
            }
        })?;

        let subscriber = tracing_subscriber::registry().with(env_filter);

        if logger_config.file_output.file_output_enabled {
            let file_appender = RollingFileAppender::new(
                logger_config
                    .file_output
                    .file_output_rotation
                    .to_tracing_appender_rotation(),
                logger_config.file_output.file_output_directory.to_owned(),
                logger_config.file_output.file_output_name_prefix.to_owned(),
            );

            let (non_blocking, guard) = tracing_appender::non_blocking(file_appender);

            let subscriber =
                subscriber.with(Layer::new().with_ansi(false).with_writer(non_blocking));

            if logger_config.stdout_output.stdout_enabled {
                let subscriber = subscriber.with(
                    Layer::new().with_ansi(logger_config.stdout_output.stdout_use_ansi_colors),
                );
                set_global_logger(subscriber)?;
                return Ok(Some(guard));
            } else {
                set_global_logger(subscriber)?;
                return Ok(Some(guard));
            }
        } else if logger_config.stdout_output.stdout_enabled {
            let subscriber = subscriber
                .with(Layer::new().with_ansi(logger_config.stdout_output.stdout_use_ansi_colors));
            set_global_logger(subscriber)?;
            return Ok(None);
        }
    }
    Ok(None)
}

fn set_global_logger<S>(subscriber: S) -> Result<(), LoggerError>
where
    S: Subscriber + Send + Sync + 'static,
{
    tracing_log::LogTracer::init().map_err(|err| LoggerError::LoggerConfigurationError {
        message: format!("Cannot start the logger LogTracer. err: {}", err),
    })?;
    set_global_default(subscriber).map_err(|err| LoggerError::LoggerConfigurationError {
        message: format!("Cannot start the logger. err: {}", err),
    })
}