很多人习惯于python,go等语言基础工具库的简单易用;在使用rust时,可能感觉比较麻烦,类似日志库这样的基础性工具库。tklog提供用法上,非常类似python等Logger的日志库用法,用法简洁;基于rust的高效性和一些优化策略,tklog的性能非常好,在压测中,可以达到 3-4 µs/op (微妙/次),这个效率比go最高的性能时候都高一些;在相同的环境下,对go进行无格式日志输出压测,可以达到 3-4µs/op,如果是格式化日志输出,则为4µs/op以上。(可以参考《 高性能日志库go-logger v2.0.3》中对各日志库的压测数据)。
在异步场景中,tklog提供了对应的方法,支持异步调用。异步方法最大的好处并非在性能上,而是它不会阻塞所在线程。但是由于 tklog的常规日志方法默认使用延迟策略,实际上也不会阻塞所在线程,或者准确说影响非常小,可以忽略不计。所以,异步场景一般也可以直接使用常规日志打印方法。
- [dependencies]
- tklog = "0.0.2" #使用时的实际最新版本;当前0.0.2版本
最简单常用的方法:直接调用
- use tklog::{trace,debug, error, fatal, info,warn}
- fn testlog() {
- trace!("trace>>>>", "aaaaaaaaa", 1, 2, 3, 4);
- debug!("debug>>>>", "bbbbbbbbb", 1, 2, 3, 5);
- info!("info>>>>", "ccccccccc", 1, 2, 3, 5);
- warn!("warn>>>>", "dddddddddd", 1, 2, 3, 6);
- error!("error>>>>", "eeeeeeee", 1, 2, 3, 7);
- fatal!("fatal>>>>", "ffffffff", 1, 2, 3, 8);
- }
说明:默认打开控制台日志,没有写日志文件。打印结果:
- [TRACE] 2024-05-26 11:47:22 testlog.rs 27:trace>>>>,aaaaaaaaa,1,2,3,4
- [DEBUG] 2024-05-26 11:47:22 testlog.rs 28:debug>>>>,bbbbbbbbb,1,2,3,5
- [INFO] 2024-05-26 11:47:22 testlog.rs 29:info>>>>,ccccccccc,1,2,3,5
- [WARN] 2024-05-26 11:47:22 testlog.rs 30:warn>>>>,dddddddddd,1,2,3,6
- [ERROR] 2024-05-26 11:47:22 testlog.rs 31:error>>>>,eeeeeeee,1,2,3,7
- [FATAL] 2024-05-26 11:47:22 testlog.rs 32:fatal>>>>,ffffffff,1,2,3,8
说明:直接调用 debug!等宏进行打印,默认调用全局静态LOG对象。LOG对象支持初始化。
- use tklog::{
- sync::Logger,
- LEVEL, LOG,
- Format,MODE,
- };
-
- fn log_init() {
- LOG.set_console(true) //设置控制台日志
- .set_level(LEVEL::Info) //日志级别,默认Debug
- .set_format(Format::LevelFlag | Format::Time | Format::ShortFileName) //结构化日志,定义输出的日志信息
- .set_cutmode_by_size("tklogsize.txt", 1<<20, 10, true) //日志文件切割模式为文件大小,每1M文件切分一次,保留10个备份日志文件,并压缩备份日志
- .set_formatter("{level}{time} {file}:{message}\n") //自定义日志输出格式。默认:{level}{time} {file}:{message}
- }
-
- fn testlog() {
- log_init() //调用初始化方法
- trace!("trace>>>>", "aaaaaaaaa", 1, 2, 3, 4); //track日志级别小于设置的LEVEL::Info ,故无输出
- info!("info>>>>", "ccccccccc", 1, 2, 3, 5);
- }
以上是全局单实例打印的示例。tklog支持自定义多实例打印。多实例一般应用在系统要求不同打印结构的场景中。
- use tklog::{
- debugs, errors, fatals, infos,
- sync::Logger,
- LEVEL, LOG,
- traces, warns, Format, MODE,
- };
- fn testmutlilog() {
- let mut log = Logger::new();
- log.set_console(true)
- .set_level(LEVEL::Debug) //定义日志级别为Debug
- .set_cutmode_by_time("tklogs.log", MODE::DAY, 10, true) //分割日志文件的方式为按天分割,保留最多10个备份,并压缩备份文件
- .set_formatter("{message} | {time} {file}{level}\n") //自定义日志结构信息的输入顺序与附加内容
-
- let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
- let log = logger.borrow_mut();
- traces!(log, "traces>>>>", "AAAAAAAAA", 1, 2, 3, 4);
- debugs!(log, "debugs>>>>", "BBBBBBBBB", 1, 2, 3, 5);
- infos!(log, "infos>>>>", "CCCCCCCCC", 1, 2, 3, 5);
- warns!(log, "warns>>>>", "DDDDDDDDDD", 1, 2, 3, 6);
- errors!(log, "errors>>>>", "EEEEEEEE", 1, 2, 3, 7);
- fatals!(log, "fatals>>>>", "FFFFFFFF", 1, 2, 3, 8);
-
- thread::sleep(Duration::from_secs(1))
- }
执行结果:
- debugs>>>>,BBBBBBBBB,1,2,3,5 | 2024-05-26 14:13:25 testlog.rs 70[DEBUG]
- infos>>>>,CCCCCCCCC,1,2,3,5 | 2024-05-26 14:13:25 testlog.rs 71[INFO]
- warns>>>>,DDDDDDDDDD,1,2,3,6 | 2024-05-26 14:13:25 testlog.rs 72[WARN]
- errors>>>>,EEEEEEEE,1,2,3,7 | 2024-05-26 14:13:25 testlog.rs 73[ERROR]
- fatals>>>>,FFFFFFFF,1,2,3,8 | 2024-05-26 14:13:25 testlog.rs 74[FATAL]
注意:以上输入结构化信息由 "{message} | {time} {file}{level}
\n"
formatter决定。formatter中除了关键标识 {message}
{time}
{file}
{level}
外,其他内容原样输出,如 | , 空格,换行 等。
示例:
LOG.set_level(LEVEL::Info) //日志级别,设置为Info
调用 .set_console(bool) 函数
LOG.set_console(false) // false表示不打印控制台日志。默认为true
LOG.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName)
默认:"{level}{time} {file}:{message} \n"
LOG.set_formatter("{message} | {time} {file}{level}\n"); //自定义日志结构信息的输入顺序与附加内容
说明:除了关键标识 {message}
{time}
{file}
{level}
外,其他内容原样输出,如 | , 空格,换行 等。
时间标识:MODE::HOUR,MODE::DAY,MODE::MONTH
分别是:小时,天,月份
调用 .set_cutmode_by_time() 函数,参数:
示例
- let mut log = Logger::new();
- log.set_cutmode_by_time("/usr/local/tklogs.log", MODE::DAY, 0, false)
说明:备份文件路径为: /usr/local/tklogs.log ,时间模式为:按天备份,参数0表示不限制备份文件数,false表示不压缩备份的日志文件
备份的文件格式:
调用 .set_cutmode_by_size() 函数,参数:
示例
- let mut log = Logger::new();
- log.set_cutmode_by_time("tklogs.log", 100<<20, 10, true)
说明:备份文件路径为:tklogs.log ,按100M大小备份文件,参数10表示只保留最新10个备份文件,true表示压缩备份的日志文件
备份的文件格式:
tklog提供常规日志打印 方法为:
全局单例异步调用
- use tklog::{
- async_debug, async_error, async_fatal, async_info, async_trace, async_warn, LEVEL, Format, ASYNC_LOG
- };
-
- async fn async_log_init() {
- // 全局单例设置参数
- ASYNC_LOG
- .set_console(false) //控制台
- .set_level(LEVEL::Trace) //日志级别
- .set_format(Format::LevelFlag | Format::Time | Format::ShortFileName) //结构化日志,定义输出的日志信息
- .set_cutmode_by_size("tklog_async.txt", 10000, 10, false).await; //日志文件切割模式为文件大小,每10000字节切割一次,保留10个备份日志文件
-
- #[tokio::test]
- async fn testlog() {
- async_log_init().await; //参数设置
- async_trace!("trace>>>>", "aaaaaaa", 1, 2, 3);
- async_debug!("debug>>>>", "aaaaaaa", 1, 2, 3);
- async_info!("info>>>>", "bbbbbbbbb", 1, 2, 3);
- async_warn!("warn>>>>", "cccccccccc", 1, 2, 3);
- async_error!("error>>>>", "ddddddddddddd", 1, 2, 3);
- async_fatal("fatal>>>>", "eeeeeeeeeeeeee", 1, 2, 3);
- tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
- }
输出结果:
- [TRACE] 20:03:32 testasynclog.rs 20:trace>>>>,aaaaaaa,1,2,3
- [DEBUG] 20:03:32 testasynclog.rs 21:debug>>>>,aaaaaaa,1,2,3
- [INFO] 20:03:32 testasynclog.rs 22:info>>>>,bbbbbbbbb,1,2,3
- [WARN] 20:03:32 testasynclog.rs 23:warn>>>>,cccccccccc,1,2,3
- [ERROR] 20:03:32 testasynclog.rs 24:error>>>>,ddddddddddddd,1,2,3
- [FATAL] 20:03:32 testasynclog.rs 25:fatal>>>>,eeeeeeeeeeeeee,1,2,3
多实例异步
- use std::sync::Arc;
-
- use tklog::{
- async_debugs, async_errors, async_fatals, async_infos, async_traces, async_warns, LEVEL, Format, ASYNC_LOG, MODE
- };
- #[tokio::test]
- async fn testmultilogs() {
- //新建 Async::Logger 对象
- let mut log = tklog::Async::Logger::new();
- log.set_console(false)
- .set_level(LEVEL::Debug)
- .set_cutmode_by_time("tklogasync.log", MODE::DAY, 10, true)
- .await
- .set_formatter("{message} | {time} {file}{level}");
-
- let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
- let log = logger.borrow_mut();
- async_traces!(log, "async_traces>>>>", "AAAAAAAAAA", 1, 2, 3);
- async_debugs!(log, "async_debugs>>>>", "BBBBBBBBBB", 1, 2, 3);
- async_infos!(log, "async_infos>>>>", "CCCCCCCCCC", 1, 2, 3);
- async_warns!(log, "async_warns>>>>", "DDDDDDDDDD", 1, 2, 3);
- async_errors!(log, "async_errors>>>>", "EEEEEEEEEEE", 1, 2, 3);
- async_fatals!(log, "async_fatals>>>>", "FFFFFFFFFFFF", 1, 2, 3);
- tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
- }
输出结果:
- async_debugs>>>>,BBBBBBBBBB,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 45[DEBUG]
- async_infos>>>>,CCCCCCCCCC,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 46[INFO]
- async_warns>>>>,DDDDDDDDDD,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 47[WARN]
- async_errors>>>>,EEEEEEEEEEE,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 48[ERROR]
- async_fatals>>>>,FFFFFFFFFFFF,1,2,3 | 2024-05-26 20:10:24 testasynclog.rs 49[FATAL]
- test_debug time: [3.3747 µs 3.4599 µs 3.5367 µs]
- change: [-69.185% -68.009% -66.664%] (p = 0.00 < 0.05)
- Performance has improved.
- Found 9 outliers among 100 measurements (9.00%)
- 6 (6.00%) high mild
- 3 (3.00%) high severe
说明:时间范围给出了三个数据点,分别代表了测试执行时间的最小值(3.3747微秒)、平均值附近的值(3.4599微秒)、以及最大值(3.5367微秒)
- test_debug time: [3.8377 µs 3.8881 µs 3.9408 µs]
- change: [-66.044% -65.200% -64.363%] (p = 0.00 < 0.05)
- Performance has improved.
- Found 2 outliers among 100 measurements (2.00%)
- 2 (2.00%) high mild
说明:测试运行的时间范围是从3.8377微秒到3.9408微秒,覆盖了一个大概的分布情况,其中3.8881微秒大约是这段时间内的平均或中位数执行时间
结论:日志打印函数性能:3 µs/op — 4 µs/op (微妙/次)