blob: c980b852490f0ae3fd8d1181af0134d051c82120 [file] [log] [blame]
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Spans represent periods of time in which a program was executing in a particular context."><meta name="keywords" content="rust, rustlang, rust-lang, span"><title>tracing::span - Rust</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" href="../../normalize.css"><link rel="stylesheet" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" href="../../ayu.css" disabled><link rel="stylesheet" href="../../dark.css" disabled><link rel="stylesheet" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script defer src="../../main.js"></script><noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../../tracing/index.html"><div class="logo-container"><img src="https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png" alt="logo"></div></a><h2></h2></nav><nav class="sidebar"><a class="sidebar-logo" href="../../tracing/index.html"><div class="logo-container">
<img src="https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png" alt="logo"></div></a><h2 class="location"><a href="#">Module span</a></h2><div class="sidebar-elems"><section><ul class="block"><li><a href="#structs">Structs</a></li><li><a href="#traits">Traits</a></li></ul></section></div></nav><main><div class="width-limiter"><nav class="sub"><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press ‘S’ to search, ‘?’ for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><a href="../../help.html">?</a></div><div id="settings-menu" tabindex="-1"><a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../wheel.svg"></a></div></div></form></nav><section id="main-content" class="content"><div class="main-heading"><h1 class="fqn">Module <a href="../index.html">tracing</a>::<wbr><a class="mod" href="#">span</a><button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"><img src="../../clipboard.svg" width="19" height="18" alt="Copy item path"></button></h1><span class="out-of-band"><a class="srclink" href="../../src/tracing/span.rs.html#1-1623">source</a> · <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">[<span class="inner">&#x2212;</span>]</a></span></div><details class="rustdoc-toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Spans represent periods of time in which a program was executing in a
particular context.</p>
<p>A span consists of <a href="../field/index.html">fields</a>, user-defined key-value pairs of arbitrary data
that describe the context the span represents, and a set of fixed attributes
that describe all <code>tracing</code> spans and events. Attributes describing spans
include:</p>
<ul>
<li>An <a href="struct.Id.html" title="Id"><code>Id</code></a> assigned by the subscriber that uniquely identifies it in relation
to other spans.</li>
<li>The span’s <a href="#span-relationships">parent</a> in the trace tree.</li>
<li><a href="../struct.Metadata.html">Metadata</a> that describes static characteristics of all spans
originating from that callsite, such as its name, source code location,
<a href="../struct.Level.html">verbosity level</a>, and the names of its fields.</li>
</ul>
<h2 id="creating-spans"><a href="#creating-spans">Creating Spans</a></h2>
<p>Spans are created using the <a href="../macro.span.html"><code>span!</code></a> macro. This macro is invoked with the
following arguments, in order:</p>
<ul>
<li>The <a href="../struct.Metadata.html#method.target"><code>target</code></a> and/or <a href="#span-relationships"><code>parent</code></a> attributes, if the user wishes to
override their default values.</li>
<li>The span’s <a href="../struct.Level.html">verbosity level</a></li>
<li>A string literal providing the span’s name.</li>
<li>Finally, between zero and 32 arbitrary key/value fields.</li>
</ul>
<p>For example:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>tracing::{span, Level};
<span class="doccomment">/// Construct a new span at the `INFO` level named &quot;my_span&quot;, with a single
/// field named answer , with the value `42`.
</span><span class="kw">let </span>my_span = <span class="macro">span!</span>(Level::INFO, <span class="string">&quot;my_span&quot;</span>, answer = <span class="number">42</span>);</code></pre></div>
<p>The documentation for the <a href="../macro.span.html"><code>span!</code></a> macro provides additional examples of
the various options that exist when creating spans.</p>
<p>The <a href="../macro.trace_span.html"><code>trace_span!</code></a>, <a href="../macro.debug_span.html"><code>debug_span!</code></a>, <a href="../macro.info_span.html"><code>info_span!</code></a>, <a href="../macro.warn_span.html"><code>warn_span!</code></a>, and
<a href="../macro.error_span.html"><code>error_span!</code></a> exist as shorthand for constructing spans at various
verbosity levels.</p>
<h3 id="recording-span-creation"><a href="#recording-span-creation">Recording Span Creation</a></h3>
<p>The <a href="struct.Attributes.html" title="Attributes"><code>Attributes</code></a> type contains data associated with a span, and is
provided to the <a href="../trait.Subscriber.html"><code>Subscriber</code></a> when a new span is created. It contains
the span’s metadata, the ID of <a href="#span-relationships">the span’s parent</a> if one was
explicitly set, and any fields whose values were recorded when the span was
constructed. The subscriber, which is responsible for recording <code>tracing</code>
data, can then store or record these values.</p>
<h2 id="the-span-lifecycle"><a href="#the-span-lifecycle">The Span Lifecycle</a></h2><h3 id="entering-a-span"><a href="#entering-a-span">Entering a Span</a></h3>
<p>A thread of execution is said to <em>enter</em> a span when it begins executing,
and <em>exit</em> the span when it switches to another context. Spans may be
entered through the <a href="../struct.Span.html#method.enter"><code>enter</code></a>, <a href="../struct.Span.html#method.entered"><code>entered</code></a>, and <a href="../struct.Span.html#method.in_scope"><code>in_scope</code></a> methods.</p>
<p>The <a href="../struct.Span.html#method.enter"><code>enter</code></a> method enters a span, returning a <a href="struct.Entered.html">guard</a> that exits the span
when dropped</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span>my_var: u64 = <span class="number">5</span>;
<span class="kw">let </span>my_span = <span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;my_span&quot;</span>, my_var);
<span class="comment">// `my_span` exists but has not been entered.
// Enter `my_span`...
</span><span class="kw">let </span>_enter = my_span.enter();
<span class="comment">// Perform some work inside of the context of `my_span`...
// Dropping the `_enter` guard will exit the span.</span></code></pre></div>
<div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;">
<strong>Warning</strong>: In asynchronous code that uses async/await syntax,
<code>Span::enter</code> may produce incorrect traces if the returned drop
guard is held across an await point. See
<a href="struct.Span.html#in-asynchronous-code">the method documentation</a>
for details.
</pre></div>
<p>The <a href="../struct.Span.html#method.entered"><code>entered</code></a> method is analogous to <a href="../struct.Span.html#method.enter"><code>enter</code></a>, but moves the span into
the returned guard, rather than borrowing it. This allows creating and
entering a span in a single expression:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Create a span and enter it, returning a guard:
</span><span class="kw">let </span>span = <span class="macro">span!</span>(Level::INFO, <span class="string">&quot;my_span&quot;</span>).entered();
<span class="comment">// We are now inside the span! Like `enter()`, the guard returned by
// `entered()` will exit the span when it is dropped...
// ...but, it can also be exited explicitly, returning the `Span`
// struct:
</span><span class="kw">let </span>span = span.exit();</code></pre></div>
<p>Finally, <a href="../struct.Span.html#method.in_scope"><code>in_scope</code></a> takes a closure or function pointer and executes it
inside the span:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span>my_var: u64 = <span class="number">5</span>;
<span class="kw">let </span>my_span = <span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;my_span&quot;</span>, my_var = <span class="kw-2">&amp;</span>my_var);
my_span.in_scope(|| {
<span class="comment">// perform some work in the context of `my_span`...
</span>});
<span class="comment">// Perform some work outside of the context of `my_span`...
</span>my_span.in_scope(|| {
<span class="comment">// Perform some more work in the context of `my_span`.
</span>});</code></pre></div>
<pre class="ignore" style="white-space:normal;font:inherit;">
<strong>Note</strong>: Since entering a span takes <code>&self</code>, and
<code>Span</code>s are <code>Clone</code>, <code>Send</code>, and
<code>Sync</code>, it is entirely valid for multiple threads to enter the
same span concurrently.
</pre>
<h3 id="span-relationships"><a href="#span-relationships">Span Relationships</a></h3>
<p>Spans form a tree structure — unless it is a root span, all spans have a
<em>parent</em>, and may have one or more <em>children</em>. When a new span is created,
the current span becomes the new span’s parent. The total execution time of
a span consists of the time spent in that span and in the entire subtree
represented by its children. Thus, a parent span always lasts for at least
as long as the longest-executing span in its subtree.</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// this span is considered the &quot;root&quot; of a new trace tree:
</span><span class="macro">span!</span>(Level::INFO, <span class="string">&quot;root&quot;</span>).in_scope(|| {
<span class="comment">// since we are now inside &quot;root&quot;, this span is considered a child
// of &quot;root&quot;:
</span><span class="macro">span!</span>(Level::DEBUG, <span class="string">&quot;outer_child&quot;</span>).in_scope(|| {
<span class="comment">// this span is a child of &quot;outer_child&quot;, which is in turn a
// child of &quot;root&quot;:
</span><span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;inner_child&quot;</span>).in_scope(|| {
<span class="comment">// and so on...
</span>});
});
<span class="comment">// another span created here would also be a child of &quot;root&quot;.
</span>});</code></pre></div>
<p>In addition, the parent of a span may be explicitly specified in
the <code>span!</code> macro. For example:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="comment">// Create, but do not enter, a span called &quot;foo&quot;.
</span><span class="kw">let </span>foo = <span class="macro">span!</span>(Level::INFO, <span class="string">&quot;foo&quot;</span>);
<span class="comment">// Create and enter a span called &quot;bar&quot;.
</span><span class="kw">let </span>bar = <span class="macro">span!</span>(Level::INFO, <span class="string">&quot;bar&quot;</span>);
<span class="kw">let </span>_enter = bar.enter();
<span class="comment">// Although we have currently entered &quot;bar&quot;, &quot;baz&quot;&#39;s parent span
// will be &quot;foo&quot;.
</span><span class="kw">let </span>baz = <span class="macro">span!</span>(parent: <span class="kw-2">&amp;</span>foo, Level::INFO, <span class="string">&quot;baz&quot;</span>);</code></pre></div>
<p>A child span should typically be considered <em>part</em> of its parent. For
example, if a subscriber is recording the length of time spent in various
spans, it should generally include the time spent in a span’s children as
part of that span’s duration.</p>
<p>In addition to having zero or one parent, a span may also <em>follow from</em> any
number of other spans. This indicates a causal relationship between the span
and the spans that it follows from, but a follower is <em>not</em> typically
considered part of the duration of the span it follows. Unlike the parent, a
span may record that it follows from another span after it is created, using
the <a href="../struct.Span.html#method.follows_from"><code>follows_from</code></a> method.</p>
<p>As an example, consider a listener task in a server. As the listener accepts
incoming connections, it spawns new tasks that handle those connections. We
might want to have a span representing the listener, and instrument each
spawned handler task with its own span. We would want our instrumentation to
record that the handler tasks were spawned as a result of the listener task.
However, we might not consider the handler tasks to be <em>part</em> of the time
spent in the listener task, so we would not consider those spans children of
the listener span. Instead, we would record that the handler tasks follow
from the listener, recording the causal relationship but treating the spans
as separate durations.</p>
<h3 id="closing-spans"><a href="#closing-spans">Closing Spans</a></h3>
<p>Execution may enter and exit a span multiple times before that span is
<em>closed</em>. Consider, for example, a future which has an associated
span and enters that span every time it is polled:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">struct </span>MyFuture {
<span class="comment">// data
</span>span: tracing::Span,
}
<span class="kw">impl </span>Future <span class="kw">for </span>MyFuture {
<span class="kw">type </span>Output = ();
<span class="kw">fn </span>poll(<span class="self">self</span>: Pin&lt;<span class="kw-2">&amp;mut </span><span class="self">Self</span>&gt;, _cx: <span class="kw-2">&amp;mut </span>Context&lt;<span class="lifetime">&#39;_</span>&gt;) -&gt; Poll&lt;<span class="self">Self</span>::Output&gt; {
<span class="kw">let </span>_enter = <span class="self">self</span>.span.enter();
<span class="comment">// Do actual future work...
</span>}
}</code></pre></div>
<p>If this future was spawned on an executor, it might yield one or more times
before <code>poll</code> returns <a href="https://doc.rust-lang.org/nightly/core/task/poll/enum.Poll.html#variant.Ready"><code>Poll::Ready</code></a>. If the future were to yield, then
the executor would move on to poll the next future, which may <em>also</em> enter
an associated span or series of spans. Therefore, it is valid for a span to
be entered repeatedly before it completes. Only the time when that span or
one of its children was the current span is considered to be time spent in
that span. A span which is not executing and has not yet been closed is said
to be <em>idle</em>.</p>
<p>Because spans may be entered and exited multiple times before they close,
<a href="../trait.Subscriber.html"><code>Subscriber</code></a>s have separate trait methods which are called to notify them
of span exits and when span handles are dropped. When execution exits a
span, <a href="../trait.Subscriber.html#tymethod.exit"><code>exit</code></a> will always be called with that span’s ID to notify the
subscriber that the span has been exited. When span handles are dropped, the
<a href="../trait.Subscriber.html#method.drop_span"><code>drop_span</code></a> method is called with that span’s ID. The subscriber may use
this to determine whether or not the span will be entered again.</p>
<p>If there is only a single handle with the capacity to exit a span, dropping
that handle “closes” the span, since the capacity to enter it no longer
exists. For example:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code>{
<span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;my_span&quot;</span>).in_scope(|| {
<span class="comment">// perform some work in the context of `my_span`...
</span>}); <span class="comment">// --&gt; Subscriber::exit(my_span)
// The handle to `my_span` only lives inside of this block; when it is
// dropped, the subscriber will be informed via `drop_span`.
</span>} <span class="comment">// --&gt; Subscriber::drop_span(my_span)</span></code></pre></div>
<p>However, if multiple handles exist, the span can still be re-entered even if
one or more is dropped. For determining when <em>all</em> handles to a span have
been dropped, <code>Subscriber</code>s have a <a href="../trait.Subscriber.html#method.clone_span"><code>clone_span</code></a> method, which is called
every time a span handle is cloned. Combined with <code>drop_span</code>, this may be
used to track the number of handles to a given span — if <code>drop_span</code> has
been called one more time than the number of calls to <code>clone_span</code> for a
given ID, then no more handles to the span with that ID exist. The
subscriber may then treat it as closed.</p>
<h2 id="when-to-use-spans"><a href="#when-to-use-spans">When to use spans</a></h2>
<p>As a rule of thumb, spans should be used to represent discrete units of work
(e.g., a given request’s lifetime in a server) or periods of time spent in a
given context (e.g., time spent interacting with an instance of an external
system, such as a database).</p>
<p>Which scopes in a program correspond to new spans depend somewhat on user
intent. For example, consider the case of a loop in a program. Should we
construct one span and perform the entire loop inside of that span, like:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">let </span>span = <span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;my_loop&quot;</span>);
<span class="kw">let </span>_enter = span.enter();
<span class="kw">for </span>i <span class="kw">in </span><span class="number">0</span>..n {
<span class="comment">// ...
</span>}</code></pre></div>
<p>Or, should we create a new span for each iteration of the loop, as in:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">for </span>i <span class="kw">in </span><span class="number">0</span>..n {
<span class="kw">let </span>span = <span class="macro">span!</span>(Level::TRACE, <span class="string">&quot;my_loop&quot;</span>, iteration = i);
<span class="kw">let </span>_enter = span.enter();
<span class="comment">// ...
</span>}</code></pre></div>
<p>Depending on the circumstances, we might want to do either, or both. For
example, if we want to know how long was spent in the loop overall, we would
create a single span around the entire loop; whereas if we wanted to know how
much time was spent in each individual iteration, we would enter a new span
on every iteration.</p>
</div></details><h2 id="structs" class="small-section-header"><a href="#structs">Structs</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Attributes.html" title="tracing::span::Attributes struct">Attributes</a></div><div class="item-right docblock-short">Attributes provided to a <code>Subscriber</code> describing a new span when it is
created.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Entered.html" title="tracing::span::Entered struct">Entered</a></div><div class="item-right docblock-short">A guard representing a span which has been entered and is currently
executing.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.EnteredSpan.html" title="tracing::span::EnteredSpan struct">EnteredSpan</a></div><div class="item-right docblock-short">An owned version of <a href="struct.Entered.html" title="Entered"><code>Entered</code></a>, a guard representing a span which has been
entered and is currently executing.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Id.html" title="tracing::span::Id struct">Id</a></div><div class="item-right docblock-short">Identifies a span within the context of a subscriber.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Record.html" title="tracing::span::Record struct">Record</a></div><div class="item-right docblock-short">A set of fields recorded by a span.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Span.html" title="tracing::span::Span struct">Span</a></div><div class="item-right docblock-short">A handle representing a span, with the capability to enter the span if it
exists.</div></div></div><h2 id="traits" class="small-section-header"><a href="#traits">Traits</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="trait" href="trait.AsId.html" title="tracing::span::AsId trait">AsId</a></div><div class="item-right docblock-short">Trait implemented by types which have a span <code>Id</code>.</div></div></div></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="tracing" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.66.0-nightly (5c8bff74b 2022-10-21)" ></div></body></html>