如何在跟踪中使用动态跨度名称?

How to use a dynamic span name with tracing?

我需要动态检测具有不同名称的 span。如何使用动态命名创建跟踪范围?

use tracing; // 0.1.22

fn main() {
    let name: &'static str = "foo bar";
    let span = tracing::span!(tracing::Level::TRACE, name);
    let span_handle = span.enter();
    tracing::info!("Hello, world!");
    drop(span_handle);
}
error[E0435]: attempt to use a non-constant value in a constant
 --> src/main.rs:5:54
  |
5 |     let span = tracing::span!(tracing::Level::TRACE, name);
  |                                                      ^^^^ non-constant value

Playground

与其尝试动态设置 span 的名称,不如添加一个字段:

let value = "forty-two";
let span = tracing::span!(tracing::Level::TRACE, "foo bar", value = value);

来自the docs

A span consists of fields, user-defined key-value pairs of arbitrary data that describe the context the span represents

为了确认您所追求的,是您的 span 的动态命名,即。名称是在运行时决定的?或者你只是想在常量中声明你的跨度的名称并在你创建你的跨度时使用它们?

如果是前者,我相信你做不到,因为宏明确地只接受literals。但是,如果是后者,您可以通过基本宏解决它。

Playground

macro_rules! prefix_name {
    ($name:literal) => {
        concat!("prefix::", $name)
    };
}

macro_rules! span_name {
    () => {
        "foo::bar"
    };
}

那下面就可以用了

fn main() {
    let span = tracing::span!(tracing::Level::TRACE, prefix_name!("foo bar"));
    let span_handle = span.enter();
    tracing::info!("Hello, world!");
    drop(span_handle);
    
    let span = tracing::span!(tracing::Level::TRACE, span_name!());
    let span_handle = span.enter();
    tracing::info!("Hello, world!");
    drop(span_handle);
}

老实说,我只能猜测为什么会这样(所以任何确定知道的人,请随时纠正我)。但我会假设宏扩展发生在实际尝试编译代码之前。因此,当编译器尝试编译该跨度时,宏已经扩展为底层文字。