日志记录几乎是每个应用程序的重要组成部分,它可以帮助我们有效地调试和跟踪错误。在Rust中,我们可能会使用log crate,它提供了一个日志facade,应用程序及其依赖项可以挂接到它。但是,log crate不提供实际的日志记录实现,这意味着它不会自己将日志写入终端或文件。这就是Ftail的用武之地——它可以为终端和文件提供简单的、可配置的日志记录。设置它很简单,只需几行代码就可以将日志同时输出到终端和文件中。
下面是一个将日志记录输出到终端(最低日志级别为Debug)和每日文件(最低日志级别为Error)的示例:
使用以下命令创建一个Rust新项目:
cargo new ftail-example
在Cargo.toml文件中加入依赖项:
[dependencies]
ftail = "0.1"
log = "0.4.22"
然后,在项目根目录下创建一个名为logs的文件夹。
main.rs文件中的代码如下:
use ftail::Ftail;
use log::LevelFilter;
fn main() {
Ftail::new()
.console(LevelFilter::Debug)
.daily_file("logs", LevelFilter::Error)
.init()
.unwrap();
// 堆代码 duidaima.com
// 可以在代码中的任何地方记录消息
log::trace!("This is a trace message");
log::debug!("This is a debug message");
log::info!(target: "foo", "bar");
log::warn!("This is a warning message");
log::error!("This is an error message");
}
这将初始化一个Ftail实例,添加一个用于将日志记录到终端的驱动程序,以及另一个用于将日志记录到每日文件的驱动程序。init()方法将所有这些联系在一起,确保根据你定义的过滤器捕获和处理日志。
运行结果如下:
DEBUG ftail_example This is a debug message
INFO foo bar
WARN ftail_example This is a warning message
ERROR ftail_example This is an error message
执行完成后会在logs文件下生成一个日志文件,如图:
默认实现
ftail crate提供了几个默认的日志记录器,因此你可以根据需要快速定制日志。
输出到终端
基本的console日志记录器使用标准格式打印日志消息。它简单、有效,非常适合在终端中进行开发或调试。
输出格式化的日志到终端
formatted_console日志记录器为日志添加了一些修饰,包括颜色格式和更清晰的时间戳。这使得日志更容易阅读,特别是在开发期间。有些终端甚至生成了指向日志消息的源文件和行号的可点击链接。
例:
· TRACE
This is a trace message
examples/formatted_console/src/main.rs:9
输出到单独的文件中
single_file日志记录器实现将消息记录到单个.log文件中,需要在设置这个驱动程序时指定文件名和位置。
按日期划分日志文件
daily_file日志记录器实现每天创建一个新的日志文件,日志存储在指定的目录中,每个文件使用YYYY-MM-DD.log格式命名。这对于长时间运行的应用程序来说是完美的,因为它使日志文件保持有序且易于管理。
配置Ftail
ftail提供了各种选项来配置日志记录器。下面是一个如何自定义时区、日期-时间格式和过滤器的示例:
Ftail::new()
.timezone(ftail::Tz::Europe__Amsterdam)
.datetime_format("%d-%m-%Y %H:%M:%S%.3f")
.console(LevelFilter::Off)
.filter_levels(vec![
Level::Trace,
Level::Debug,
Level::Info,
Level::Error,
])
.filter_targets(vec!["foo"])
.init()?;
配置日期时间格式
默认情况下,ftail使用“%Y-%m-%d %H:%M:%S”的格式作为日志消息中的时间戳。但是,我们可以自定义此格式以满足实际项目的需要。在上面的示例中,我们将格式更改为“%d-%m-%Y %H:%M:%S%.3f”,它将毫秒数添加到时间戳(%.3f代表小数点后三位)。
配置时区
ftail允许你为日志设置一个特定的时区,如果你的应用程序在多个地区运行,或者如果需要在不同的服务器上保持一致的时间戳,这是很有帮助的。在上面的示例中,我们将时区设置为Europe/Amsterdam,默认为系统的本地时区。
要使用时区,请确保在Cargo.toml中启用了时区功能:
[dependencies]
ftail = { version = "0.1", features = ["timezone"] }
配置日志文件最大尺寸
日志文件会快速增长,特别是在生产环境中。为了防止单个日志文件变得太大,ftail允许设置最大文件大小(以MB为单位)。一旦达到限制,它就将日志滚动到一个新文件中,将.old1附加到前一个日志文件名,依此类推。
.max_file_size(100)
过滤日志级别
你可以通过显式指定日志级别来过滤写入的日志。在下面的示例中,我们进行筛选,只包括Debug、Info和Error消息,跳过Trace和Warn。
.filter_levels(vec![Level::Debug, Level::Info, Level::Error])
过滤目标
有时,我们只想记录应用程序的特定部分。通过过滤目标,可以控制记录代码库的哪些部分或哪些依赖项。在上面的示例中,我们进行筛选,只记录来自foo目标的消息。
添加自定义日志记录器
如果默认实现不能满足需求,ftail允许我们定义自己的日志记录器。下面是一个例子,我们创建了一个自定义记录器,为它实现了Log特性,并将它hook到ftail中:
struct CustomLogger {
config: Config,
}
impl log::Log for CustomLogger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= self.config.level_filter
}
fn log(&self, record: &log::Record) {
if !self.enabled(record.metadata()) {
return;
}
let time = chrono::Local::now()
.format(&self.config.datetime_format)
.to_string();
println!("{} [{}] {}", time.black(), record.level().bold(), record.args());
}
fn flush(&self) {}
}
Ftail::new()
.custom(
|config: Config| Box::new(CustomLogger { config }) as Box<dyn Log + Send + Sync>,
LevelFilter::Debug,
)
.datetime_format("%H:%M:%S%.3f")
.init()?;
这为我们使用ftail构建自定义日志解决方案提供了充分的灵活性,包括高级格式化、过滤和输出等选项。