pub use log::LevelFilter;
use fern;
use std::{env, io, path::PathBuf, str::FromStr};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum StdoutLog {
Off,
Plain,
Colored,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct LoggerConfig {
pub stdout: StdoutLog,
pub level_filter: LevelFilter,
pub log_file: Option<PathBuf>,
pub allow_env_override: bool,
}
impl Default for LoggerConfig {
fn default() -> LoggerConfig {
LoggerConfig {
stdout: StdoutLog::Colored,
level_filter: LevelFilter::Debug,
log_file: None,
allow_env_override: true,
}
}
}
pub fn start_logger(mut config: LoggerConfig) {
if config.allow_env_override {
env_var_override(&mut config);
}
let mut dispatch = basic_dispatch(config.level_filter);
match config.stdout {
StdoutLog::Plain => dispatch = dispatch.chain(io::stdout()),
StdoutLog::Colored => dispatch = dispatch.chain(colored_stdout()),
StdoutLog::Off => {}
}
if let Some(path) = config.log_file {
match fern::log_file(path) {
Ok(log_file) => dispatch = dispatch.chain(log_file),
Err(_) => eprintln!("Unable to access the log file, as such it will not be used"),
}
}
dispatch.apply().unwrap_or_else(|_| {
debug!("Global logger already set, default Amethyst logger will not be used")
});
}
fn env_var_override(config: &mut LoggerConfig) {
if let Ok(var) = env::var("AMETHYST_LOG_STDOUT") {
match var.to_lowercase().as_ref() {
"off" => config.stdout = StdoutLog::Off,
"plain" => config.stdout = StdoutLog::Plain,
"colored" => config.stdout = StdoutLog::Colored,
_ => {}
}
}
if let Ok(var) = env::var("AMETHYST_LOG_LEVEL_FILTER") {
if let Ok(lf) = LevelFilter::from_str(&var) {
config.level_filter = lf;
}
}
if let Ok(path) = env::var("AMETHYST_LOG_FILE_PATH") {
config.log_file = Some(PathBuf::from(path));
}
}
fn basic_dispatch(level_filter: LevelFilter) -> fern::Dispatch {
fern::Dispatch::new()
.level(level_filter)
.format(|out, message, record| {
out.finish(format_args!(
"[{level}][{target}] {message}",
level = record.level(),
target = record.target(),
message = message,
))
})
}
fn colored_stdout() -> fern::Dispatch {
let color_config = fern::colors::ColoredLevelConfig::new();
fern::Dispatch::new()
.chain(io::stdout())
.format(move |out, message, record| {
let color = color_config.get_color(&record.level());
out.finish(format_args!(
"{color}{message}{color_reset}",
color = format!("\x1B[{}m", color.to_fg_str()),
message = message,
color_reset = "\x1B[0m",
))
})
}