内容简介:文档列表见:(上次更新:2018-11-22)基于log、env_logger、fern等的使用总结,详细配置建议参考官方说明。给Cargo.toml文件加上如下配置,log基本为Rust项目日志需求的标配库,env_logger提供了具体实现,类似策略模式:log定义操作,env_logger实现具体行为,很方便切换另一个实现了log所定义接口的库,比如
文档列表见: Rust 移动端跨平台复杂图形渲染项目开发系列总结(目录)
(上次更新:2018-11-22)基于log、env_logger、fern等的使用总结,详细配置建议参考官方说明。
给工程添加第三方日志库依赖
给Cargo.toml文件加上如下配置,log基本为Rust项目日志需求的标配库,env_logger提供了具体实现,类似策略模式:log定义操作,env_logger实现具体行为,很方便切换另一个实现了log所定义接口的库,比如 daboross/fern 。
[dependencies] log = "0.4.0" env_logger = "0.6.0" 复制代码
env_log配置
下面描述我们项目对env_log所作的配置。
配置输出时间为本地时间
env_logger默认用0时区,而北京是东8区,每次日志输出都少8小时,时间没对上不方便分析日志。0时区举个例子:
[2018-11-18T02:00:08Z INFO webgpu-native::registry] env_logger initialized. 复制代码
下面给出env_logger输出本地时间的示例代码,参考了 DCjanus/nabu
,他用flexi_logger,略调整即可用于env_logger。
加上更多自定义信息的关键是修改 writeln!
宏。
#[macro_use] extern crate log; extern crate chrono; extern crate env_logger; fn init_log() { use chrono::Local; use std::io::Write; let env = env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "trace"); env_logger::Builder::from_env(env) .format(|buf, record| { writeln!( buf, "{} {} [{}] {}", Local::now().format("%Y-%m-%d %H:%M:%S"), record.level(), record.module_path().unwrap_or("<unnamed>"), &record.args() ) }) .init(); info!("env_logger initialized."); } 复制代码
以上代码需在fn main()开始或lazy_static开始,否则刚开始部分日志不受新配置影响。放在lazy_static的日志配置需要 手动 激活,比如
// 定义 lazy_static! { pub(crate) static ref HUB: Hub = { init_log(); Hub::default() }; } // 在某个入口函数中先访问HUB,“强迫”它执行lazy_static代码块 fn entry_point() { &*HUB; // “强迫”执行lazy_static代码块 HUB.some_method(); // 里面的info!()等可正常输出到文件或控制台 } 复制代码
以东8区为例,执行显示:
// 修改前 [2018-11-18T02:00:08Z INFO webgpu-native::registry] env_logger initialized. // 修改后 2018-11-18 09:27:43 INFO [webgpu-native::registry] env_logger initialized. 复制代码
日志添加行号
writeln!( buf, "{} {} [{}:{}] {}", Local::now().format("%Y-%m-%d %H:%M:%S"), record.level(), record.module_path().unwrap_or("<unnamed>"), record.line().unwrap_or(0), &record.args() ) 复制代码
执行显示:
2018-11-18 10:38:41 INFO [webgpu-native::registry:87] env_logger initialized. 复制代码
日志添加文件名
writeln!( buf, "{} {} [{}:{}:{}] {}", Local::now().format("%Y-%m-%d %H:%M:%S"), record.level(), record.module_path().unwrap_or("<unnamed>"), record.line().unwrap_or(0), &record.args() ) 复制代码
执行显示:
2018-11-18 10:38:48 INFO [webgpu-native::registry:webgpu-native/src/registry.rs:87] env_logger initialized. 复制代码
过滤日志级别
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "trace"); 复制代码
filter_or()
可配置如下内置值过滤不同级别的日志,其实我们也可自行添加filter tag:
- "trace"
- "info"
- "debug"
- "warn"
- "error"
也可以在程序执行时传递命令行参数进行过滤:
$ RUST_LOG=info ./main [2018-11-03T06:09:06Z INFO default] starting up 复制代码
动态过滤信息
在复杂项目中往往存在多个模块,作为其中一个模块的开发者,为了定位自己负责模块的问题,过滤掉其他模块的日志是很常见的需求,由于整体项目通常使用同一个日志库,逐行注释其他模块的日志输出显然是不可理的行为。另外,虽然控制台可以做过滤处理,多条件的过滤规则编写起来也有难度,而且可能日志查看系统不支持这种操作。其实,我们可以给前面一直在修改的 format()
加上过滤逻辑,比如:
format(|buf, record| { // special format for debug messages coming from our own crate. if record.level() > log::LevelFilter::Info && record.target() == "my_module" { write!(...) } else if /* some condition */ { write!(...) } else if /* some condition 2*/ { write!(...) } else { write!(...) } } 复制代码
过滤逻辑的实现可参考 fern/cmd-program.rs 。
fern,env_logger的另一个选择
Simple, efficient logging for Rust
fern配置起来更直观(所下所示), 目前我还没测试它与env_logger的性能差异 。
// Configure logger at runtime fern::Dispatch::new() // Perform allocation-free log formatting .format(|out, message, record| { out.finish(format_args!( "{}[{}][{}] {}", chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), record.target(), record.level(), message )) }) // Add blanket level filter - .level(log::LevelFilter::Debug) // - and per-module overrides .level_for("hyper", log::LevelFilter::Info) // Output to stdout, files, and other Dispatch configurations .chain(std::io::stdout()) .chain(fern::log_file("output.log")?) // Apply globally .apply()?; // and log using log crate macros! info!("helllo, world!"); 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。