pub trait Tracer {
type Span: Span;
// Required method
fn build_with_context(
&self,
builder: SpanBuilder,
parent_cx: &Context,
) -> Self::Span;
// Provided methods
fn start<T>(&self, name: T) -> Self::Span
where T: Into<Cow<'static, str>> { ... }
fn start_with_context<T>(&self, name: T, parent_cx: &Context) -> Self::Span
where T: Into<Cow<'static, str>> { ... }
fn span_builder<T>(&self, name: T) -> SpanBuilder
where T: Into<Cow<'static, str>> { ... }
fn build(&self, builder: SpanBuilder) -> Self::Span { ... }
fn in_span<T, F, N>(&self, name: N, f: F) -> T
where F: FnOnce(Context) -> T,
N: Into<Cow<'static, str>>,
Self::Span: Send + Sync + 'static { ... }
}
Expand description
The interface for constructing Span
s.
§In Synchronous Code
Spans can be created and nested manually:
use opentelemetry::{global, trace::{Span, Tracer, TraceContextExt}, Context};
let tracer = global::tracer("my-component");
let parent = tracer.start("foo");
let parent_cx = Context::current_with_span(parent);
let mut child = tracer.start_with_context("bar", &parent_cx);
// ...
child.end(); // explicitly end
drop(parent_cx) // or implicitly end on drop
Spans can also use the current thread’s Context
to track which span is active:
use opentelemetry::{global, trace::{SpanKind, Tracer}};
let tracer = global::tracer("my-component");
// Create simple spans with `in_span`
tracer.in_span("foo", |_foo_cx| {
// parent span is active
tracer.in_span("bar", |_bar_cx| {
// child span is now the active span and associated with the parent span
});
// child has ended, parent now the active span again
});
// parent has ended, no active spans
Spans can also be marked as active, and the resulting guard allows for greater control over when the span is no longer considered active.
use opentelemetry::{global, trace::{Span, Tracer, mark_span_as_active}};
let tracer = global::tracer("my-component");
let parent_span = tracer.start("foo");
let parent_active = mark_span_as_active(parent_span);
{
let child = tracer.start("bar");
let _child_active = mark_span_as_active(child);
// do work in the context of the child span...
// exiting the scope drops the guard, child is no longer active
}
// Parent is active span again
// Parent can be dropped manually, or allowed to go out of scope as well.
drop(parent_active);
// no active span
§In Asynchronous Code
If you are instrumenting code that make use of std::future::Future
or
async/await, be sure to use the FutureExt
trait. This is needed because
the following example will not work:
async {
// Does not work
let _g = mark_span_as_active(span);
// ...
};
The context guard _g
will not exit until the future generated by the
async
block is complete. Since futures can be entered and exited
multiple times without them completing, the span remains active for as
long as the future exists, rather than only when it is polled, leading to
very confusing and incorrect output.
In order to trace asynchronous code, the Future::with_context
combinator
can be used:
use opentelemetry::{trace::FutureExt, Context};
let cx = Context::current();
let my_future = async {
// ...
};
my_future
.with_context(cx)
.await;
Future::with_context
attaches a context to the future, ensuring that the
context’s lifetime is as long as the future’s.
Required Associated Types§
Required Methods§
sourcefn build_with_context(
&self,
builder: SpanBuilder,
parent_cx: &Context,
) -> Self::Span
fn build_with_context( &self, builder: SpanBuilder, parent_cx: &Context, ) -> Self::Span
Start a span from a SpanBuilder
with a parent context.
Provided Methods§
sourcefn start<T>(&self, name: T) -> Self::Span
fn start<T>(&self, name: T) -> Self::Span
Starts a new Span
.
By default the currently active Span
is set as the new Span
’s parent.
Each span has zero or one parent span and zero or more child spans, which represent causally related operations. A tree of related spans comprises a trace. A span is said to be a root span if it does not have a parent. Each trace includes a single root span, which is the shared ancestor of all other spans in the trace.
sourcefn start_with_context<T>(&self, name: T, parent_cx: &Context) -> Self::Span
fn start_with_context<T>(&self, name: T, parent_cx: &Context) -> Self::Span
Starts a new Span
with a given context.
If this context contains a span, the newly created span will be a child of that span.
Each span has zero or one parent span and zero or more child spans, which represent causally related operations. A tree of related spans comprises a trace. A span is said to be a root span if it does not have a parent. Each trace includes a single root span, which is the shared ancestor of all other spans in the trace.
sourcefn span_builder<T>(&self, name: T) -> SpanBuilder
fn span_builder<T>(&self, name: T) -> SpanBuilder
Creates a span builder.
SpanBuilder
s allow you to specify all attributes of a Span
before
the span is started.
sourcefn build(&self, builder: SpanBuilder) -> Self::Span
fn build(&self, builder: SpanBuilder) -> Self::Span
Start a Span
from a SpanBuilder
.
sourcefn in_span<T, F, N>(&self, name: N, f: F) -> T
fn in_span<T, F, N>(&self, name: N, f: F) -> T
Start a new span and execute the given closure with reference to the context in which the span is active.
This method starts a new span and sets it as the active span for the given function. It then executes the body. It ends the span before returning the execution result.
§Examples
use opentelemetry::{global, trace::{Span, Tracer, get_active_span}, KeyValue};
fn my_function() {
// start an active span in one function
global::tracer("my-component").in_span("span-name", |_cx| {
// anything happening in functions we call can still access the active span...
my_other_function();
})
}
fn my_other_function() {
// call methods on the current span from
get_active_span(|span| {
span.add_event("An event!".to_string(), vec![KeyValue::new("happened", true)]);
})
}