use std::{fs, io, path};
use flexi_logger::{Cleanup, Criterion, DeferredNow, Duplicate, FileSpec, FlexiLoggerError, Logger, LoggerHandle, Naming};
use log::{info, Record};
const CURRENT_PKG: &str = env!("CARGO_PKG_NAME");
#[allow(dead_code)]
pub fn init(log_dir: &str, log_file: &str, env_cargo_crate_name: &str) -> Result<LoggerHandle, FlexiLoggerError> {
let log_dir_path = path::absolute(log_dir)?;
if !log_dir_path.exists() {
fs::create_dir_all(log_dir_path.clone())?;
}
let log_dir = log_dir_path
.as_path()
.to_str()
.ok_or(io::Error::new(io::ErrorKind::InvalidInput, "error parse absolute path of log dir"))?;
let logger = if cfg!(debug_assertions) {
Logger::try_with_env_or_str(format!("info,{env_cargo_crate_name}=debug"))?
} else {
Logger::try_with_env_or_str(format!("error,{env_cargo_crate_name}=info"))?
};
let log = logger
.log_to_file(FileSpec::default().directory(log_dir).basename(log_file).suffix(""))
.duplicate_to_stdout(Duplicate::All)
.rotate(
Criterion::Size(10_000_000), Naming::Timestamps,
Cleanup::KeepLogFiles(3), )
.append()
.format(my_format)
.create_symlink(format!("{}/{}", log_dir, log_file))
.start();
let symlink_path = log_dir_path.join(log_file);
let symlink_path = symlink_path.to_str().ok_or(io::Error::new(io::ErrorKind::InvalidData, "cannot parse"))?;
info!("current package is {CURRENT_PKG}, log is output to {}", symlink_path);
log
}
fn my_format(w: &mut dyn std::io::Write, now: &mut DeferredNow, record: &Record) -> Result<(), std::io::Error> {
write!(
w,
"{} [{}] [{}:{}] {}",
now.format("%Y-%m-%d %H:%M:%S"),
record.level(),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
&record.args()
)
}