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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use std::fmt::Display;
use ftlog::{
appender::{file::Period, FileAppender},
info, FtLogFormat,
};
use log::{Level, LevelFilter, Record};
use time::Duration;
fn init() {
// Custom log style. Datetime format is fixed for performance
// A formatter defines how to build a message.
// Since Formatting message into string can slow down the log macro call,
// the idomatic way is to send required field as is to log thread, and build
// message in log thread.
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(),
})
}
}
// Store necessary field, define how to build into string with `Display` trait.
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
))
}
}
ftlog::Builder::new()
// use our own format
.format(MyFormatter)
// global max log level
.max_log_level(LevelFilter::Info)
// define root appender, pass None would write to stderr
.root(FileAppender::rotate_with_expire(
"./current.log",
Period::Day,
Duration::days(7),
))
// ---------- configure additional filter ----------
// write to "ftlog-appender" appender, with different level filter
.filter("ftlog::appender", "ftlog-appender", LevelFilter::Error)
// write to root appender, but with different level filter
.filter("ftlog", None, LevelFilter::Trace)
// write to "ftlog" appender, with default level filter
.filter("ftlog::appender::file", "ftlog", None)
// ---------- configure additional appender ----------
// new appender
.appender("ftlog-appender", FileAppender::new("ftlog-appender.log"))
// new appender, rotate to new file every Day
.appender("ftlog", FileAppender::rotate("ftlog.log", Period::Day))
.try_init()
.expect("logger build or set failed");
}
fn main() {
init();
info!("Hello, world!");
for i in 0..120 {
info!("running {}!", i);
info!(limit=3000; "limit running{} !", i);
std::thread::sleep(std::time::Duration::from_secs(1));
}
std::thread::sleep(std::time::Duration::from_secs(1));
}
/*
Output:
2022-11-11 13:53:13.933+08 0ms logger@ftlog||src/lib.rs:439[WARN] Logs with level more verbose than INFO will be ignored in `ftlog`
2022-11-11 13:53:13.933+08 0ms main@complex||examples/complex.rs:83[INFO] Hello, world!
2022-11-11 13:53:13.934+08 1ms main@complex||examples/complex.rs:85[INFO] running 0!
2022-11-11 13:53:13.934+08 3ms 0 main@complex||examples/complex.rs:86[INFO] limit running0 !
2022-11-11 13:53:13.934+08 3ms logger@ftlog::appender::file||src/appender/file.rs:255[INFO] Log file deleted: current-20221111T1352.log
2022-11-11 13:53:14.939+08 0ms main@complex||examples/complex.rs:85[INFO] running 1!
2022-11-11 13:53:15.939+08 0ms main@complex||examples/complex.rs:85[INFO] running 2!
2022-11-11 13:53:16.943+08 0ms main@complex||examples/complex.rs:85[INFO] running 3!
2022-11-11 13:53:16.943+08 0ms 2 main@complex||examples/complex.rs:86[INFO] limit running3 !
2022-11-11 13:53:17.945+08 0ms main@complex||examples/complex.rs:85[INFO] running 4!
2022-11-11 13:53:18.946+08 0ms main@complex||examples/complex.rs:85[INFO] running 5!
2022-11-11 13:53:19.951+08 0ms main@complex||examples/complex.rs:85[INFO] running 6!
2022-11-11 13:53:19.951+08 0ms 2 main@complex||examples/complex.rs:86[INFO] limit running6 !
2022-11-11 13:53:20.956+08 0ms main@complex||examples/complex.rs:85[INFO] running 7!
2022-11-11 13:53:21.961+08 0ms main@complex||examples/complex.rs:85[INFO] running 8!
2022-11-11 13:53:22.966+08 0ms main@complex||examples/complex.rs:85[INFO] running 9!
2022-11-11 13:53:22.966+08 4ms 2 main@complex||examples/complex.rs:86[INFO] limit running9 !
Default style example:
2022-04-11 15:08:19.847+08 0ms INFO main@src/main.rs:25 Hello, world!
2022-04-11 15:08:19.847+08 0ms INFO main@src/main.rs:28 running 0!
2022-04-11 15:08:19.847+08 0ms 0 INFO main@src/main.rs:29 limit running0 !
2022-04-11 15:08:20.849+08 0ms INFO main@src/main.rs:28 running 1!
2022-04-11 15:08:21.852+08 0ms INFO main@src/main.rs:28 running 2!
2022-04-11 15:08:22.857+08 0ms INFO main@src/main.rs:28 running 3!
2022-04-11 15:08:22.857+08 0ms 2 INFO main@src/main.rs:29 limit running3 !
2022-04-11 15:08:23.862+08 0ms INFO main@src/main.rs:28 running 4!
2022-04-11 15:08:24.864+08 0ms INFO main@src/main.rs:28 running 5!
*/