资讯动态

tracing-log 0.2.0 迁移指南:env_logger 与 trace_logger 特性移除后的替代方案

发布时间:2026/10/16 14:19:24 来源:尧图企业网站定制
可观测性开发工具【免费下载链接】tracingApplication level tracing for Rust.项目地址https://gitcode.com/gh_mirrors/tr/tracing点击查看免费下载tracing-log是tracing生态与log门面facade之间的兼容层一方面通过LogTracer把log::Record转成tracing::Event送入 trace 树另一方面配合tracing的log/log-always特性把tracing事件反向输出为log记录。本文以 tracing-log/CHANGELOG.md 中 0.2.0 的两个破坏性变更为主线讲解env_logger与trace_logger特性被移除的原因、官方建议的迁移路径并结合仓库源码说明LogTracer的内部工作方式与替代方案的底层实现帮助读者平滑升级并避免常见的递归日志陷阱。背景tracing-log 是什么tracing-log位于仓库 tracing-log/其定位在 tracing-log/src/lib.rs 中写得很明确提供将logcrate 的非结构化日志记录接入tracing生态的适配层。它对外提供两件核心武器LogTracer一个实现了log::Log接口的类型消费log::Record并把它们输出为tracing::Event源码见 tracing-log/src/log_tracer.rs。AsTrace与AsLog在两个生态的类型如log::Level↔tracing_core::Level、log::LevelFilter↔tracing_core::LevelFilter之间做双向转换的 trait。该 crate 支持 Rust 1.65默认启用log-tracer与std两个特性interest-cache特性可选启用用于对log记录的 Interest 做缓存详见 tracing-log/Cargo.toml。0.2.0 的两个破坏性变更0.2.02023 年 10 月 24 日发布引入了两个破坏性变更移除了env_logger和trace_logger这两个 feature。此前它们已被废弃0.1.42023 年 10 月 23 日将env_logger特性标记为废弃推荐改用tracing_subscriber::fmt::Subscriber。0.1.12019 年 10 月 29 日将TraceLogger标记为废弃建议改用tracing的log与log-always特性。到 0.2.0这些废弃的代码路径被彻底移除官方给出了两条明确的迁移路径。变更一移除env_logger特性env_logger特性的存在本身是一个历史包袱它引入了对无人维护的attycrate 的依赖触发安全公告 GHSA-g98v-hv3f-hcfr对应 RUSTSEC-2021-0145即终端 TTY 检测相关依赖不再被维护而带来的安全隐患。移除该特性即可解除这一依赖链。相关变更由 PR #2771 完成。官方建议的迁移路径改用tracing_subscriber::fmt::Subscriber或tracing_subscriber::fmt::Layer并配合Targets或EnvFilter过滤器。这套组合在功能上是env_logger的自然替代fmt::Subscriber负责把tracing事件格式化成人类可读的文本输出Targets/EnvFilter负责按 target 或指令过滤。变更二移除trace_logger特性trace_logger曾被用于在tracing之外把事件转回log记录。官方给出的迁移路径是使用tracingcrate 自带的log特性标志即 log feature。tracing提供了两个相关特性见 tracing/src/lib.rslog启用后当没有活动的tracingSubscriber时调用事件宏或创建带字段的 span 会发出log::Record。这是为库作者设计的——希望自己的诊断既能被使用tracing的应用消费也能被只使用log的应用消费且不承担双重输出的开销。log-always即使已经设置了Subscriber也会无条件发出log::Record。它面向的是用log记录文本日志、用tracing记录指标/剖析/分布式追踪等结构化诊断的应用场景。tracing的官方文档明确建议库作者不要启用log-always否则应用将无法关闭这些log输出。值得注意的是log-always [log]在 tracing/Cargo.toml 中会隐式启用log二者是叠加关系而非互斥。迁移落地从 env_logger 到 tracing-subscriber迁移env_logger用法时最直接的替代是把env_logger::init()换成tracing_subscriber的初始化。仓库中tracing-subscriber的fmt::Subscriber构建器提供了与env_logger类似的 API源码见 tracing-subscriber/src/fmt/mod.rsuse tracing_subscriber::fmt; // 等价于旧的 env_logger::init() fmt::init(); // 或使用构建器进行更细粒度的配置 fmt::Subscriber::builder() .with_env_filter(my_cratedebug,hyperinfo) .with_target(false) .init();关键 API 对应关系如下均以仓库源码为准原env_logger能力tracing-subscriber替代仓库位置默认初始化fmt::init()/fmt::Subscriber::builder().init()tracing-subscriber/src/fmt/mod.rs按环境变量RUST_LOG过滤.with_env_filter(...)或EnvFilter::from_default_env()tracing-subscriber/src/fmt/mod.rs、tracing-subscriber/src/filter/env/mod.rs按 target 白名单过滤.with_targets(...)/Targets::new().with_target(crate, LevelFilter::DEBUG)tracing-subscriber/src/filter/targets.rs日志级别上限.with_max_level(...)tracing-subscriber/src/fmt/mod.rs其中EnvFilter解析RUST_LOG风格指令如hyperinfo,towerwarnTargets则提供面向 target 的静态指令集二者都实现了tracing-subscriber的Layer过滤机制可以单独使用也可以叠加在fmt::Layer之上实现分层过滤。tracing-subscriber的default特性本身已包含tracing-log见 tracing-subscriber/Cargo.toml因此使用FmtSubscriber时通常无需再手动依赖tracing-log。迁移落地从 TraceLogger 到 tracing 的 log 特性旧TraceLogger的职责是把tracing事件重新输出为log::Record。迁移到tracing的log特性后只需要在Cargo.toml中调整特性声明[dependencies] tracing { version 0.1, features [log] } # 或 features [log-always]启用log特性后tracing宏会经由 tracing/src/macros.rs 中的__tracing_log!内部宏把事件翻译成log::Record消息是 span/event 字段的字符串表示log的 target、级别、模块路径、文件与行号都会被填充此外 span 的 enter/exit/close 生命周期也会产生log记录它们统一以Trace级别发出并归类到独立的logtargettracing::span及其子 targettracing::span::active方便单独开关见 tracing/src/lib.rs。迁移后的核心组件LogTracer 是怎么工作的迁移到tracing-subscriber之后tracing-log依然扮演重要角色它让tracing应用能够消费那些仍然只发log::Record的第三方依赖例如hyper。仓库 examples/examples/hyper-echo.rs 就是这一用法的示例——先初始化LogTracer再通过tracing的 span 记录来自hyper的无结构日志。LogTracer初始化有三种方式对应 tracing-log/src/log_tracer.rs 中的源码use tracing_log::LogTracer; // 方式一转发所有 log 记录是否启用完全交给当前 Subscriber 决定 LogTracer::init()?; // 方式二先按 log 级别做一次粗过滤只有不高于指定级别的记录才被转发 LogTracer::init_with_filter(log::LevelFilter::Info)?; // 方式三通过 Builder 进行更细粒度的定制 LogTracer::builder() .ignore_crate(foo) // 忽略目标以 foo 开头的 crate .with_max_level(log::LevelFilter::Info) // 设置全局最大级别 .init()?;Builder 的默认配置是不过滤任何 cratefilter为log::LevelFilter::max()即全部放行见 tracing-log/src/log_tracer.rs。init()内部调用log::set_boxed_logger注册全局 logger并调用log::set_max_level设置logcrate 的最大级别——注意log的全局 logger 只能设置一次。LogTracer实现log::Log的三个方法tracing-log/src/log_tracer.rs时enabled的判定顺序是先对比tracing当前的最大级别tracing_core::LevelFilter::current()高于它则直接禁用再检查ignore_crates列表target 以其中任一字符串开头的记录被忽略最后把log::Metadata通过AsTrace转成tracing元数据交给当前dispatcher的enabled()决定是否放行。而log()方法在enabled()通过后调用 tracing-log/src/lib.rs 中的dispatch_record把log::Record组装成tracing::Event记录的消息被放入message字段target、模块路径、文件与行号分别进入log.target、log.module_path、log.file、log.line字段字段名定义见 tracing-log/src/lib.rs。转换不会把格式化参数变成结构化字段但会把事件挂到当前正在执行的 span 之下——这正是该库的核心价值让依赖发出的log记录能够在 trace 树中找到自己的位置。仓库测试 tracing-log/tests/log_tracer.rs 验证了这一点通过log::Record::builder()构造带 target、file、line、module_path 的记录经LogTracer转发后Subscriber::event能通过normalized_metadata()取回完整元数据。进阶Interest 缓存与 NormalizeEvent0.1.3 为LogTracer引入了with_interest_cache对应 PR #1636。启用interest-cache特性后需要std见 tracing-log/Cargo.toml每个线程会维护一个 LRU 缓存以level target为键缓存 Interest 判定结果实现见 tracing-log/src/interest_cache.rs。默认配置下min_verbosity为Debug、LRU 容量为 1024use tracing_log::{InterestCacheConfig, LogTracer}; LogTracer::builder() .with_interest_cache( InterestCacheConfig::default() .with_min_verbosity(log::Level::Debug) // 低于该级别不缓存 .with_lru_cache_size(1024) // 每个 leveltarget 占一个槽位 ) .init()?;这一设计的动机在 tracing-log/src/log_tracer.rs 有详细说明当没有任何trace!日志启用时仅靠全局最大级别就能廉价地过滤掉trace!记录但只要任意一条trace!日志被启用每个trace!调用都必须跑完整过滤链代价可能很高。缓存正是为这种场景准备的。需要注意的是如果你注册了动态过滤器并希望每次都被执行则不应启用该缓存。此外tracing-log还提供NormalizeEventtrait由于Event要求Metadata是static的而log::Record提供的是带生命周期的 file/line/module_path转换后的事件元数据里这些字段是缺失的target 被硬编码为log。normalized_metadata()能从事件字段中把这些信息捞回来构造一份完整且与源事件等寿命的元数据见 tracing-log/src/lib.rs。tracing-subscriber的 JSON 格式化器正是利用它来还原日志的来源信息。重要警告不要双向转换tracing-log/src/lib.rs 明确警告不要把将log记录转成tracing事件的 logger即LogTracer与把tracing事件转回log记录的Subscriber即启用了tracing的log-always特性的场景同时使用。否则事件会在 subscriber 与 logger 之间无限递归最终导致调用栈溢出。如果真的需要让log生成的tracing事件再被记录为log必须引入额外的过滤层来打断Event ↔ log::Record的循环。升级检查清单检查项说明移除tracing-log的env_logger特性改用tracing-subscriber的fmt::Subscriber/fmt::LayerTargets/EnvFilter移除trace_logger特性改用tracingcrate 的log或log-always特性检查Cargo.toml确认没有残留对atty的间接依赖该依赖已随特性移除而解除检查双向转换确保没有同时启用LogTracer与log-always避免递归日志确认 MSRVtracing-log0.2.0 要求 Rust 1.65与 Tokio 项目的编译器支持策略一致版本演进小结从 tracing-log/CHANGELOG.md 的时间线可以看到该 crate 的演进脉络0.1.02019-09-03首次发布0.1.1 废弃TraceLogger0.1.2 重导出logcrate、补齐AsLog/AsTrace的LevelFilter双向转换并修复LogTracer::enabled不调用Subscriber::enabled、不检查最大级别提示等问题0.1.3 引入with_interest_cache、修复不遵守tracing最大级别过滤器的问题并将 MSRV 提升到 1.490.1.4 废弃env_logger特性最终在 0.2.0 完成两个破坏性移除。理解这一演进有助于在升级时快速定位自己受影响的代码路径。赞分享可观测性开发工具【免费下载链接】tracingApplication level tracing for Rust.项目地址https://gitcode.com/gh_mirrors/tr/tracing点击查看免费下载相关推荐QEMU 移除特性完整指南旧命令行与新替代方案的迁移手册QEMU 移除特性完整指南旧命令行与新替代方案的迁移手册 导读 QEMU 在持续演进过程中会移除一批曾长期存在、但已被更现代机制取代的旧特性。本文以 docs虚拟化硬件仿真OpenTelemetry semconv v1.41.0 迁移指南DeploymentEnvironmentName 移除与替代方案OpenTelemetry semconv v1.41.0 迁移指南DeploymentEnvironmentName 移除与替代方案 本文基于 kOps 仓云原生集群管理运维IaCKornia 迁移指南BoxMotTracker 移除与基于 boxmot RTDETRDetectorBuilder 的替代方案Kornia 迁移指南BoxMotTracker 移除与基于 boxmot RTDETRDetectorBuilder 的替代方案 本篇技术指南聚焦 Ko计算机视觉深度学习人工智能图像处理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑