ane*_*son 5 trace rust rust-cargo rust-tokio
我正在为公司内部使用编写一个 Rust 板条箱,它包装了优秀的 Tokiotracing板条箱,并带有一些附加功能。我不仅重新导出了 中的宏tracing,而且还添加了一些我自己的在内部调用tracing宏的宏。我的目标是让我们所有的其他内部 crate 仅依赖于我的包装 crate,而不必tracing在每个 crate 中明确引入依赖项。
这非常有效,直到我今天遇到一个问题,我花了几个小时来隔离。我做了一个最小的例子来展示这里的行为。
在这个例子中,我有一个带有两个 crate 的工作区:my-logger-crate它包装tracing和公开一个 macro print_trace!,一个二进制 cratemy-binary-crate依赖于my-logger-crate,并在main函数内调用宏。
该Cargo.toml用于my-logger-crate非常简单; 我添加到自动生成的骨架中的唯一内容是tracing依赖项:
[package]
name = "my-logger-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.12"
Run Code Online (Sandbox Code Playgroud)
这是my-logger-crate宏:
[package]
name = "my-logger-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.12"
Run Code Online (Sandbox Code Playgroud)
这由 使用my-binary-crate,它Cargo.toml也很简单:
[package]
name = "my-binary-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
my-logger-crate = { path = "../my-logger-crate" }
# If the following line is uncommented, then the call to `print_trace!` in `main()` fails to compile.
# tower = "0.3"
Run Code Online (Sandbox Code Playgroud)
这是 中的main()函数my-binary-crate:
/// Re-export everything in the `tracing` crate
pub use ::tracing::*;
/// A version of the `trace!` macro that sets a special target
#[macro_export]
macro_rules! print_trace {
($($arg:tt)*) => (
// Invoke the `trace!` macro which is defined in the `tracing` crate but which has been
// re-exported from this crate, so that downstream callers don't have to take an explicit
// dependency on `tracing`
$crate::trace!(target: "console", $($arg)*)
)
}
Run Code Online (Sandbox Code Playgroud)
如果my-binary-crate没有任何冲突的依赖项,这将编译并运行良好。
但是看看如果我们tower在my-binary-crate/Cargo.toml文件中有依赖会发生什么:
[package]
name = "my-binary-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
my-logger-crate = { path = "../my-logger-crate" }
# If the following line is uncommented, then the call to `print_trace!` in `main()` fails to compile.
tower = "0.3"
Run Code Online (Sandbox Code Playgroud)
这是发生的事情:
[package]
name = "my-binary-crate"
version = "0.1.0"
authors = ["Adam Nelson <anelson@users.noreply.github.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
my-logger-crate = { path = "../my-logger-crate" }
# If the following line is uncommented, then the call to `print_trace!` in `main()` fails to compile.
# tower = "0.3"
Run Code Online (Sandbox Code Playgroud)
该print_trace!宏扩展出来的tracing::trace!宏,然后扩展到tracing::event!,然后扩展到代码来记录事件,其中包括对呼叫tracing::...。在我添加该tower依赖项之前,所有这些都可以正常工作,因此显然编译器能够tracing::...正确解析,即使my-binary-crate对tracing自身没有直接依赖关系。
我怀疑这与依赖冲突有关。 tower拉入一个很长的依赖树,包括tower-buffer,它本身依赖于tracing = "0.1.2"。
我对 Cargo 如何解决这个看似冲突的理解是它会使用tracingversion 0.1.12,因为我的日志记录箱明确依赖于 version =0.1.12,并tower-buffer指定了0.1.2,它等效于^0.1.2. 但我不明白为什么添加这个额外的依赖树会破坏我的宏的使用。
目前,我已经通过tracing在所有使用我的日志记录箱的下游箱中添加显式依赖来解决它,但这远非理想。
我在启用宏跟踪的情况下运行:
fn main() {
println!("Hello, world!");
// Log a trace event with the logging system
my_logger_crate::print_trace!("this is a trace message from print_trace!");
}
Run Code Online (Sandbox Code Playgroud)
不足为奇的是,该错误是试图调用tracing::__mk_format_string!,这失败,因为没有这样的箱子tracing被引用my-binary-crate。奇怪的是,为了解决这个错误,tracing必须评估其他几个宏。也许这是一个错误tracing,它应该是$crate::__mk_format_string!。但是,在我添加tower对my-binary-crate.
| 归档时间: |
|
| 查看次数: |
624 次 |
| 最近记录: |