use anyhow::{anyhow, Result};
use chrono::{NaiveDate, NaiveDateTime};
use log::LevelFilter;
use log4rs::{
append::console::ConsoleAppender,
append::file::FileAppender,
config::{Appender, Config as LogConfig, Root},
encode::pattern::PatternEncoder,
};
use num_traits::Num;
use std::env;
use std::fmt::Display;
use std::path::Path;
pub mod config;
pub mod formatter;
pub mod output;
pub use config::init_log_config;
pub use output::{log_as_date, log_as_datetime, log_as_json, log_as_number, log_as_string};
pub fn init_log(log_path: &Path, prefix: Option<&str>) -> Result<()> {
init_log_with_console(log_path, prefix, false)
}
pub fn init_log_with_console(
log_path: &Path,
prefix: Option<&str>,
enable_console: bool,
) -> Result<()> {
let env_var = match prefix {
Some(p) => format!("{}_DUMBO_LOG_LEVEL", p),
None => "DUMBO_LOG_LEVEL".to_string(),
};
let level = env::var(&env_var)
.unwrap_or_else(|_| "Info".to_string())
.parse::<LevelFilter>()
.unwrap_or(LevelFilter::Info);
let logfile = FileAppender::builder()
.encoder(Box::new(PatternEncoder::new("{d} {l} {t} - {m}{n}")))
.build(log_path)
.map_err(|e| anyhow!("创建日志文件失败: {}", e))?;
let mut config_builder =
LogConfig::builder().appender(Appender::builder().build("logfile", Box::new(logfile)));
if enable_console {
let console = ConsoleAppender::builder()
.encoder(Box::new(PatternEncoder::new("{d} {l} {t} - {m}{n}")))
.build();
config_builder =
config_builder.appender(Appender::builder().build("console", Box::new(console)));
}
let root_builder = if enable_console {
Root::builder()
.appender("logfile")
.appender("console")
.build(level)
} else {
Root::builder().appender("logfile").build(level)
};
let log_config = config_builder
.build(root_builder)
.map_err(|e| anyhow!("构建日志配置失败: {}", e))?;
log4rs::init_config(log_config).map_err(|e| anyhow!("初始化日志系统失败: {}", e))?;
Ok(())
}