Tracing Span Instrument Annotations

Enrich tracing spans with structured field annotations, enter guards for synchronous sections, and follow-from causality links.

RustResilience

Code

snippet
use tracing::{field::Empty, info_span, Instrument as _, Span};

#[tracing::instrument(name = "charge", fields(order_id, amount_cents, risk = Empty))]
async fn charge(card_token: &str, order_id: u64, amount: u64) -> Result<(), String> {
    let span = Span::current();

    // 运行中途才能确定的字段:record 到已建 span 上
    span.record("amount_cents", amount);

    if amount > 1_000_000 {
        span.record("risk", "high");
        return Err("amount exceeds single-charge limit".into());
    }
    span.record("risk", "low");

    // 模拟网关调用:子 span 自动嵌套
    tracing::info!(card_last4 = &card_token[(card_token.len() - 4)..], "contacting gateway");
    Ok(())
}

fn sync_section() {
    let span = info_span!("sync_transform", rows = 0);
    let _guard = span.enter();

    for i in 0..3 {
        // 同步代码里 span 字段随循环更新
        Span::current().record("rows", i + 1);
    }
    tracing::info!("transform complete");
}

#[tokio::main]
async fn main() {
    let outcome = charge("tok_4242424242424242", 991, 25_000).await;
    println!("charge result: {:?}", outcome);

    let parent = info_span!("request", id = 7);
    async {
        sync_section();
        let child = info_span!("db_query");
        child.follows_from(parent.clone());
        let _g = child.enter();
        tracing::info!("query issued under causality link");
    }
    .instrument(parent)
    .await;
}