Netwave
Netwave

Reputation: 42678

How to use a dynamic span name with tracing?

I need to instrument spans with different names dynamically. How can I create a tracing span with dynamic naming?

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

Upvotes: 9

Views: 3498

Answers (3)

Elliott
Elliott

Reputation: 21

You can accomplish this by setting the otel.name field on a span:

let span = tracing::Span::current();
let my_span_name = "Whatever I want the name to be".to_owned();
span.record("otel.name", my_span_name);

Reference

Upvotes: 2

Naaman
Naaman

Reputation: 11

To confirm what you're after, is it dynamic naming of your spans, ie. the name is decided at runtime? or do you just want to be able to declare the name of your spans in constants and use those when you create your spans?

If it's the former, then I don't believe you're able to, because the macro explicitly only accepts literals. However if its the latter, you can work around it via basic macros.

Playground

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

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

Then you can use it below

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);
}

To be honest I can only take a guess at why this works (so anyone who knows for sure, please feel free to correct me). But I would assume that macro expansion occurs prior to actually trying to compile the code. So by the time the compiler is trying to compile that span, the macro has already been expanded to the underlying literal.

Upvotes: 1

Shepmaster
Shepmaster

Reputation: 430270

Instead of attempting to set the span's name dynamically, add a field:

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

From the docs:

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

Upvotes: 4

Related Questions