span!() { /* proc-macro */ }Expand description
Creates a new span using OpenTelemetry.
This macro provides a concise syntax for creating spans with optional attributes, span kind, parent context, and body (closure or async block).
§Syntax
span!(name [, scope: expr] [, parent: cx] [, kind: K] [, attrs...] [, body])Where:
name- Span name (string literal or expression)scope: expr- Optional instrumentation scope. If omitted, uses calling crate’s scope.parent: cx- Optional parent context. If omitted, usesContext::current().kind: K- Optional span kind (e.g.,kind: SpanKind::Server)attrs...- Optional attributes as"key" = valuepairsbody- Optional body:|| { },move || { },async { }, orasync move { }
Without a body, returns the span for manual lifetime management. With a body, the span is active for the duration of the closure/async block.
§Examples
use apollo_opentelemetry::span;
use opentelemetry::trace::SpanKind;
// Simple span
let _span = span!("my-operation");
// With closure
span!("process", || {
// work happens here
});
// With kind and attributes
span!("db-query", kind: SpanKind::Client, "db.system" = "postgresql", || {
// execute query
});
// Async
span!("async-operation", async {
// async work
}).await;§Spawned tasks
The async block form returns a Future, making it composable with
tokio::spawn(), select!, join!, etc. The span context is captured
when the span is created, so spawned tasks inherit the parent automatically:
use apollo_opentelemetry::span;
span!("parent", async {
tokio::spawn(span!("child", async {
do_background_work().await;
})).await.unwrap();
}).await;§Dynamic span names
Span names can be expressions — variables, format!, function calls, etc.:
use apollo_opentelemetry::span;
let name = String::from("dynamic-span");
let _span = span!(name);
let id = 42u32;
span!(format!("request-{id}"), || { /* work */ });§Optional attributes
Attribute values of Option<T> are silently skipped when None:
use apollo_opentelemetry::span;
let user_id: Option<i64> = Some(42);
let _span = span!("request", "user.id" = user_id);§Automatic span status from Result
Closure and async block forms automatically set the span status based on the return value:
Ok(_)→ span status set toOkErr(e)→ span status set toErrorwith the error’s display message- Any other type → span status unchanged
use apollo_opentelemetry::span;
fn process() -> Result<(), String> {
span!("process", || {
do_work()?;
Ok(())
})
}§Custom Instrumentation Scope
Use scope: to override the instrumentation scope (library name and version
reported in telemetry). If omitted, the calling crate’s scope is used.
use apollo_opentelemetry::span;
use opentelemetry::InstrumentationScope;
let _span = span!("my-operation", scope: my_scope());§Explicit Parent Context
Use parent: to create a span with a specific parent context:
use apollo_opentelemetry::span;
use opentelemetry::Context;
use opentelemetry::trace::TraceContextExt;
span!("child", parent: parent_cx, || {
// This span's parent comes from parent_cx
});Creates a new span using OpenTelemetry.
See apollo_opentelemetry::span! for full documentation.