How can I add key-value pairs for Tokio tracing dynamically using logfmt?

I want to add key-value pairs to my Tokio tracing at runtime. How can I manage this?

I tried the following:

tracing = "0.1.40"
tracing-logfmt = "0.3.4"
tracing-subscriber = { version = "0.3.18", features = [
  "fmt",
], default-features = false }
use tracing::{info, info_span, level_filters::LevelFilter};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

fn main() {
    tracing_subscriber::registry()
        .with(LevelFilter::INFO)                                                                                                                                                                   .with(tracing_logfmt::layer())
        .init();

    info!(key1 = "value1", "message");

    let k = "key2";
    let v = "val2";
    let _span1 = info_span!("span1", k = v);
    let _guard1 = _span1.enter();

    info!(key1 = "value1", "message");
}
$ cargo run --bin test
   Compiling rkm v0.1.0 (/home/vagrant/Code/atc-github.azure.cloud.bmw/rkm)
warning: unused variable: `k`
  --> src/bin/test.rs:12:9
   |
12 |     let k = "key2";
   |         ^ help: if this is intentional, prefix it with an underscore: `_k`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: `rkm` (bin "test") generated 1 warning
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s
     Running `target/debug/test`

ts=2024-06-06T14:00:30.154669291Z level=info target=test message=message key1=value1
ts=2024-06-06T14:00:30.155327356Z level=info target=test span=span1 span_path=span1 message=message key1=value1 k=val2

Unfortunately, I'm not able to set the name of the new key to key2. Furthermore, I do not want to have the additional pairs span and span_path.
How can I achive that?

Thanks for your support!

You can't have dynamic field names like you are trying to have with k. The closest thing would be having your key as a constant. From the docs:

Constant expressions can also be used as field names. Constants must be enclosed in curly braces ({}) to indicate that the value of the constant is to be used as the field name, rather than the constant’s name. For example:

const RESOURCE_NAME: &str = "foo";
// this span will have the field `foo = "some_id"`
span!(Level::TRACE, "get", { RESOURCE_NAME } = "some_id");

I personally would simply log them as info_span!("span1", key = k, value = v).

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.