如何结合RUST_LOG配置tracing,仅记录自有crate日志
配置tracing实现指定日志输出需求
我有一个拆分了lib.rs的二进制Rust应用,想要配置tracing实现以下行为:
- 将日志事件输出至stdout;
- 始终忽略非自有crate产生的事件;
- 未设置
RUST_LOG环境变量时不记录任何日志,设置后仅按其指定级别记录。
我知道单独用以下两种配置能分别实现部分需求:
tracing_subscriber::fmt() .with_env_filter(EnvFilter::new("my_crate")) .init();
(仅记录自有crate的日志)
和
tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .init();
(根据RUST_LOG控制日志级别)
但尝试组合这两种逻辑时失败了,我试了下面的代码但没生效:
tracing_subscriber::fmt() .with_env_filter( EnvFilter::from_default_env() .add_directive(Directive::from_str("my_crate").unwrap()), ) .init();
正确实现方式
要同时满足所有需求,核心是根据RUST_LOG的存在状态生成对应的EnvFilter,同时严格限制只记录自有crate的日志。
完整代码示例
use tracing_subscriber::{fmt, filter::{EnvFilter, Directive}}; fn init_tracing() { let env_filter = match std::env::var("RUST_LOG") { // 未设置RUST_LOG时,直接关闭自有crate的所有日志 Err(_) => EnvFilter::new("my_crate=off"), // 设置了RUST_LOG时,结合级别规则并屏蔽其他所有crate Ok(log_level) => EnvFilter::new(format!("{log_level},my_crate")) .add_directive(Directive::from_str("=off").unwrap()), }; fmt() .with_env_filter(env_filter) .init(); }
逻辑拆解
- 无
RUST_LOG时:使用my_crate=off直接禁用自有crate的所有日志,自然不会输出任何内容; - 有
RUST_LOG时:- 将
RUST_LOG指定的级别与自有crate绑定(比如RUST_LOG=debug会转为debug,my_crate); - 添加
=off指令,该指令会匹配所有未明确指定的crate,直接关闭它们的日志,确保只有自有crate的日志按指定级别输出;
- 将
- 输出到stdout是
tracing_subscriber::fmt()的默认行为,无需额外配置。
简洁写法
也可以用更紧凑的逻辑实现相同效果:
use tracing_subscriber::{fmt, filter::EnvFilter}; fn init_tracing() { let base_filter = EnvFilter::new("my_crate"); let env_filter = std::env::var("RUST_LOG") .map(|level| EnvFilter::new(level).and(base_filter).add_directive("=off".parse().unwrap())) .unwrap_or_else(|_| EnvFilter::new("my_crate=off")); fmt() .with_env_filter(env_filter) .init(); }
内容的提问来源于stack exchange,提问作者Max888
相关产品推荐
相关产品推荐

