tokio_trace/span.rs
1//! Spans represent periods of time in the execution of a program.
2//!
3//! # Entering a Span
4//!
5//! A thread of execution is said to _enter_ a span when it begins executing,
6//! and _exit_ the span when it switches to another context. Spans may be
7//! entered through the [`enter`] method, which enters the target span,
8//! performs a given function (either a closure or a function pointer), exits
9//! the span, and then returns the result.
10//!
11//! Calling `enter` on a span handle enters the span that handle corresponds to,
12//! if the span exists:
13//! ```
14//! # #[macro_use] extern crate tokio_trace;
15//! # use tokio_trace::Level;
16//! # fn main() {
17//! let my_var: u64 = 5;
18//! let my_span = span!(Level::TRACE, "my_span", my_var = &my_var);
19//!
20//! my_span.enter(|| {
21//! // perform some work in the context of `my_span`...
22//! });
23//!
24//! // Perform some work outside of the context of `my_span`...
25//!
26//! my_span.enter(|| {
27//! // Perform some more work in the context of `my_span`.
28//! });
29//! # }
30//! ```
31//!
32//! # The Span Lifecycle
33//!
34//! Execution may enter and exit a span multiple times before that
35//! span is _closed_. Consider, for example, a future which has an associated
36//! span and enters that span every time it is polled:
37//! ```rust
38//! # extern crate tokio_trace;
39//! # extern crate futures;
40//! # use futures::{Future, Poll, Async};
41//! struct MyFuture {
42//! // data
43//! span: tokio_trace::Span,
44//! }
45//!
46//! impl Future for MyFuture {
47//! type Item = ();
48//! type Error = ();
49//!
50//! fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
51//! self.span.enter(|| {
52//! // Do actual future work
53//! # Ok(Async::Ready(()))
54//! })
55//! }
56//! }
57//! ```
58//!
59//! If this future was spawned on an executor, it might yield one or more times
60//! before `poll` returns `Ok(Async::Ready)`. If the future were to yield, then
61//! the executor would move on to poll the next future, which may _also_ enter
62//! an associated span or series of spans. Therefore, it is valid for a span to
63//! be entered repeatedly before it completes. Only the time when that span or
64//! one of its children was the current span is considered to be time spent in
65//! that span. A span which is not executing and has not yet been closed is said
66//! to be _idle_.
67//!
68//! Because spans may be entered and exited multiple times before they close,
69//! [`Subscriber`]s have separate trait methods which are called to notify them
70//! of span exits and when span handles are dropped. When execution exits a
71//! span, [`exit`] will always be called with that span's ID to notify the
72//! subscriber that the span has been exited. When span handles are dropped, the
73//! [`drop_span`] method is called with that span's ID. The subscriber may use
74//! this to determine whether or not the span will be entered again.
75//!
76//! If there is only a single handle with the capacity to exit a span, dropping
77//! that handle "close" the span, since the capacity to enter it no longer
78//! exists. For example:
79//! ```
80//! # #[macro_use] extern crate tokio_trace;
81//! # use tokio_trace::Level;
82//! # fn main() {
83//! {
84//! span!(Level::TRACE, "my_span").enter(|| {
85//! // perform some work in the context of `my_span`...
86//! }); // --> Subscriber::exit(my_span)
87//!
88//! // The handle to `my_span` only lives inside of this block; when it is
89//! // dropped, the subscriber will be informed via `drop_span`.
90//!
91//! } // --> Subscriber::drop_span(my_span)
92//! # }
93//! ```
94//!
95//! However, if multiple handles exist, the span can still be re-entered even if
96//! one or more is dropped. For determining when _all_ handles to a span have
97//! been dropped, `Subscriber`s have a [`clone_span`] method, which is called
98//! every time a span handle is cloned. Combined with `drop_span`, this may be
99//! used to track the number of handles to a given span — if `drop_span` has
100//! been called one more time than the number of calls to `clone_span` for a
101//! given ID, then no more handles to the span with that ID exist. The
102//! subscriber may then treat it as closed.
103//!
104//! # Accessing a Span's Attributes
105//!
106//! The [`Attributes`] type represents a *non-entering* reference to a `Span`'s data
107//! — a set of key-value pairs (known as _fields_), a creation timestamp,
108//! a reference to the span's parent in the trace tree, and metadata describing
109//! the source code location where the span was created. This data is provided
110//! to the [`Subscriber`] when the span is created; it may then choose to cache
111//! the data for future use, record it in some manner, or discard it completely.
112//!
113//! [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span
114//! [`drop_span`]: ../subscriber/trait.Subscriber.html#method.drop_span
115//! [`exit`]: ../subscriber/trait.Subscriber.html#tymethod.exit
116//! [`Subscriber`]: ../subscriber/trait.Subscriber.html
117//! [`Attributes`]: struct.Attributes.html
118//! [`enter`]: struct.Span.html#method.enter
119pub use tokio_trace_core::span::{Attributes, Id, Record};
120
121use std::{
122 cmp, fmt,
123 hash::{Hash, Hasher},
124};
125use {dispatcher::Dispatch, field, Metadata};
126
127/// Trait implemented by types which have a span `Id`.
128pub trait AsId: ::sealed::Sealed {
129 /// Returns the `Id` of the span that `self` corresponds to, or `None` if
130 /// this corresponds to a disabled span.
131 fn as_id(&self) -> Option<&Id>;
132}
133
134/// A handle representing a span, with the capability to enter the span if it
135/// exists.
136///
137/// If the span was rejected by the current `Subscriber`'s filter, entering the
138/// span will silently do nothing. Thus, the handle can be used in the same
139/// manner regardless of whether or not the trace is currently being collected.
140#[derive(Clone)]
141pub struct Span {
142 /// A handle used to enter the span when it is not executing.
143 ///
144 /// If this is `None`, then the span has either closed or was never enabled.
145 inner: Option<Inner>,
146 meta: &'static Metadata<'static>,
147}
148
149/// A handle representing the capacity to enter a span which is known to exist.
150///
151/// Unlike `Span`, this type is only constructed for spans which _have_ been
152/// enabled by the current filter. This type is primarily used for implementing
153/// span handles; users should typically not need to interact with it directly.
154#[derive(Debug)]
155pub(crate) struct Inner {
156 /// The span's ID, as provided by `subscriber`.
157 id: Id,
158
159 /// The subscriber that will receive events relating to this span.
160 ///
161 /// This should be the same subscriber that provided this span with its
162 /// `id`.
163 subscriber: Dispatch,
164}
165
166/// A guard representing a span which has been entered and is currently
167/// executing.
168///
169/// This guard may be used to exit the span, returning an `Enter` to
170/// re-enter it.
171///
172/// This type is primarily used for implementing span handles; users should
173/// typically not need to interact with it directly.
174#[derive(Debug)]
175#[must_use = "once a span has been entered, it should be exited"]
176struct Entered<'a> {
177 inner: &'a Inner,
178}
179
180// ===== impl Span =====
181
182impl Span {
183 /// Constructs a new `Span` with the given [metadata] and set of
184 /// [field values].
185 ///
186 /// The new span will be constructed by the currently-active [`Subscriber`],
187 /// with the current span as its parent (if one exists).
188 ///
189 /// After the span is constructed, [field values] and/or [`follows_from`]
190 /// annotations may be added to it.
191 ///
192 /// [metadata]: ../metadata
193 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html
194 /// [field values]: ../field/struct.ValueSet.html
195 /// [`follows_from`]: ../struct.Span.html#method.follows_from
196 #[inline]
197 pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
198 let new_span = Attributes::new(meta, values);
199 Self::make(meta, new_span)
200 }
201
202 /// Constructs a new `Span` as the root of its own trace tree, with the
203 /// given [metadata] and set of [field values].
204 ///
205 /// After the span is constructed, [field values] and/or [`follows_from`]
206 /// annotations may be added to it.
207 ///
208 /// [metadata]: ../metadata
209 /// [field values]: ../field/struct.ValueSet.html
210 /// [`follows_from`]: ../struct.Span.html#method.follows_from
211 #[inline]
212 pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet) -> Span {
213 Self::make(meta, Attributes::new_root(meta, values))
214 }
215
216 /// Constructs a new `Span` as child of the given parent span, with the
217 /// given [metadata] and set of [field values].
218 ///
219 /// After the span is constructed, [field values] and/or [`follows_from`]
220 /// annotations may be added to it.
221 ///
222 /// [metadata]: ../metadata
223 /// [field values]: ../field/struct.ValueSet.html
224 /// [`follows_from`]: ../struct.Span.html#method.follows_from
225 pub fn child_of<I>(
226 parent: I,
227 meta: &'static Metadata<'static>,
228 values: &field::ValueSet,
229 ) -> Span
230 where
231 I: AsId,
232 {
233 let new_span = match parent.as_id() {
234 Some(parent) => Attributes::child_of(parent.clone(), meta, values),
235 None => Attributes::new_root(meta, values),
236 };
237 Self::make(meta, new_span)
238 }
239
240 /// Constructs a new disabled span.
241 #[inline(always)]
242 pub fn new_disabled(meta: &'static Metadata<'static>) -> Span {
243 Span { inner: None, meta }
244 }
245
246 fn make(meta: &'static Metadata<'static>, new_span: Attributes) -> Span {
247 let attrs = &new_span;
248 let inner = ::dispatcher::get_default(move |dispatch| {
249 let id = dispatch.new_span(attrs);
250 Some(Inner::new(id, dispatch))
251 });
252 let span = Self { inner, meta };
253 span.log(format_args!("{}; {}", meta.name(), FmtAttrs(&new_span)));
254 span
255 }
256
257 /// Executes the given function in the context of this span.
258 ///
259 /// If this span is enabled, then this function enters the span, invokes
260 /// and then exits the span. If the span is disabled, `f` will still be
261 /// invoked, but in the context of the currently-executing span (if there is
262 /// one).
263 ///
264 /// Returns the result of evaluating `f`.
265 pub fn enter<F: FnOnce() -> T, T>(&self, f: F) -> T {
266 self.log(format_args!("-> {}", self.meta.name));
267 let _enter = self.inner.as_ref().map(Inner::enter);
268 let result = f();
269 self.log(format_args!("<- {}", self.meta.name));
270 result
271 }
272
273 /// Returns a [`Field`](../field/struct.Field.html) for the field with the
274 /// given `name`, if one exists,
275 pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field>
276 where
277 Q: field::AsField,
278 {
279 self.metadata().and_then(|meta| field.as_field(meta))
280 }
281
282 /// Returns true if this `Span` has a field for the given
283 /// [`Field`](../field/struct.Field.html) or field name.
284 #[inline]
285 pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool
286 where
287 Q: field::AsField,
288 {
289 self.field(field).is_some()
290 }
291
292 /// Visits that the field described by `field` has the value `value`.
293 pub fn record<Q: ?Sized, V>(&self, field: &Q, value: &V) -> &Self
294 where
295 Q: field::AsField,
296 V: field::Value,
297 {
298 if let Some(field) = field.as_field(self.meta) {
299 self.record_all(
300 &self
301 .meta
302 .fields()
303 .value_set(&[(&field, Some(value as &field::Value))]),
304 );
305 }
306
307 self
308 }
309
310 /// Visit all the fields in the span
311 pub fn record_all(&self, values: &field::ValueSet) -> &Self {
312 let record = Record::new(values);
313 if let Some(ref inner) = self.inner {
314 inner.record(&record);
315 }
316 self.log(format_args!("{}; {}", self.meta.name(), FmtValues(&record)));
317 self
318 }
319
320 /// Returns `true` if this span was disabled by the subscriber and does not
321 /// exist.
322 #[inline]
323 pub fn is_disabled(&self) -> bool {
324 self.inner.is_none()
325 }
326
327 /// Indicates that the span with the given ID has an indirect causal
328 /// relationship with this span.
329 ///
330 /// This relationship differs somewhat from the parent-child relationship: a
331 /// span may have any number of prior spans, rather than a single one; and
332 /// spans are not considered to be executing _inside_ of the spans they
333 /// follow from. This means that a span may close even if subsequent spans
334 /// that follow from it are still open, and time spent inside of a
335 /// subsequent span should not be included in the time its precedents were
336 /// executing. This is used to model causal relationships such as when a
337 /// single future spawns several related background tasks, et cetera.
338 ///
339 /// If this span is disabled, or the resulting follows-from relationship
340 /// would be invalid, this function will do nothing.
341 pub fn follows_from<I>(&self, from: I) -> &Self
342 where
343 I: AsId,
344 {
345 if let Some(ref inner) = self.inner {
346 if let Some(from) = from.as_id() {
347 inner.follows_from(from);
348 }
349 }
350 self
351 }
352
353 /// Returns this span's `Id`, if it is enabled.
354 pub fn id(&self) -> Option<Id> {
355 self.inner.as_ref().map(Inner::id)
356 }
357
358 /// Returns this span's `Metadata`, if it is enabled.
359 pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
360 if self.inner.is_some() {
361 Some(self.meta)
362 } else {
363 None
364 }
365 }
366
367 #[cfg(feature = "log")]
368 #[inline]
369 fn log(&self, message: fmt::Arguments) {
370 use log;
371 let logger = log::logger();
372 let log_meta = log::Metadata::builder()
373 .level(level_to_log!(self.meta.level))
374 .target(self.meta.target)
375 .build();
376 if logger.enabled(&log_meta) {
377 logger.log(
378 &log::Record::builder()
379 .metadata(log_meta)
380 .module_path(self.meta.module_path)
381 .file(self.meta.file)
382 .line(self.meta.line)
383 .args(message)
384 .build(),
385 );
386 }
387 }
388
389 #[cfg(not(feature = "log"))]
390 #[inline]
391 fn log(&self, _: fmt::Arguments) {}
392}
393
394impl cmp::PartialEq for Span {
395 fn eq(&self, other: &Self) -> bool {
396 self.meta.callsite() == other.meta.callsite() && self.inner == other.inner
397 }
398}
399
400impl Hash for Span {
401 fn hash<H: Hasher>(&self, hasher: &mut H) {
402 self.inner.hash(hasher);
403 }
404}
405
406impl fmt::Debug for Span {
407 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408 let mut span = f.debug_struct("Span");
409 span.field("name", &self.meta.name())
410 .field("level", &self.meta.level())
411 .field("target", &self.meta.target());
412
413 if let Some(ref inner) = self.inner {
414 span.field("id", &inner.id());
415 } else {
416 span.field("disabled", &true);
417 }
418
419 if let Some(ref path) = self.meta.module_path() {
420 span.field("module_path", &path);
421 }
422
423 if let Some(ref line) = self.meta.line() {
424 span.field("line", &line);
425 }
426
427 if let Some(ref file) = self.meta.file() {
428 span.field("file", &file);
429 }
430
431 span.finish()
432 }
433}
434
435// ===== impl Inner =====
436
437impl Inner {
438 /// Enters the span, returning a guard that may be used to exit the span and
439 /// re-enter the prior span.
440 ///
441 /// This is used internally to implement `Span::enter`. It may be used for
442 /// writing custom span handles, but should generally not be called directly
443 /// when entering a span.
444 #[inline]
445 fn enter(&self) -> Entered {
446 self.subscriber.enter(&self.id);
447 Entered { inner: self }
448 }
449
450 /// Indicates that the span with the given ID has an indirect causal
451 /// relationship with this span.
452 ///
453 /// This relationship differs somewhat from the parent-child relationship: a
454 /// span may have any number of prior spans, rather than a single one; and
455 /// spans are not considered to be executing _inside_ of the spans they
456 /// follow from. This means that a span may close even if subsequent spans
457 /// that follow from it are still open, and time spent inside of a
458 /// subsequent span should not be included in the time its precedents were
459 /// executing. This is used to model causal relationships such as when a
460 /// single future spawns several related background tasks, et cetera.
461 ///
462 /// If this span is disabled, this function will do nothing. Otherwise, it
463 /// returns `Ok(())` if the other span was added as a precedent of this
464 /// span, or an error if this was not possible.
465 fn follows_from(&self, from: &Id) {
466 self.subscriber.record_follows_from(&self.id, &from)
467 }
468
469 /// Returns the span's ID.
470 fn id(&self) -> Id {
471 self.id.clone()
472 }
473
474 fn record(&self, values: &Record) {
475 self.subscriber.record(&self.id, values)
476 }
477
478 fn new(id: Id, subscriber: &Dispatch) -> Self {
479 Inner {
480 id,
481 subscriber: subscriber.clone(),
482 }
483 }
484}
485
486impl cmp::PartialEq for Inner {
487 fn eq(&self, other: &Self) -> bool {
488 self.id == other.id
489 }
490}
491
492impl Hash for Inner {
493 fn hash<H: Hasher>(&self, state: &mut H) {
494 self.id.hash(state);
495 }
496}
497
498impl Drop for Inner {
499 fn drop(&mut self) {
500 self.subscriber.drop_span(self.id.clone());
501 }
502}
503
504impl Clone for Inner {
505 fn clone(&self) -> Self {
506 Inner {
507 id: self.subscriber.clone_span(&self.id),
508 subscriber: self.subscriber.clone(),
509 }
510 }
511}
512
513// ===== impl Entered =====
514
515impl<'a> Drop for Entered<'a> {
516 #[inline]
517 fn drop(&mut self) {
518 // Dropping the guard exits the span.
519 //
520 // Running this behaviour on drop rather than with an explicit function
521 // call means that spans may still be exited when unwinding.
522 self.inner.subscriber.exit(&self.inner.id);
523 }
524}
525
526struct FmtValues<'a>(&'a Record<'a>);
527
528impl<'a> fmt::Display for FmtValues<'a> {
529 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
530 let mut res = Ok(());
531 self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
532 res = write!(f, "{}={:?} ", k, v);
533 });
534 res
535 }
536}
537
538struct FmtAttrs<'a>(&'a Attributes<'a>);
539
540impl<'a> fmt::Display for FmtAttrs<'a> {
541 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
542 let mut res = Ok(());
543 self.0.record(&mut |k: &field::Field, v: &fmt::Debug| {
544 res = write!(f, "{}={:?} ", k, v);
545 });
546 res
547 }
548}
549
550// ===== impl AsId =====
551
552impl ::sealed::Sealed for Span {}
553
554impl AsId for Span {
555 fn as_id(&self) -> Option<&Id> {
556 self.inner.as_ref().map(|inner| &inner.id)
557 }
558}
559
560impl<'a> ::sealed::Sealed for &'a Span {}
561
562impl<'a> AsId for &'a Span {
563 fn as_id(&self) -> Option<&Id> {
564 self.inner.as_ref().map(|inner| &inner.id)
565 }
566}
567
568impl ::sealed::Sealed for Id {}
569
570impl AsId for Id {
571 fn as_id(&self) -> Option<&Id> {
572 Some(self)
573 }
574}
575
576impl<'a> ::sealed::Sealed for &'a Id {}
577
578impl<'a> AsId for &'a Id {
579 fn as_id(&self) -> Option<&Id> {
580 Some(self)
581 }
582}
583
584impl ::sealed::Sealed for Option<Id> {}
585
586impl AsId for Option<Id> {
587 fn as_id(&self) -> Option<&Id> {
588 self.as_ref()
589 }
590}
591
592impl<'a> ::sealed::Sealed for &'a Option<Id> {}
593
594impl<'a> AsId for &'a Option<Id> {
595 fn as_id(&self) -> Option<&Id> {
596 self.as_ref()
597 }
598}
599
600#[cfg(test)]
601mod test {
602 use super::*;
603
604 trait AssertSend: Send {}
605 impl AssertSend for Span {}
606
607 trait AssertSync: Sync {}
608 impl AssertSync for Span {}
609}