4 个版本
0.5.3 | 2023 年 12 月 17 日 |
---|---|
0.5.2 | 2023 年 12 月 17 日 |
0.5.1 | 2023 年 12 月 17 日 |
0.5.0 | 2023 年 12 月 17 日 |
#219 in 调试
56KB
673 行
the_logger
该包旨在使日志记录变得容易,只需两行即可创建日志文件。但它不仅易于使用和启动,而且还可以进行到微秒级的定制。
此日志系统基于 std 库将内容写入文件,并使用 tokio 仅用于全局锁定文件写入器,lazy_static 保持文件写入器的静态引用,chrono 用于获取日志的日期和时间。可选的(将在未来版本中提供),您可以通过创建一个 json 文件并在此设置配置来配置其设置。
特性
- 非常容易调用和使用。
- 高度可定制,个性化功能不断逐渐增加。
- 轻量级,默认功能下只有 3 个依赖项(lazy_static、tokio 和 chrono)。
- 在代码的任何位置都可以访问,无需通过引用传递。
- 启动时和运行时均可配置参数。
如何使用
如前所述,基本用法非常简单,默认设置下无需配置即可进行日志记录。调用记录器需要一个异步函数
use the_logger::{log_warning, TheLogger};
async fn init_logger(thread_id: u8) {
let logger: &TheLogger = TheLogger::instance();
log_warning!(logger, "This is a warning emitted by thread {}", thread_id);
}
如上例所示,仅需要两行代码即可设置记录器和记录消息。执行日志记录有多种方式,但最简洁的方式是通过宏调用。另一种方法是
use the_logger::TheLogger;
async fn init_logger(thread_id: u8) {
TheLogger::instance()
.warning().await
.log_in_file(
(file!(), line!(), column!()
), "This is another logging example").await;
}
后一种方法将行数减少到 1,但代价是调用变得非常冗长且不太直观,失去了此包的目的。
如第一个示例所示,log_X!() 宏具有对 format!() 宏的内建支持,无需分配额外变量来构建消息。宏的第一个参数需要是记录器元素,其余参数可以使用内建字符串格式化器使用,支持所有 format!() 宏功能
use the_logger::{log_warning, TheLogger};
async fn init_logger(thread_id: u8) {
let logger: &TheLogger = TheLogger::instance();
// This log...
log_warning!(logger, "This is a log by thread {}", thread_id);
// ...is equivalent content-wise to this log
let msg = format!("This is a log by thread {}", thread_id);
log_warning!(logger, msg);
}
使用此记录器的两种主要方法:通过引用传递实例,或在任何您想调用实例的地方
use the_logger::{log_info, TheLogger};
async fn parent_function() {
let logger: &TheLogger = TheLogger::instance();
child_function_one(logger).await;
child_function_two();
}
async fn child_function_one(logger: &TheLogger) {
log_info!(
logger,
"This will trigger an Informational log by passing the logger instance as reference"
);
}
async fn child_function_two() {
let logger: &TheLogger = TheLogger::instance();
log_info!(
logger,
"This will trigger an Informational log by calling an instance of the logger without parameters"
);
}
这是由于使用了前面提到的tokio的RwLock功能。此方法决定避免在写入日志文件时出现不一致和错误。这样,无论有多少个线程在运行,_logger crate都将确保日志行一次写入一个,并且按照它们被调用的顺序写入。
日志文件
所有生成的文件都将放在使用此crate的项目中,位于logs/
文件夹中,名称为:"Log <year>-<month>-<day>.log"
在未来的版本中,您将能够配置名称(日期始终存在以更好地组织文件),保存路径,文件格式,并且您还可以删除超过可配置天数的老文件。
日志级别
有7个日志级别,它们并非都是级别,而是类别。这些是
- 详细
- 信息
- 错误
- 警告
- 调试
- 跟踪
- 严重
每个都可能在不同的情况下在您的代码中发挥作用,并且它们都存在供您按需使用。
要调用每个级别,您可以简单地使用定义的宏调用
use the_logger::TheLogger;
use the_logger::{log, log_info, log_error, log_warning, log_debug, log_trace, log_critical};
async fn init_logger(thread_id: u8) {
let logger: &TheLogger = TheLogger::instance();
log!(logger, "This call will trigger a Verbose log");
log_info!(logger, "This call will trigger an Informational log");
log_error!(logger, "This call will trigger an Error log");
log_warning!(logger, "This call will trigger a Warning log");
log_debug!(logger, "This call will trigger a Debug log");
log_trace!(logger, "This call will trigger a Trace log");
log_critical!(logger, "This call will trigger a Critical log");
}
配置
如前所述,此记录器非常可定制。您可以选择显示或隐藏几乎所有的元素
- 日期中的年份
- 日期中的月份
- 日期中的日期
- 时间中的小时
- 时间中的分钟
- 时间中的秒
- 时间中的毫秒
- 时间中的微秒
- 日志级别
- 日志位置(文件、行和列)
默认配置是显示上述所有元素,除了文件位置选项中的列。
您还可以配置位置和内容文本的最大长度。默认情况下,位置文本内容限制为60个字符,日志内容本身限制为300。
有两种配置此记录器的方法:在启动时和在运行时(将来将通过json文件添加配置)。要在启动时进行配置
use the_logger::{TheLogger, TheLoggerConfig};
async fn config_logger() {
let logger_config = TheLoggerConfig::default()
.hide_millisecs() // This will hide both the milliseconds and the microseconds
.hide_level() // This will hide the log level
.hide_location() // This will hide the file name, line and column
.location_content_length(100) // This will set the maximum location content text length to 100
.log_content_length(1000); // This will set the maximum log content text length to 1000
// Feel free to explore the documentation for more configuration options
let logger: &TheLogger = TheLogger::instance().config_logger(logger_config).await;
// The logger is now configured with the options set above
}
此配置方法仅建议在启动时使用,因为将TheLoggerConfig结构实例发送到.config_logger()
将覆盖当前配置的内容。对于运行时配置,有更有效的方法
use the_logger::{TheLogger, TheLoggerConfig};
async fn config_logger() {
// Logger instanced at start
let logger: &TheLogger = TheLogger::instance();
// Logger configured on the go
logger.hide_millisecs().await
.hide_level().await
.hide_location().await
.location_content_length(100).await
.log_content_length(1000).await;
// The configuration applied is the same as in the example above
}
日志内容示例
在以下示例中,除了位置内容长度设置为20个字符外,所有参数都保留为其默认值
2023-12-17 01:51:10.677106 [VERBOSE] @src\main.rs: 37 Log from thread 10
2023-12-17 01:51:10.677219 [WARNING] @src\main.rs: 37 Log from thread 17
2023-12-17 01:51:10.677343 [TRACE] @src\main.rs: 34 Log from thread 2
2023-12-17 01:51:10.702689 [CRITICAL] @src\main.rs: 28 Log from thread 0
2023-12-17 01:51:10.810655 [ERROR] @src\main.rs: 31 Log from thread 1
2023-12-17 01:51:11.367695 [INFO] @src\main.rs: 34 Log from thread 2
2023-12-17 01:51:11.538744 [DEBUG] @src\main.rs: 40 Log from thread 4
上一行日志是从大约350行由30个线程生成的日志中选出的。它们不是作为一组提取的,因为有些线程的睡眠时间比其他线程长,导致重复,因此我不得不选择其中的一些行。
以下是一个具有所有默认设置的日志行示例
2023-12-17 01:55:43.144632 [WARNING] @src\main.rs: 43 Log from thread 26
您可以看到隐藏某些元素以及配置位置内容长度和/或日志文本内容长度是有用的。为了提高可读性,我们将从现在开始使用20个字符的位置内容长度。现在,如果我们去掉日志级别,我们得到
2023-12-17 01:58:57.874425 @src\main.rs: 39 Log from thread 24
接下来,我们还将去掉毫秒,这将自动去掉微秒
2023-12-17 01:59:57 @src\main.rs: 37 Log from thread 2
但是,您可能需要按时间点跟踪您的程序或服务,此时日志日期可能没有用,只显示完整的时间戳、级别、位置和内容
02:01:52.509640 [CRITICAL] @src\main.rs: 32 Log from thread 0
您可能还有一个只有单个文件的小程序,错误信息非常详细,您可以配置它以获取
02:02:54.830615 [INFO] Log from thread 16
如果您只想获取日志级别和内容,因为您的错误信息已经包含了日期、时间和位置?您也可以这样做
[CRITICAL] Log from thread 14
最后,如果您只想隐藏所有内容,除了日志文本内容
Log from thread 25
唯一不能隐藏的参数是日志文本内容,因为它是日志的基本要求。
一些测试和结论
禁用元素记录到文件的能力带来了两个主要好处:由于需要写入文件的数据量减少,程序执行速度更快,与数据量相关的是文件大小。
为了测试文件大小,我在全配置(默认参数)和最小配置(仅日志文本内容)下运行了一个包含100个线程的程序,持续了2分钟,文件大小如下
- 全配置大约为1116KB
- 最小配置大约为177KB
这意味着通过仅保留所需的最小数据,文件大小减少了约84%。当然,这么多线程在写入文件时引入了瓶颈,因为它们必须等待锁释放,但大小比例在不同测试中保持不变。为了确保这一点,我将线程数量减少到30,时间相同,结果如下
- 全配置大约为792KB
- 最小配置大约为124KB
这给出了相同的全大小/最小大小比率。
未来功能和错误报告
正如我在整个readme文件中提到的,我有一些改进和功能的想法,包括
- 通过在一个文件夹中创建一个json文件来配置,尚未确定
- 配置日志文件路径
- 配置日志文件名
- 配置一些分隔符
- 配置日志级别封装 -> [ERROR] vs {ERROR} vs (ERROR) vs ERROR vs |ERROR|等
如果您有任何建议、错误报告或其他类型的反馈,我将在下一节中提供一些联系方式。
总结
这就是对这个crate的总结,希望您觉得它有用,如果您有任何问题、建议或报告,请随时联系我:
电子邮件:nacho.ponce25@gmail.com
Telegram:@tommyHellraiser
或在GitHub存储库中提交一个问题: https://github.com/tommyHellraiser/the_logger
感谢您阅读,祝您一切顺利!
依赖项
~3–4.5MB
~71K SLoC