[dependencies]
tracing = { version = "0.1", features = ["max_level_trace", "release_max_level_info"] }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
可看做log的进化版,用于分布式追踪。
features = ["max_level_trace", "release_max_level_info"]
可以指定tracing生成的日志的level范围,在编译期完成过滤。似乎不推荐使用。
使用 tracing 记录日志 - Rust语言圣经(Rust Course)
tracing只是生成日志,但打印、记录还是要交给Collector,如tracing_subscriber。
span 等级问题
TODO
tracing_subscriber
fn main() {
// 设置一个Subscriber
tracing_subscriber::fmt().init();
//没有span也行,但不太符合规范
let span = info_span!("root");
let _enter = span.enter();
info!("This is a test log message");
}
tracing_subscriber::fmt()
.with_max_level(tracing::Level::TRACE)
.init();
fmt()
返回一个SubscriberBuilder
,可以使用with
来添加配置。如果使用finish()
则会生成Subscribe,然后要手动用registry
挂载到全局;如果使用init()
则自动挂载到全局,结束配置。
tracing_subscriber在引入features = ["env-filter"]
后可以通过环境变量来设置日志范围,使用.with(tracing_subscriber::EnvFilter::from_default_env());
后就会读取RUST_LOG
环境变量作为其最大(即最低)日志级别。可以用build.rs
来指定:
fn main() {
println!("cargo:rustc-env=RUST_LOG=info");
}
使用layer实现同时打印到控制台和文件:
fn config_tracing(){
let console_subscriber = tracing_subscriber::fmt::layer()
.with_writer(std::io::stdout);
let log_file = std::fs::File::create("log.txt").unwrap();
let file_subscriber = tracing_subscriber::fmt::layer()
.with_writer(log_file)
.with_ansi(false);
let subscriber = tracing_subscriber::registry()
.with(console_subscriber)
.with(file_subscriber);
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
}
filter
使用EnvFilter以进行日志过滤。
"debug,my_crate_name=trace,hyper=debug"
意思是全局默认过滤到debug以上,my_crate_name
过滤到trace,hyper
过滤到debug。
使用try_from_env
可以实现“如果环境变量有则用环境变量的,否则用unwrap_or_else
中的”。比如下面的代码可以设置环境变量APP_LOG
为"trace,hyper=debug"
以覆盖默认变量。
let env_filter = EnvFilter::try_from_env("APP_LOG")
.unwrap_or_else(|_| EnvFilter::new("debug,ipfs_node_wrapper=trace,hyper=debug"));
let console_subscriber = tracing_subscriber::fmt::layer()
.with_writer(std::io::stdout)
.with_filter(env_filter);
测试时输出
测试lib crate时可能需要输出日志来debug,因此lib的toml中要在[dev-dependencies]
下引入tracing_subscriber然后在测试的开头写上:
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_test_writer()
.init();
with_test_writer
开启了测试中的capture日志的功能。with_test_writer
tracing_appender
这是专门用于写日志到文件的库。
fn config_tracing(){
let console_subscriber = tracing_subscriber::fmt::layer()
.with_writer(std::io::stdout);
let file_appender = RollingFileAppender::new(
Rotation::HOURLY,
"log",
"ipfs_node_wrapper.log");
let file_subscriber = tracing_subscriber::fmt::layer()
.with_writer(file_appender)
.with_ansi(false);
let subscriber = tracing_subscriber::registry()
.with(console_subscriber)
.with(file_subscriber);
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
}
或者更简单的官方例子:
use tracing_subscriber::fmt::writer::MakeWriterExt;
// Log all events to a rolling log file.
let logfile = tracing_appender::rolling::hourly("/logs", "myapp-logs");
// Log `INFO` and above to stdout.
let stdout = std::io::stdout.with_max_level(tracing::Level::INFO);
tracing_subscriber::fmt()
// Combine the stdout and log file `MakeWriter`s into one
// `MakeWriter` that writes to both
.with_writer(stdout.and(logfile))
.init();