span_fn

Attribute Macro span_fn 

Source
#[span_fn]
Expand description

Instruments a function with automatic span tracing.

This is the primary macro for instrumenting both sync and async functions in micromegas. It automatically detects the function type and applies the appropriate instrumentation.

§Supported Function Types

  • Sync functions: Wrapped with span_scope! for scope-based timing
  • Async functions: Wrapped with InstrumentedFuture for accurate async timing
  • Async trait methods: Works with #[async_trait] - place #[span_fn] after #[async_trait]

§Basic Usage

use micromegas_tracing::prelude::*;

// Async function - tracks time across .await points
#[span_fn]
async fn process_request(req: Request) -> Response {
    let data = fetch_data(req.id).await;
    transform(data).await
}

// Sync function - tracks wall-clock execution time
#[span_fn]
fn calculate_checksum(data: &[u8]) -> u32 {
    data.iter().fold(0u32, |acc, &b| acc.wrapping_add(b as u32))
}

§Custom Span Names

By default, the span name is the function name prefixed with the module path. You can override this with a custom name:

#[span_fn("custom_operation_name")]
async fn internal_impl() {
    // Span will be named "module::path::custom_operation_name"
}

§With Async Traits

When using #[async_trait], place #[span_fn] on the method after the #[async_trait] attribute on the impl block:

use async_trait::async_trait;
use micromegas_tracing::prelude::*;

#[async_trait]
trait DataService {
    async fn fetch(&self, id: u64) -> Data;
}

#[async_trait]
impl DataService for MyService {
    #[span_fn]
    async fn fetch(&self, id: u64) -> Data {
        self.db.query(id).await
    }
}

§How It Works

For async functions, the macro:

  1. Removes the async keyword
  2. Changes the return type to impl Future<Output = T>
  3. Wraps the body in an InstrumentedFuture that tracks timing

For sync functions, the macro:

  1. Inserts a span_scope! call at the start of the function
  2. The span automatically closes when the function returns

§Performance

The overhead is approximately 40ns per span (20ns per event, with a span recording both begin and end). This makes it suitable for high-frequency instrumentation. Spans are collected in thread-local storage and batched for efficient transmission.

§See Also

  • [log_fn] - For simple function entry logging without timing
  • span_scope! - For manual scope-based spans within a function
  • span_async_named! - For manual async spans with dynamic names