11 个版本
新 0.1.0 | 2024 年 8 月 24 日 |
---|---|
0.0.10 | 2024 年 8 月 15 日 |
0.0.8 | 2024 年 6 月 20 日 |
0.0.3 | 2024 年 5 月 30 日 |
#185 在 调试 中
每月 325 次下载
110KB
2K SLoC
tklog 是一个高性能的 Rust 结构化日志库 [中文]
tklog 具有易用性、效率丰富的功能集。它支持控制台日志记录、文件日志记录、同步和异步日志记录模式,以及像按时间或大小切片日志和压缩备份日志文件这样的高级功能。
功能
- 支持功能包括控制台日志记录、文件日志记录、同步日志记录、异步日志记录。
- 日志级别设置与标准库相同:跟踪、调试、信息、警告、错误、致命。
- 具有自定义格式的格式化输出,可以包括日志级别标志、格式化时间戳和日志文件位置。
- 按时间间隔切片日志文件:按小时、按天或按月。
- 按指定文件大小切片日志文件。
- 文件滚动机制,当达到最大备份次数时自动删除旧日志文件,以防止日志过多。
- 压缩归档的备份日志文件。
- 支持官方日志库标准 API
官方网站
简单使用说明
使用 tklog
[dependencies]
tklog = "0.0.10" # "0.0.x" current version
使用 tklog 最简单的方法是直接使用宏调用
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
对于初始化和自定义,tklog 提供了配置选项的方法,例如控制台输出、日志级别、格式化样式、切割策略和自定义格式化程序。
use tklog::{
sync::Logger,LEVEL, LOG,
Format, MODE,
};
fn log_init() {
LOG.set_console(true) // Enables console logging
.set_level(LEVEL::Info) // Sets the log level; default is Debug
.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName) // Defines structured log output with chosen details
.set_cutmode_by_size("tklogsize.txt", 1<<20, 10, true) // Cuts logs by file size (1 MB), keeps 10 backups, compresses backups
.set_formatter("{level}{time} {file}:{message}\n"); // Customizes log output format; default is "{level}{time} {file}:{message}"
}
这展示了全局、单例式日志设置。此外,tklog 还支持自定义的多实例日志配置,这对于需要在不同组件之间具有不同日志结构的系统非常有用。
多实例日志
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) //Set the log level to Debug
.set_cutmode_by_time("tklogs.log", MODE::DAY, 10, true) //Split log files daily, keep up to 10 backups, and compress them
.set_formatter("{message} | {time} {file}{level}\n"); //Customize the log structure's output format and additional content
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" 的格式。格式化器包括如 {message}、{time}、{file}、{level} 以及这些占位符之外任何额外的文本或分隔符。
详细使用指南
1. 日志级别:Trace < Debug < Info < Warn < Error < Fatal。
示例
LOG.set_level(LEVEL::Info) //Sets the log level to Info
2. 控制台日志:通过 .set_console(bool)
启用或禁用。
LOG.set_console(false) //Disables console logging (default is true)
3. 日志格式
Format::Nano : No formatting
Format::Date : Outputs date (e.g., 2024-05-26)
Format::Time : Outputs time to seconds (e.g., 14:13:25)
Format::Microseconds :Outputs time with microseconds (e.g., 18:09:17.462245)
Format::LongFileName :Full file path with line number (e.g., tests/testlog.rs 25)
Format::ShortFileName : Abbreviated file path with line number (e.g., testlog.rs 25)
Format::LevelFlag : Log level marker (e.g., [Debug]).
对于自定义格式
LOG.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName)
4. 自定义格式字符串
默认为 "{level}{time} {file}:{message}\n"。
-
{level}
:日志级别指示符,例如,[Debug]。 -
{time}
:记录的时间戳。 -
{file}
:文件名和行号。 -
{message}
:日志内容。
示例
LOG.set_formatter("{message} | {time} {file}{level}\n")
提醒:在 {level}
、{time}
、{file}
和 {message}
标签之外的文字将原样输出,包括分隔符、空格和换行符。
5. 基于时间的日志文件轮转
模式: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
,每日轮转,无备份限制,且不压缩每日日志。
备份命名约定
- 每日
tklogs_20240521.log
tklogs_20240522.log
- 每小时
tklogs_2024052110.log
tklogs_2024052211.log
- 每月
tklogs_202403.log
tklogs_202404.log
6. 基于大小的日志文件轮转
使用 .set_cutmode_by_size()
配置以下参数
- 文件路径
- 滚动大小
- 最大备份
- 压缩备份
示例
let mut log = Logger::new();
log.set_cutmode_by_size("tklogs.log", 100<<20, 10, true);
在此,tklogs.log
表示路径,每个文件滚动 100 MB,保留 10 个备份,并压缩它们。
备份文件命名约定
tklogs_1.log.gz
tklogs_2.log.gz
tklogs_3.log.gz
日志打印方法
-
全局单例
trace!
、debug!
、info!
、warn!
、error!
、fatal!
-
多个实例
traces!
、debugs!
、infos!
、warns!
、errors!
、fatals!
异步日志
-
全局单例异步
async_trace!
,async_debug!
,async_info!
,async_warn!
,async_error!
,async_fatal!
-
多个实例异步
async_traces!
,async_debugs!
,async_infos!
,async_warns!
,async_errors!
,async_fatals!
示例:全局异步使用
use tklog::{
async_debug, async_error, async_fatal, async_info, async_trace, async_warn, LEVEL, Format, ASYNC_LOG
};
async fn async_log_init() {
// Configure global singleton
ASYNC_LOG
.set_console(false) // Disable console output
.set_level(LEVEL::Trace) // Set log level to Trace
.set_format(Format::LevelFlag | Format::Time | Format::ShortFileName) // Define structured logging output
.set_cutmode_by_size("tklog_async.txt", 10000, 10, false) // Rotate log files by size, every 10,000 bytes, with 10 backups
.await;
}
#[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() {
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}\n");
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]
支持官方日志库标准 API
- tklog 实现了官方 Log 接口 API 的常规使用
- 实现官方日志库 API,用于异步场景
如何启用官方日志库 API:
tklog 通过调用 uselog()
函数启用官方日志的 API 支持
使用示例
use std::{thread, time::Duration};
use tklog::{Format, LEVEL, LOG};
fn test_synclog() {
//init LOG
LOG.set_console(true)
.set_level(LEVEL::Debug)
.set_cutmode_by_size("logsize.log", 10000, 10, true)
.uselog(); //Enable the official log library
log::trace!("trace>>>>{}{}{}{}{}", "aaaa", 1, 2, 3, 4);
log::debug!("debug>>>>{}{}",1,2);
log::info!("info log");
log::warn!("warn log");
log::error!("error log");
thread::sleep(Duration::from_secs(1))
}
在异步场景中启用日志库 API
use std::{thread, time::Duration};
use tklog::{Format, LEVEL, ASYNC_LOG};
async fn test_synclog() {
//init ASYNC LOG
ASYNC_LOG.set_console(false)
.set_cutmode_by_size("asynclogsize.log", 10000, 10, true).await
.uselog(); //Enable the official log library
log::trace!("trace async log>>>>{}{}{}{}{}", "aaaaaaaaa", 1, 2, 3, 4);
log::debug!("debug async log>>>>{}{}",1,2);
log::info!("info async log");
log::warn!("warn async log");
log::error!("error async log");
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
}
模块设置日志参数
- tklog 提供
set_option
和set_mod_option
来设置 Logger 对象的全局日志参数和指定模块的日志参数 - 在项目中,您可以使用全局 LOG 对象同时为多个 mod 设置日志参数
- 不同的 mod 可以设置不同的日志级别、日志格式、日志文件等
- ASYNC_LOG 的 mod 日志参数与 LOG 对象相同
set_option
示例:
tklog::LOG.set_option(LogOption{level:Some(LEVEL::Debug),console: Some(false),format:None,formatter:None,fileoption: Some(Box::new(FileTimeMode::new("day.log",tklog::MODE::DAY,0,true)))});
LogOption 指令
- level 日志级别
- format 日志格式
- formatter 用户定义的日志输出格式
- console 控制台日志设置
- fileoption 文件日志设置
set_mod_option
文件日志设置:
tklog::LOG.set_mod_option("testlog::module1",LogOption{level:Some(LEVEL::Debug),console: Some(false),format:None,formatter:None,fileoption: Some(Box::new(FileTimeMode::new("day.log", tklog::MODE::DAY, 0,true)))});
testlog::module1
是模块名称,您可以使用module_path!()
打印当前模块名称- 当在
testlog::module1
模块中使用 tklog 时,tklog 将使用 LogOption 对象
完整的 mod 示例
mod module1 {
use std::{thread, time::Duration};
use tklog::{handle::FileTimeMode, LogOption, LEVEL};
pub fn testmod() {
tklog::LOG.set_mod_option("testlog::module1", LogOption { level: Some(LEVEL::Debug), format: None, formatter: None, console: None, fileoption: Some(Box::new(FileTimeMode::new("module1.log", tklog::MODE::DAY, 0, true))) }).uselog();
tklog::debug!("module1,tklog api,LOG debug log>>", 123);
tklog::info!("module1,tklog api,LOG info log>>", 456);
log::debug!("module1,log api,debug log>>{}", 111);
log::info!("module1,log api,info log>>{}", 222);
thread::sleep(Duration::from_secs(1))
}
}
mod module2 {
use std::{thread, time::Duration};
use tklog::{handle::FileTimeMode, LogOption, LEVEL};
pub fn testmod() {
tklog::LOG.set_mod_option("testlog::module2", LogOption { level: Some(LEVEL::Info), format: None, formatter: None, console: None, fileoption: Some(Box::new(FileTimeMode::new("module2.log", tklog::MODE::DAY, 0, true))) }).uselog();
tklog::debug!("module2,tklog api,LOG debug log>>", 123);
tklog::info!("module2,tklog api,LOG info log>>", 456);
log::debug!("module2,log api,debug log>>{}", 111);
log::info!("module2,log api,info log>>{}", 222);
thread::sleep(Duration::from_secs(1))
}
}
#[test]
fn testmod2() {
module1::testmod();
module2::testmod();
}
执行结果
[DEBUG] 2024-06-19 10:54:07 testlog.rs 54:module1,tklog api,LOG debug log>>,123
[INFO] 2024-06-19 10:54:07 testlog.rs 55:module1,tklog api,LOG info log>>,456
[DEBUG] 2024-06-19 10:54:07 testlog.rs 56:module1,log api,debug log>>111
[INFO] 2024-06-19 10:54:07 testlog.rs 57:module1,log api,info log>>222
[INFO] 2024-06-19 10:54:08 testlog.rs 68:module2,tklog api,LOG info log>>,456
[INFO] 2024-06-19 10:54:08 testlog.rs 70:module2,log api,info log>>222
示例 2:异步日志
mod module3 {
use tklog::{handle::FileTimeMode, Format, LogOption, LEVEL};
pub async fn testmod() {
tklog::ASYNC_LOG.set_mod_option("testlog::module3", LogOption { level: Some(LEVEL::Debug), format: Some(Format::Date), formatter: None, console: None, fileoption: Some(Box::new(FileTimeMode::new("module3.log", tklog::MODE::DAY, 0, true))) }).await.uselog();
tklog::async_debug!("async module3,tklog api,LOG debug log>>", 123);
tklog::async_info!("async module3,tklog api,LOG info log>>", 456);
log::debug!("async module3,log api,debug log>>{}", 333);
log::info!("async module3,log api,info log>>{}", 444);
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}
mod module4 {
use tklog::{handle::FileTimeMode, Format, LogOption, LEVEL};
pub async fn testmod() {
tklog::ASYNC_LOG.set_mod_option("testlog::module4", LogOption { level: Some(LEVEL::Info), format: Some(Format::Date), formatter: None, console: None, fileoption: Some(Box::new(FileTimeMode::new("module4.log", tklog::MODE::DAY, 0, true))) }).await.uselog();
tklog::async_debug!("async module4,tklog api,LOG debug log>>", 123);
tklog::async_info!("async module4,tklog api,LOG info log>>", 456);
log::debug!("async module4,log api,debug log>>{}", 333);
log::info!("async module4,log api,info log>>{}", 444);
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}
#[tokio::test]
async fn testmod4() {
module3::testmod().await;
module4::testmod().await;
}
执行结果
[DEBUG] 2024-06-19 10:59:26 testlog.rs 85:async module3,tklog api,LOG debug log>>,123
[INFO] 2024-06-19 10:59:26 testlog.rs 86:async module3,tklog api,LOG info log>>,456
[DEBUG] 2024-06-19 10:59:26 testlog.rs 87:async module3,log api,debug log>>333
[INFO] 2024-06-19 10:59:26 testlog.rs 88:async module3,log api,info log>>444
[INFO] 2024-06-19 10:59:27 testlog.rs 98:async module4,tklog api,LOG info log>>,456
[INFO] 2024-06-19 10:59:27 testlog.rs 100:async module4,log api,info log>>444
tklog 支持多实例格式化格式!并支持异步格式!
示例:
#[test]
fn testformats() {
let mut log = Logger::new();
log.set_console(true)
.set_level(LEVEL::Debug)
.set_cutmode_by_time("tklogs.log", MODE::DAY, 10, true);
let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
let log = logger.borrow_mut();
let v = vec![1, 2, 3];
tklog::formats!(log, LEVEL::Debug, "Debug>>>{},{}>>>{:?}", 1, 2, v);
let v2 = vec!['a', 'b'];
tklog::formats!(log, LEVEL::Info, "Info>>>{},{}>>{:?}", 1, 2, v2);
tklog::formats!(log, LEVEL::Warn, "Warn>>>{},{}", 1, 2);
tklog::formats!(log, LEVEL::Error, "Error>>>{},{}", 1, 2);
tklog::formats!(log, LEVEL::Fatal, "Fatal>>>{},{}", 1, 2);
thread::sleep(Duration::from_secs(1))
}
执行结果
[DEBUG] 2024-06-06 15:54:07 testsynclog.rs 80:Debug>>>1,2>>>[1, 2, 3]
[INFO] 2024-06-06 15:54:07 testsynclog.rs 83:Info>>>1,2>>['a', 'b']
[WARN] 2024-06-06 15:54:07 testsynclog.rs 84:Warn>>>1,2
[ERROR] 2024-06-06 15:54:07 testsynclog.rs 85:Error>>>1,2
[FATAL] 2024-06-06 15:54:07 testsynclog.rs 86:Fatal>>>1,2
异步示例
#[tokio::test]
async fn testformats() {
let mut log = tklog::Async::Logger::new();
log.set_console(true)
.set_level(LEVEL::Debug)
.set_cutmode_by_time("tklogasyncs.log", MODE::DAY, 10, true)
.await;
let mut logger = Arc::clone(&Arc::new(Mutex::new(log)));
let log = logger.borrow_mut();
let v = vec![1, 2, 3];
tklog::async_formats!(log, LEVEL::Debug, "Debug>>>{},{}>>>{:?}", 1, 2, v);
let v2 = vec!['a', 'b'];
tklog::async_formats!(log, LEVEL::Info, "Info>>>{},{}>>{:?}", 1, 2, v2);
tklog::async_formats!(log, LEVEL::Warn, "Warn>>>{},{}", 1, 2);
tklog::async_formats!(log, LEVEL::Error, "Error>>>{},{}", 1, 2);
tklog::async_formats!(log, LEVEL::Fatal, "Fatal>>>{},{}", 1, 2);
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
执行结果
[DEBUG] 2024-06-06 16:09:26 testasynclog.rs 61:Debug>>>1,2>>>[1, 2, 3]
[INFO] 2024-06-06 16:09:26 testasynclog.rs 64:Info>>>1,2>>['a', 'b']
[WARN] 2024-06-06 16:09:26 testasynclog.rs 65:Warn>>>1,2
[ERROR] 2024-06-06 16:09:26 testasynclog.rs 66:Error>>>1,2
[FATAL] 2024-06-06 16:09:26 testasynclog.rs 67:Fatal>>>1,2
tklog 支持自定义日志处理函数。
tklog 允许通过 set_custom_handler()
添加外部自定义函数,以控制日志处理流程和逻辑。
示例
#[test]
fn test_custom() {
fn custom_handler(lc: &LogContext) -> bool {
println!("level >>>>>>>>>>>>>>>>>{:?}", lc.level);
println!("message >>>>>>>>>>>>>>>>>{:?}", lc.log_body);
println!("filename >>>>>>>>>>>>>>>>>{:?}", lc.filename);
println!("line >>>>>>>>>>>>>>>>>{:?}", lc.line);
println!("modname >>>>>>>>>>>>>>>>>{:?}", lc.modname);
if lc.level == LEVEL::Debug {
println!("{}", "debug now");
return false;
}
true
}
LOG.set_custom_handler(custom_handler);
debug!("000000000000000000");
info!("1111111111111111111");
thread::sleep(Duration::from_secs(1))
}
执行结果
---- test_custom stdout ----
level >>>>>>>>>>>>>>>>>Debug
message >>>>>>>>>>>>>>>>>"000000000000000000"
filename >>>>>>>>>>>>>>>>>"tests\\testsynclog.rs"
line >>>>>>>>>>>>>>>>>143
modname >>>>>>>>>>>>>>>>>"testsynclog"
debug now
level >>>>>>>>>>>>>>>>>Info
message >>>>>>>>>>>>>>>>>"1111111111111111111"
filename >>>>>>>>>>>>>>>>>"tests\\testsynclog.rs"
line >>>>>>>>>>>>>>>>>144
modname >>>>>>>>>>>>>>>>>"testsynclog"
[INFO] 2024-08-05 15:39:07 testsynclog.rs 144:1111111111111111111
说明
当函数 fn custom_handler(lc: &LogContext) -> bool
返回 true
时,tklog 调用 custom_handler
执行自定义函数,然后继续 tklog 的日志过程。当它返回 false
时,tklog 不继续其日志过程,并直接返回。如示例所示,当日志级别为 Debug
时,它返回 false
,所以 tklog 不打印 Debug
日志。
tklog
支持自定义日志多参数分隔符
tklog
允许使用 set_separator()
方法设置自定义分隔符
以下 Rust 代码演示了如何在 tklog
框架中配置和使用自定义分隔符来设置日志条目
#[test]
fn testlog() {
log_init();
trace!("trace>>>>", "aaaaaaaaa", 1, 2, 3, 4);
debug!("debug>>>>", "bbbbbbbbb", 1, 2, 3, 5);
LOG.set_separator("|");
info!("info>>>>", "ccccccccc", 1, 2, 3, 5);
warn!("warn>>>>", "dddddddddd", 1, 2, 3, 6);
LOG.set_separator(",");
error!("error>>>>", "eeeeeeee", 1, 2, 3, 7);
fatal!("fatal>>>>", "ffffffff", 1, 2, 3, 8);
thread::sleep(Duration::from_secs(1))
}
执行结果
测试日志函数生成的输出展示了设置不同分隔符对日志消息的影响
---- testlog stdout ----
[TRACE] 2024-08-15 14:14:19.289590 tests\testsynclog.rs 22:trace>>>>aaaaaaaaa1234
[DEBUG] 2024-08-15 14:14:19.289744 tests\testsynclog.rs 23:debug>>>>bbbbbbbbb1235
[INFO] 2024-08-15 14:14:19.289761 tests\testsynclog.rs 25:info>>>>|ccccccccc|1|2|3|5
[WARN] 2024-08-15 14:14:19.289774 tests\testsynclog.rs 26:warn>>>>|dddddddddd|1|2|3|6
[ERROR] 2024-08-15 14:14:19.289789 tests\testsynclog.rs 28:error>>>>,eeeeeeee,1,2,3,7
[FATAL] 2024-08-15 14:14:19.289802 tests\testsynclog.rs 29:fatal>>>>,ffffffff,1,2,3,8
tklog 支持为日志级别设置独立的日志格式参数
通过 set_level_option()
设置 tklog 的独立日志格式参数,以适应不同的日志级别
#[test]
fn testlog() {
// Set the log format for Info level to include Format::LevelFlag.
// Set the log format for Fatal level to include Format::LevelFlag and Format::Date.
LOG.set_level_option(LEVEL::Info, LevelOption { format: Some(Format::LevelFlag), formatter: None })
.set_level_option(LEVEL::Fatal, LevelOption { format: Some(Format::LevelFlag | Format::Date), formatter: None});
trace!("this is trace log");
debug!("this is debug log");
info!("this is info log");
warn!("this is warn log");
error!("this is error log");
fatal!("this is fatal log");
thread::sleep(Duration::from_secs(1))
}
执行结果
---- testlog stdout ----
[DEBUG] 2024-08-24 15:06:02 test_0100.rs 17:this is debug log
[INFO] this is info log
[WARN] 2024-08-24 15:06:02 test_0100.rs 19:this is warn log
[ERROR] 2024-08-24 15:06:02 test_0100.rs 20:this is error log
[FATAL] 2024-08-24 this is fatal log
基准测试
log_benchmark time: [2.9703 µs 2.9977 µs 3.0256 µs]
change: [-95.539% -95.413% -95.268%] (p = 0.00 < 0.05)
Performance has improved.
Found 9 outliers among 100 measurements (9.00%)
4 (4.00%) high mild
5 (5.00%) high severe
log_benchmark time: [2.9685 µs 3.0198 µs 3.0678 µs]
change: [-3.6839% -1.2170% +1.0120%] (p = 0.34 > 0.05)
No change in performance detected.
Found 7 outliers among 100 measurements (7.00%)
7 (7.00%) high mild
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
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
说明:时间范围提供了三个数据点,分别代表最小测试执行时间(2.9055 微秒)、接近平均值的值(2.9444 微秒 - 3.8881 微秒)和最大值(3.9408 微秒)。
结论:日志打印函数性能:2 µs/op - 3.9 µs/op(微秒/操作)
依赖项
~6–13MB
~142K SLoC