use std::fmt::Display;
use ftlog::{
appender::{file::Period, FileAppender},
info, FtLogFormat, LoggerGuard,
};
use log::{Level, LevelFilter, Record};
use time::Duration;
fn init() -> LoggerGuard {
struct MyFormatter;
impl FtLogFormat for MyFormatter {
fn msg(&self, record: &Record) -> Box<dyn Send + Sync + std::fmt::Display> {
Box::new(Msg {
level: record.level(),
thread: std::thread::current().name().map(|n| n.to_string()),
file: record.file_static(),
line: record.line(),
args: format!("{}", record.args()),
module_path: record.module_path_static(),
})
}
}
struct Msg {
level: Level,
thread: Option<String>,
file: Option<&'static str>,
line: Option<u32>,
args: String,
module_path: Option<&'static str>,
}
impl Display for Msg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!(
"{}@{}||{}:{}[{}] {}",
self.thread.as_ref().map(|x| x.as_str()).unwrap_or(""),
self.module_path.unwrap_or(""),
self.file.unwrap_or(""),
self.line.unwrap_or(0),
self.level,
self.args
))
}
}
let time_format = time::format_description::parse_owned::<1>(
"[year]/[month]/[day] [hour]:[minute]:[second].[subsecond digits:6]",
)
.unwrap();
ftlog::Builder::new()
.format(MyFormatter)
.time_format(time_format)
.max_log_level(LevelFilter::Info)
.root(
FileAppender::builder()
.path("./current.log")
.rotate(Period::Day)
.expire(Duration::days(7))
.build(),
)
.filter("ftlog::appender", "ftlog-appender", LevelFilter::Error)
.filter("ftlog", None, LevelFilter::Trace)
.filter("ftlog::appender::file", "ftlog", None)
.appender("ftlog-appender", FileAppender::new("ftlog-appender.log"))
.appender("ftlog", FileAppender::rotate("ftlog.log", Period::Day))
.try_init()
.expect("logger build or set failed")
}
fn main() {
let _guard = init();
info!("Hello, world!");
for i in 0..120 {
info!("running {}!", i);
info!(limit=3000i64; "limit running{} !", i);
std::thread::sleep(std::time::Duration::from_secs(1));
}
}