Struct Span
struct Span { ... }
A handle representing a span, with the capability to enter the span if it exists.
If the span was rejected by the current Subscriber's filter, entering the
span will silently do nothing. Thus, the handle can be used in the same
manner regardless of whether or not the trace is currently being collected.
Implementations
impl Span
fn new(meta: &'static Metadata<'static>, values: &ValueSet<'_>) -> SpanConstructs a new
Spanwith the given metadata and set of field values.The new span will be constructed by the currently-active
Subscriber, with the current span as its parent (if one exists).After the span is constructed, field values and/or
follows_fromannotations may be added to it.fn new_root(meta: &'static Metadata<'static>, values: &ValueSet<'_>) -> SpanConstructs a new
Spanas the root of its own trace tree, with the given metadata and set of field values.After the span is constructed, field values and/or
follows_fromannotations may be added to it.fn child_of<impl Into<Option<Id>>: Into<Option<Id>>>(parent: impl Into<Option<Id>>, meta: &'static Metadata<'static>, values: &ValueSet<'_>) -> SpanConstructs a new
Spanas child of the given parent span, with the given metadata and set of field values.After the span is constructed, field values and/or
follows_fromannotations may be added to it.fn new_disabled(meta: &'static Metadata<'static>) -> SpanConstructs a new disabled span with the given
Metadata.This should be used when a span is constructed from a known callsite, but the subscriber indicates that it is disabled.
Entering, exiting, and recording values on this span will not notify the
Subscriberbut may record log messages if thelogfeature flag is enabled.const fn none() -> SpanConstructs a new span that is completely disabled.
This can be used rather than
Option<Span>to represent cases where a span is not present.Entering, exiting, and recording values on this span will do nothing.
fn current() -> SpanReturns a handle to the span considered by the
Subscriberto be the current span.If the subscriber indicates that it does not track the current span, or that the thread from which this function is called is not currently inside a span, the returned span will be disabled.
fn enter(self: &Self) -> Entered<'_>Enters this span, returning a guard that will exit the span when dropped.
If this span is enabled by the current subscriber, then this function will call
Subscriber::enterwith the span'sId, and dropping the guard will callSubscriber::exit. If the span is disabled, this does nothing.In Asynchronous Code
Warning: in asynchronous code that uses async/await syntax,
Span::entershould be used very carefully or avoided entirely. Holding the drop guard returned bySpan::enteracross.awaitpoints will result in incorrect traces. For example,# use info_span; # async asyncThe drop guard returned by
Span::enterexits the span when it is dropped. When an async function or async block yields at an.awaitpoint, the current scope is exited, but values in that scope are not dropped (because the async block will eventually resume execution from that await point). This means that another task will begin executing while remaining in the entered span. This results in an incorrect trace.Instead of using
Span::enterin asynchronous code, prefer the following:-
To enter a span for a synchronous section of code within an async block or function, prefer
Span::in_scope. Sincein_scopetakes a synchronous closure and exits the span when the closure returns, the span will always be exited before the next await point. For example:# use info_span; # async async -
For instrumenting asynchronous code,
tracingprovides theFuture::instrumentcombinator for attaching a span to a future (async function or block). This will enter the span every time the future is polled, and exit it whenever the future yields.Instrumentcan be used with an async block inside an async function:# use tracing::info_span; use tracing::Instrument; # async fn some_other_async_function() {} async fn my_async_function() { let span = info_span!("my_async_function"); async move { // This is correct! If we yield here, the span will be exited, // and re-entered when we resume. some_other_async_function().await; //more asynchronous code inside the span... } // instrument the async block with the span... .instrument(span) // ...and await it. .await }It can also be used to instrument calls to async functions at the callsite:
# use tracing::debug_span; use tracing::Instrument; # async fn some_other_async_function() {} async fn my_async_function() { let some_value = some_other_async_function() .instrument(debug_span!("some_other_async_function")) .await; // ... } -
The
#[instrument]attribute macro can automatically generate correct code when used on an async function:# async fn some_other_async_function() {} #[tracing::instrument(level = "info")] async fn my_async_function() { // This is correct! If we yield here, the span will be exited, // and re-entered when we resume. some_other_async_function().await; // ... }
Examples
# use ; let span = span!; let guard = span.enter; // code here is within the span drop; // code here is no longer within the spanGuards need not be explicitly dropped:
# use trace_span;Sub-scopes may be created to limit the duration for which the span is entered:
# use ; let span = info_span!; // this event is not inside the span. info!-
fn entered(self: Self) -> EnteredSpanEnters this span, consuming it and returning a [guard]
EnteredSpanthat will exit the span when dropped.Warning: In asynchronous code that uses async/await syntax,Span::enteredmay produce incorrect traces if the returned drop guard is held across an await point. See theSpan::enterdocumentation for details.If this span is enabled by the current subscriber, then this function will call
Subscriber::enterwith the span'sId, and dropping the guard will callSubscriber::exit. If the span is disabled, this does nothing.This is similar to the
Span::entermethod, except that it moves the span by value into the returned guard, rather than borrowing it. Therefore, this method can be used to create and enter a span in a single expression, without requiring alet-binding. For example:# use info_span; let _span = info_span!.entered;rather than:
# use info_span; let span = info_span!; let _e = span.enter;Furthermore,
enteredmay be used when the span must be stored in some other struct or be passed to a function while remaining entered.Note: The returnedEnteredSpanguard does not implementSend. Dropping the guard will exit this span, and if the guard is sent to another thread and dropped there, that thread may never have entered this span. Thus,EnteredSpans should not be sent between threads.Examples
The returned guard can be [explicitly exited][EnteredSpan::exit], returning the un-entered span:
# use ; let span = span!.entered; // code here is within the span // explicitly exit the span, returning it let span = span.exit; // code here is no longer within the span // enter the span again let span = span.entered; // now we are inside the span once againGuards need not be explicitly dropped:
# use trace_span;Since the
EnteredSpanguard can dereference to theSpanitself, the span may still be accessed while entered. For example:# use info_span; use field; // create the span with an empty field, and enter it. let span = info_span!.entered; // we can still record a value for the field while the span is entered. span.record;fn or_current(self: Self) -> SelfReturns this span, if it was enabled by the current
Subscriber, or the current span (whose lexical distance may be further than expected), if this span is disabled.This method can be useful when propagating spans to spawned threads or async tasks. Consider the following:
let _parent_span = info_span!.entered; // ... let child_span = debug_span!; spawn;If the current
Subscriberenables theDEBUGlevel, then both the "parent" and "child" spans will be enabled. Thus, when the "spawaned a thread!" event occurs, it will be inside of the "child" span. Because "parent" is the parent of "child", the event will also be inside of "parent".However, if the
Subscriberonly enables theINFOlevel, the "child" span will be disabled. When the thread is spawned, thechild_span.entered()call will do nothing, since "child" is not enabled. In this case, the "spawned a thread!" event occurs outside of any span, since the "child" span was responsible for propagating its parent to the spawned thread.If this is not the desired behavior,
Span::or_currentcan be used to ensure that the "parent" span is propagated in both cases, either as a parent of "child" or directly. For example:let _parent_span = info_span!.entered; // ... // If DEBUG is enabled, then "child" will be enabled, and `or_current` // returns "child". Otherwise, if DEBUG is not enabled, "child" will be // disabled, and `or_current` returns "parent". let child_span = debug_span!.or_current; spawn;When spawning asynchronous tasks,
Span::or_currentcan be used similarly, in combination withinstrument:use Instrument; # // lol # let _parent_span = info_span!.entered; // ... let child_span = debug_span!; spawn;In general,
or_currentshould be preferred over nesting aninstrumentcall inside of anin_current_spancall, as usingor_currentwill be more efficient.use Instrument; # // lol # async let _parent_span = info_span!.entered; // Do this: spawn; // ...rather than this: spawn;fn in_scope<F: FnOnce() -> T, T>(self: &Self, f: F) -> TExecutes the given function in the context of this span.
If this span is enabled, then this function enters the span, invokes
fand then exits the span. If the span is disabled,fwill still be invoked, but in the context of the currently-executing span (if there is one).Returns the result of evaluating
f.Examples
# use ; let my_span = span!; my_span.in_scope; // this event occurs outside the span. trace!;Calling a function and returning the result:
# use ; let span = info_span!; // the span will be entered for the duration of the call to // `hello_world`. let a_string = span.in_scope;fn field<Q: field::AsField + ?Sized>(self: &Self, field: &Q) -> Option<Field>Returns a [
Field][super::field::Field] for the field with the givenname, if one exists,fn has_field<Q: field::AsField + ?Sized>(self: &Self, field: &Q) -> boolReturns true if this
Spanhas a field for the given [Field][super::field::Field] or field name.fn record<Q: field::AsField + ?Sized, V: field::Value>(self: &Self, field: &Q, value: V) -> &SelfRecords that the field described by
fieldhas the valuevalue.This may be used with
field::Emptyto declare fields whose values are not known when the span is created, and record them later:use ; // Create a span with two fields: `greeting`, with the value "hello world", and // `parting`, without a value. let span = trace_span!; // ... // Now, record a value for parting as well. // (note that the field name is passed as a string slice) span.record;However, it may also be used to record a new value for a field whose value was already recorded:
use info_span; # // Initially, let's assume that our attempt to do something is going okay... let span = info_span!; let _e = span.enter; match do_somethingNote: The fields associated with a span are part of itsMetadata. TheMetadatadescribing a particular span is constructed statically when the span is created and cannot be extended later to add new fields. Therefore, you cannot record a value for a field that was not specified when the span was created:use ; // Create a span with two fields: `greeting`, with the value "hello world", and // `parting`, without a value. let span = trace_span!; // ... // Now, you try to record a value for a new field, `new_field`, which was not // declared as `Empty` or populated when you created `span`. // You won't get any error, but the assignment will have no effect! span.record; // Instead, all fields that may be recorded after span creation should be declared up front, // using field::Empty when a value is not known, as we did for `parting`. // This `record` call will indeed replace field::Empty with "you will be remembered". span.record;fn record_all(self: &Self, values: &ValueSet<'_>) -> &SelfRecords all the fields in the provided
ValueSet.fn is_disabled(self: &Self) -> boolReturns
trueif this span was disabled by the subscriber and does not exist.See also
is_none.fn is_none(self: &Self) -> boolReturns
trueif this span was constructed bySpan::noneand is empty.If
is_nonereturnstruefor a given span, thenis_disabledwill also returntrue. However, when a span is disabled by the subscriber rather than constructed bySpan::none, this method will returnfalse, whileis_disabledwill returntrue.fn follows_from<impl Into<Option<Id>>: Into<Option<Id>>>(self: &Self, from: impl Into<Option<Id>>) -> &SelfIndicates that the span with the given ID has an indirect causal relationship with this span.
This relationship differs somewhat from the parent-child relationship: a span may have any number of prior spans, rather than a single one; and spans are not considered to be executing inside of the spans they follow from. This means that a span may close even if subsequent spans that follow from it are still open, and time spent inside of a subsequent span should not be included in the time its precedents were executing. This is used to model causal relationships such as when a single future spawns several related background tasks, et cetera.
If this span is disabled, or the resulting follows-from relationship would be invalid, this function will do nothing.
Examples
Setting a
follows_fromrelationship with aSpan:# use ; let span1 = span!; let span2 = span!; span2.follows_from;Setting a
follows_fromrelationship with the current span:# use ; let span = span!; span.follows_from;Setting a
follows_fromrelationship with aSpanreference:# use ; let span = span!; let curr = current; span.follows_from;Setting a
follows_fromrelationship with anId:# use ; let span = span!; let id = span.id; span.follows_from;fn id(self: &Self) -> Option<Id>Returns this span's
Id, if it is enabled.fn metadata(self: &Self) -> Option<&'static Metadata<'static>>Returns this span's
Metadata, if it is enabled.fn with_subscriber<T, impl FnOnce((&Id, &Dispatch)) -> T: FnOnce((&Id, &Dispatch)) -> T>(self: &Self, f: impl FnOnce((&Id, &Dispatch)) -> T) -> Option<T>Invokes a function with a reference to this span's ID and subscriber.
if this span is enabled, the provided function is called, and the result is returned. If the span is disabled, the function is not called, and this method returns
Noneinstead.
impl Clone for Span
fn clone(self: &Self) -> Span
impl Debug for Span
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl Drop for Span
fn drop(self: &mut Self)
impl Freeze for Span
impl Hash for Span
fn hash<H: Hasher>(self: &Self, hasher: &mut H)
impl PartialEq for Span
fn eq(self: &Self, other: &Self) -> bool
impl RefUnwindSafe for Span
impl Send for Span
impl Sync for Span
impl Unpin for Span
impl UnsafeUnpin for Span
impl UnwindSafe for Span
impl<T> Any for Span
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for Span
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for Span
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for Span
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> From for Span
fn from(t: T) -> TReturns the argument unchanged.
impl<T> Instrument for Span
impl<T> ToOwned for Span
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T> WithSubscriber for Span
impl<T, U> Into for Span
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for Span
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for Span
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>