flexi_logger
是一个功能强大且灵活的日志记录库,用于Rust语言的应用程序。它提供了丰富的配置选项和功能,适用于各种日志记录需求,从简单的控制台输出到复杂的文件日志管理。以下是对flexi_logger
的一些关键功能和特性的简介:
主要功能
info
、warn
、error
等),只记录满足级别要求的日志消息创建项目
cargo new rs_demo
Cargo.toml
[package] name = "rs_demo" version = "0.1.0" edition = "2021" [dependencies] log = "0.4" flexi_logger = "0.22" time = "0.3"
main.rs
use log::{trace, debug, info, warn, error}; use flexi_logger::{Duplicate, FileSpec, Logger, WriteMode, Criterion, Naming, Cleanup, detailed_format}; // 定义一个结构体 `Rectangle` struct Rectangle { width: u32, height: u32, } // 为 `Rectangle` 实现方法 impl Rectangle { // 关联函数(类似于静态方法) fn new(width: u32, height: u32) -> Rectangle { Rectangle { width, height } } // 实例方法 fn area(&self) -> u32 { self.width * self.height } // 实例方法 fn perimeter(&self) -> u32 { 2 * (self.width + self.height) } // 修改实例的方法 fn set_width(&mut self, width: u32) { self.width = width; } } fn main() { // 初始化日志记录,配置输出到文件,设置文件大小限制和滚动日志 let logger = Logger::try_with_str("trace") .unwrap() .log_to_file( FileSpec::default() .directory("logs") // 设置日志文件目录 .basename("app") // 设置日志文件前缀 .suffix("log") // 设置日志文件后缀 ) .rotate( Criterion::Size(10_000_000), // 设置日志文件大小限制为 10 MB Naming::Numbers, // 使用数字序号进行文件命名 Cleanup::KeepLogFiles(3), // 保留最近的 3 个日志文件 ) .write_mode(WriteMode::BufferAndFlush) // 设置日志写入模式 .duplicate_to_stderr(Duplicate::Warn) // 将警告级别的日志复制到标准错误输出 .format_for_files(detailed_format) // 使用详细格式,包含时间戳 .start() .unwrap(); // 记录不同级别的日志消息 trace!("This is a trace message."); debug!("This is a debug message."); info!("This is an info message."); warn!("This is a warning message."); error!("This is an error message."); // 使用关联函数创建一个 `Rectangle` let mut rect = Rectangle::new(30, 50); // 调用实例方法 info!("The area of the rectangle is {} square pixels.", rect.area()); info!("The perimeter of the rectangle is {} pixels.", rect.perimeter()); // 修改实例的字段 rect.set_width(40); info!("After resizing, the area of the rectangle is {} square pixels.", rect.area()); // 强制刷新日志缓冲区 logger.flush(); }
这里的配置包括:
在Rust的log库中,不同的日志宏可以记录不同级别的日志消息。这些日志级别分别是:
日志文件数据:
[2024-07-17 21:08:07.689886 +08:00] TRACE [rs_demo] src/main.rs:55: This is a trace message. [2024-07-17 21:08:07.691157 +08:00] DEBUG [rs_demo] src/main.rs:56: This is a debug message. [2024-07-17 21:08:07.691170 +08:00] INFO [rs_demo] src/main.rs:57: This is an info message. [2024-07-17 21:08:07.697314 +08:00] WARN [rs_demo] src/main.rs:58: This is a warning message. [2024-07-17 21:08:07.707785 +08:00] ERROR [rs_demo] src/main.rs:59: This is an error message. [2024-07-17 21:08:07.707804 +08:00] INFO [rs_demo] src/main.rs:65: The area of the rectangle is 1500 square pixels. [2024-07-17 21:08:07.707809 +08:00] INFO [rs_demo] src/main.rs:66: The perimeter of the rectangle is 160 pixels. [2024-07-17 21:08:07.707814 +08:00] INFO [rs_demo] src/main.rs:70: After resizing, the area of the rectangle is 2000 square pixels.
使用format_for_files函数可以用于自定义日志的输出格式。定义一个名为custom_format的函数,并将其传递给format_for_files以使用自定义格式记录日志
custom_format中:
use log::{info}; use flexi_logger::{DeferredNow, Duplicate, FileSpec, Logger, Record, WriteMode, Criterion, Naming, Cleanup}; use std::io::Write; use time::format_description::well_known::Rfc3339; use time::OffsetDateTime; // 定义一个结构体 `Rectangle` struct Rectangle { width: u32, height: u32, } // 为 `Rectangle` 实现方法 impl Rectangle { // 关联函数(类似于静态方法) fn new(width: u32, height: u32) -> Rectangle { Rectangle { width, height } } // 实例方法 fn area(&self) -> u32 { self.width * self.height } // 实例方法 fn perimeter(&self) -> u32 { 2 * (self.width + self.height) } // 修改实例的方法 fn set_width(&mut self, width: u32) { self.width = width; } } fn custom_format( w: &mut dyn Write, _now: &mut DeferredNow, record: &Record, ) -> std::io::Result<()> { let now = OffsetDateTime::now_utc().format(&Rfc3339).unwrap(); write!( w, "{} [{}] - {} - {}", now, record.level(), record.target(), record.args() ) } fn main() { // 初始化日志记录,配置输出到文件,设置文件大小限制和滚动日志 let logger = Logger::try_with_str("info") .unwrap() .log_to_file( FileSpec::default() .directory("logs") // 设置日志文件目录 .basename("app") // 设置日志文件前缀 .suffix("log") // 设置日志文件后缀 ) .rotate( Criterion::Size(10_000_000), // 设置日志文件大小限制为 10 MB Naming::Numbers, // 使用数字序号进行文件命名 Cleanup::KeepLogFiles(3), // 保留最近的 3 个日志文件 ) .write_mode(WriteMode::BufferAndFlush) // 设置日志写入模式 .duplicate_to_stderr(Duplicate::Warn) // 将警告级别的日志复制到标准错误输出 .format_for_files(custom_format) // 使用自定义格式 .start() .unwrap(); // 记录不同级别的日志消息 info!("This is an info message."); // 使用关联函数创建一个 `Rectangle` let mut rect = Rectangle::new(30, 50); // 调用实例方法 info!("The area of the rectangle is {} square pixels.", rect.area()); info!("The perimeter of the rectangle is {} pixels.", rect.perimeter()); // 修改实例的字段 rect.set_width(40); info!("After resizing, the area of the rectangle is {} square pixels.", rect.area()); // 强制刷新日志缓冲区 logger.flush(); }
2024-07-17T12:28:34.701362Z [INFO] - rs_demo - This is an info message. 2024-07-17T12:28:34.7024068Z [INFO] - rs_demo - The area of the rectangle is 1500 square pixels. 2024-07-17T12:28:34.7024153Z [INFO] - rs_demo - The perimeter of the rectangle is 160 pixels. 2024-07-17T12:28:34.7024181Z [INFO] - rs_demo - After resizing, the area of the rectangle is 2000 square pixels.
下面通过一个无限循环不断地写入日志消息,从而测试日志文件的滚动和清理功能。这种设置在实际应用中可能用于持续记录应用程序的运行状态或调试信息
use log::info; use flexi_logger::{Logger, FileSpec, Criterion, Naming, Cleanup, WriteMode, Duplicate, detailed_format}; use std::thread; use std::time::Duration; fn main() { // 初始化日志记录,配置输出到文件,设置文件大小限制和滚动日志 let _logger = Logger::try_with_str("info") .unwrap() .log_to_file( FileSpec::default() .directory("logs") // 设置日志文件目录 .basename("app") // 设置日志文件前缀 .suffix("log") // 设置日志文件后缀 ) .rotate( Criterion::Size(5_000), // 设置日志文件大小限制为 5 KB Naming::Timestamps, // 使用时间戳进行文件命名 Cleanup::KeepLogFiles(3), // 保留最近的 3 个日志文件 ) .write_mode(WriteMode::BufferAndFlush) // 设置日志写入模式 .duplicate_to_stderr(Duplicate::Warn) // 将警告级别的日志复制到标准错误输出 .format_for_files(detailed_format) // 使用详细格式,包含时间戳 .start() .unwrap(); // 无限循环,不断写入日志 loop { info!("This is an info message."); // 模拟一些工作,等待一段时间 thread::sleep(Duration::from_secs(1)); } }
运行程序数分钟,查看日志文件夹,文件夹目录结构如下,“rCURRENT.log”代表当前程序正在写入的日志文件,剩余的三个日志文件为程序保留的三个日志文件,日志文件都含有时间戳,并且不会随着程序运行的时间延长而新增文件个数
├─logs │ app_r2024-07-17_20-44-24.log │ app_r2024-07-17_20-45-19.log │ app_r2024-07-17_20-46-15.log │ app_rCURRENT.log
使用duplicate_to_stdout(Duplicate::All)方法,将所有级别的日志复制到标准输出(控制台)
.duplicate_to_stdout(Duplicate::All) // 将所有级别的日志复制到标准输出
这样,控制台能看到所有输出到日志文件的日志信息
Criterion::Age表示按时间切分日志文件,flexi_logger::Age::Day指定了按每天切分日志文件。这样,每天会生成一个新的日志文件
Criterion::Age(flexi_logger::Age::Day), // 设置日志文件按日切分