4个版本 (2个破坏性更新)
0.3.1 | 2023年11月20日 |
---|---|
0.3.0 | 2023年11月20日 |
0.2.0 | 2023年11月15日 |
0.1.0 | 2023年11月11日 |
#279 in 调试
每月383次下载
21KB
248 行
带压缩的滚动日志文件
此库提供了LogFileInitializer
结构体,用于在日志目录内获取日志文件。它使用类似于上方轮盘图的滚动策略 🎡
初始化器包含字段directory
、filename
、max_n_old_files
和preferred_max_file_size_mib
。
以下所有条件都为真时,将对文件directory/file
应用滚动
- 文件已存在。
- 文件大小 >=
preferred_max_file_size_mib
(以MiB计)。 - 今天尚未进行滚动。
在滚动的情况下,文件将被压缩为GZIP格式并保存为directory/filename-YYYYMMDD.gz
,日期为今天的UTC日期。
如果应用了滚动并且旧文件数量超过max_n_old_files
,则最旧的文件将被删除。
重要的是要知道,滚动只发生在初始化时。 init
方法返回一个正常的File
。如果程序连续运行多日而不重启,则不会应用滚动。这有以下优点
- 写入时无需检查何时滚动,无开销。
- 实际滚动过程中不会出现延迟峰值。
- 整个运行日志(从开始到终止)都在一个文件中。
程序应该每隔几天重启一次,当系统更新后重启主机。但是,如果您希望在程序运行期间每隔固定天数进行滚动,则可以使用自己的类型,在该类型中,当滚动发生时,在内部调用init
方法,然后交换文件。
有关更多详细信息,请阅读 LogFileInitializer
结构体 及其 init
方法 的文档。
示例
我们将看到当使用以下初始化器字段值调用 init
方法 时会发生什么。
use logs_wheel::LogFileInitializer;
let log_file = LogFileInitializer {
directory: "logs",
filename: "test",
max_n_old_files: 2,
preferred_max_file_size_mib: 1,
}.init()?;
Ok::<(), std::io::Error>(())
该方法调用将始终在结束时返回文件 logs/test
。但我们将讨论其副作用。
第一次调用
第一次调用将在当前目录中创建目录 logs/
(因为我们指定了相对路径),并在其中创建文件 test
。
logs/
的内容
test
后续调用
如果我们再次在 2023-11-12(UTC 时间)调用该函数,并且文件 logs/test
的大小大于 1 MiB,则该文件将被压缩为 logs/test-20231112.gz
。
在截断(空文件)后,将返回文件 logs/test
。
logs/
的内容
test
test-20231112.gz
同一天调用
如果我们再次在同一天调用该函数,即使文件 logs/test
的大小大于 1 MiB,也不会有任何变化。
文件 logs/test
将以追加模式打开。
logs/
的内容
test
test-20231112.gz
晚些时候的调用
如果我们第二天再次调用该函数,并且文件 logs/test
的大小大于 1 MiB,则该文件将被压缩为 logs/test-20231113.gz
。
截断后,将返回文件 logs/test
。
logs/
的内容
test
test-20231113.gz
test-20231112.gz
超过旧文件数量的调用
现在,我们已经有 2 个旧文件,这意味着我们达到了限制 max_n_old_files
。如果我们第二天再次调用该函数,并且文件 logs/test
的大小大于 1 MiB,则该文件将被压缩为 logs/test-20231114.gz
。最旧的文件 test-20231112.gz
将被删除。
截断后,将返回文件 logs/test
。
logs/
的内容
test
test-20231114.gz
test-20231113.gz
跟踪订阅者
您可以使用此库与 tracing 生态系统一起使用!
以下是如何将返回的文件用作 tracing subscriber 的示例。
use logs_wheel::LogFileInitializer;
use std::sync::Mutex;
let log_file = LogFileInitializer {
directory: "logs",
filename: "test",
max_n_old_files: 2,
preferred_max_file_size_mib: 1,
}.init()?;
let writer = Mutex::new(log_file);
let subscriber = tracing_subscriber::fmt()
.with_writer(writer)
// … (other `SubscriberBuilder` methods)
.finish();
# Ok::<(), std::io::Error>(())
类似的项目
- tracing-appender:在程序运行时提供 RollingFileAppender,每隔固定时间滚动。但它不会压缩旧日志文件,也不会删除任何文件。《tt class="txt-plain">logs-wheel 可以作为替代方案使用。它还可以与 NonBlocking 结合使用,以实现非阻塞写入。
- rolling-file:在程序运行时提供每隔固定时间的滚动。不进行压缩。在滚动时必须重命名每个文件,因为它们是编号的。
依赖关系
~1MB
~18K SLoC