1 //! Spans represent periods of time in which a program was executing in a 2 //! particular context. 3 //! 4 //! A span consists of [fields], user-defined key-value pairs of arbitrary data 5 //! that describe the context the span represents, and a set of fixed attributes 6 //! that describe all `tracing` spans and events. Attributes describing spans 7 //! include: 8 //! 9 //! - An [`Id`] assigned by the subscriber that uniquely identifies it in relation 10 //! to other spans. 11 //! - The span's [parent] in the trace tree. 12 //! - [Metadata] that describes static characteristics of all spans 13 //! originating from that callsite, such as its name, source code location, 14 //! [verbosity level], and the names of its fields. 15 //! 16 //! # Creating Spans 17 //! 18 //! Spans are created using the [`span!`] macro. This macro is invoked with the 19 //! following arguments, in order: 20 //! 21 //! - The [`target`] and/or [`parent`][parent] attributes, if the user wishes to 22 //! override their default values. 23 //! - The span's [verbosity level] 24 //! - A string literal providing the span's name. 25 //! - Finally, between zero and 32 arbitrary key/value fields. 26 //! 27 //! [`target`]: ../struct.Metadata.html#method.target 28 //! 29 //! For example: 30 //! ```rust 31 //! use tracing::{span, Level}; 32 //! 33 //! /// Construct a new span at the `INFO` level named "my_span", with a single 34 //! /// field named answer , with the value `42`. 35 //! let my_span = span!(Level::INFO, "my_span", answer = 42); 36 //! ``` 37 //! 38 //! The documentation for the [`span!`] macro provides additional examples of 39 //! the various options that exist when creating spans. 40 //! 41 //! The [`trace_span!`], [`debug_span!`], [`info_span!`], [`warn_span!`], and 42 //! [`error_span!`] exist as shorthand for constructing spans at various 43 //! verbosity levels. 44 //! 45 //! ## Recording Span Creation 46 //! 47 //! The [`Attributes`] type contains data associated with a span, and is 48 //! provided to the [`Subscriber`] when a new span is created. It contains 49 //! the span's metadata, the ID of [the span's parent][parent] if one was 50 //! explicitly set, and any fields whose values were recorded when the span was 51 //! constructed. The subscriber, which is responsible for recording `tracing` 52 //! data, can then store or record these values. 53 //! 54 //! # The Span Lifecycle 55 //! 56 //! ## Entering a Span 57 //! 58 //! A thread of execution is said to _enter_ a span when it begins executing, 59 //! and _exit_ the span when it switches to another context. Spans may be 60 //! entered through the [`enter`] and [`in_scope`] methods. 61 //! 62 //! The `enter` method enters a span, returning a [guard] that exits the span 63 //! when dropped 64 //! ``` 65 //! # #[macro_use] extern crate tracing; 66 //! # use tracing::Level; 67 //! let my_var: u64 = 5; 68 //! let my_span = span!(Level::TRACE, "my_span", my_var); 69 //! 70 //! // `my_span` exists but has not been entered. 71 //! 72 //! // Enter `my_span`... 73 //! let _enter = my_span.enter(); 74 //! 75 //! // Perform some work inside of the context of `my_span`... 76 //! // Dropping the `_enter` guard will exit the span. 77 //!``` 78 //! 79 //! <div class="information"> 80 //! <div class="tooltip compile_fail" style="">⚠ ️<span class="tooltiptext">Warning</span></div> 81 //! </div><div class="example-wrap" style="display:inline-block"><pre class="compile_fail" style="white-space:normal;font:inherit;"> 82 //! <strong>Warning</strong>: In asynchronous code that uses async/await syntax, 83 //! <code>Span::enter</code> may produce incorrect traces if the returned drop 84 //! guard is held across an await point. See 85 //! <a href="struct.Span.html#in-asynchronous-code">the method documentation</a> 86 //! for details. 87 //! </pre></div> 88 //! 89 //! `in_scope` takes a closure or function pointer and executes it inside the 90 //! span. 91 //! ``` 92 //! # #[macro_use] extern crate tracing; 93 //! # use tracing::Level; 94 //! let my_var: u64 = 5; 95 //! let my_span = span!(Level::TRACE, "my_span", my_var = &my_var); 96 //! 97 //! my_span.in_scope(|| { 98 //! // perform some work in the context of `my_span`... 99 //! }); 100 //! 101 //! // Perform some work outside of the context of `my_span`... 102 //! 103 //! my_span.in_scope(|| { 104 //! // Perform some more work in the context of `my_span`. 105 //! }); 106 //! ``` 107 //! 108 //! <div class="information"> 109 //! <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div> 110 //! </div> 111 //! <div class="example-wrap" style="display:inline-block"> 112 //! <pre class="ignore" style="white-space:normal;font:inherit;"> 113 //! <strong>Note</strong>: Since entering a span takes <code>&self</code<, and 114 //! <code>Span</code>s are <code>Clone</code>, <code>Send</code>, and 115 //! <code>Sync</code>, it is entirely valid for multiple threads to enter the 116 //! same span concurrently. 117 //! </pre></div> 118 //! 119 //! ## Span Relationships 120 //! 121 //! Spans form a tree structure — unless it is a root span, all spans have a 122 //! _parent_, and may have one or more _children_. When a new span is created, 123 //! the current span becomes the new span's parent. The total execution time of 124 //! a span consists of the time spent in that span and in the entire subtree 125 //! represented by its children. Thus, a parent span always lasts for at least 126 //! as long as the longest-executing span in its subtree. 127 //! 128 //! ``` 129 //! # #[macro_use] extern crate tracing; 130 //! # use tracing::Level; 131 //! // this span is considered the "root" of a new trace tree: 132 //! span!(Level::INFO, "root").in_scope(|| { 133 //! // since we are now inside "root", this span is considered a child 134 //! // of "root": 135 //! span!(Level::DEBUG, "outer_child").in_scope(|| { 136 //! // this span is a child of "outer_child", which is in turn a 137 //! // child of "root": 138 //! span!(Level::TRACE, "inner_child").in_scope(|| { 139 //! // and so on... 140 //! }); 141 //! }); 142 //! // another span created here would also be a child of "root". 143 //! }); 144 //!``` 145 //! 146 //! In addition, the parent of a span may be explicitly specified in 147 //! the `span!` macro. For example: 148 //! 149 //! ```rust 150 //! # #[macro_use] extern crate tracing; 151 //! # use tracing::Level; 152 //! // Create, but do not enter, a span called "foo". 153 //! let foo = span!(Level::INFO, "foo"); 154 //! 155 //! // Create and enter a span called "bar". 156 //! let bar = span!(Level::INFO, "bar"); 157 //! let _enter = bar.enter(); 158 //! 159 //! // Although we have currently entered "bar", "baz"'s parent span 160 //! // will be "foo". 161 //! let baz = span!(parent: &foo, Level::INFO, "baz"); 162 //! ``` 163 //! 164 //! A child span should typically be considered _part_ of its parent. For 165 //! example, if a subscriber is recording the length of time spent in various 166 //! spans, it should generally include the time spent in a span's children as 167 //! part of that span's duration. 168 //! 169 //! In addition to having zero or one parent, a span may also _follow from_ any 170 //! number of other spans. This indicates a causal relationship between the span 171 //! and the spans that it follows from, but a follower is *not* typically 172 //! considered part of the duration of the span it follows. Unlike the parent, a 173 //! span may record that it follows from another span after it is created, using 174 //! the [`follows_from`] method. 175 //! 176 //! As an example, consider a listener task in a server. As the listener accepts 177 //! incoming connections, it spawns new tasks that handle those connections. We 178 //! might want to have a span representing the listener, and instrument each 179 //! spawned handler task with its own span. We would want our instrumentation to 180 //! record that the handler tasks were spawned as a result of the listener task. 181 //! However, we might not consider the handler tasks to be _part_ of the time 182 //! spent in the listener task, so we would not consider those spans children of 183 //! the listener span. Instead, we would record that the handler tasks follow 184 //! from the listener, recording the causal relationship but treating the spans 185 //! as separate durations. 186 //! 187 //! ## Closing Spans 188 //! 189 //! Execution may enter and exit a span multiple times before that span is 190 //! _closed_. Consider, for example, a future which has an associated 191 //! span and enters that span every time it is polled: 192 //! ```rust 193 //! # extern crate tracing; 194 //! # extern crate futures; 195 //! # use futures::{Future, Poll, Async}; 196 //! struct MyFuture { 197 //! // data 198 //! span: tracing::Span, 199 //! } 200 //! 201 //! impl Future for MyFuture { 202 //! type Item = (); 203 //! type Error = (); 204 //! 205 //! fn poll(&mut self) -> Poll<Self::Item, Self::Error> { 206 //! let _enter = self.span.enter(); 207 //! // Do actual future work... 208 //! # Ok(Async::Ready(())) 209 //! } 210 //! } 211 //! ``` 212 //! 213 //! If this future was spawned on an executor, it might yield one or more times 214 //! before `poll` returns `Ok(Async::Ready)`. If the future were to yield, then 215 //! the executor would move on to poll the next future, which may _also_ enter 216 //! an associated span or series of spans. Therefore, it is valid for a span to 217 //! be entered repeatedly before it completes. Only the time when that span or 218 //! one of its children was the current span is considered to be time spent in 219 //! that span. A span which is not executing and has not yet been closed is said 220 //! to be _idle_. 221 //! 222 //! Because spans may be entered and exited multiple times before they close, 223 //! [`Subscriber`]s have separate trait methods which are called to notify them 224 //! of span exits and when span handles are dropped. When execution exits a 225 //! span, [`exit`] will always be called with that span's ID to notify the 226 //! subscriber that the span has been exited. When span handles are dropped, the 227 //! [`drop_span`] method is called with that span's ID. The subscriber may use 228 //! this to determine whether or not the span will be entered again. 229 //! 230 //! If there is only a single handle with the capacity to exit a span, dropping 231 //! that handle "closes" the span, since the capacity to enter it no longer 232 //! exists. For example: 233 //! ``` 234 //! # #[macro_use] extern crate tracing; 235 //! # use tracing::Level; 236 //! { 237 //! span!(Level::TRACE, "my_span").in_scope(|| { 238 //! // perform some work in the context of `my_span`... 239 //! }); // --> Subscriber::exit(my_span) 240 //! 241 //! // The handle to `my_span` only lives inside of this block; when it is 242 //! // dropped, the subscriber will be informed via `drop_span`. 243 //! 244 //! } // --> Subscriber::drop_span(my_span) 245 //! ``` 246 //! 247 //! However, if multiple handles exist, the span can still be re-entered even if 248 //! one or more is dropped. For determining when _all_ handles to a span have 249 //! been dropped, `Subscriber`s have a [`clone_span`] method, which is called 250 //! every time a span handle is cloned. Combined with `drop_span`, this may be 251 //! used to track the number of handles to a given span — if `drop_span` has 252 //! been called one more time than the number of calls to `clone_span` for a 253 //! given ID, then no more handles to the span with that ID exist. The 254 //! subscriber may then treat it as closed. 255 //! 256 //! # When to use spans 257 //! 258 //! As a rule of thumb, spans should be used to represent discrete units of work 259 //! (e.g., a given request's lifetime in a server) or periods of time spent in a 260 //! given context (e.g., time spent interacting with an instance of an external 261 //! system, such as a database). 262 //! 263 //! Which scopes in a program correspond to new spans depend somewhat on user 264 //! intent. For example, consider the case of a loop in a program. Should we 265 //! construct one span and perform the entire loop inside of that span, like: 266 //! 267 //! ```rust 268 //! # #[macro_use] extern crate tracing; 269 //! # use tracing::Level; 270 //! # let n = 1; 271 //! let span = span!(Level::TRACE, "my_loop"); 272 //! let _enter = span.enter(); 273 //! for i in 0..n { 274 //! # let _ = i; 275 //! // ... 276 //! } 277 //! ``` 278 //! Or, should we create a new span for each iteration of the loop, as in: 279 //! ```rust 280 //! # #[macro_use] extern crate tracing; 281 //! # use tracing::Level; 282 //! # let n = 1u64; 283 //! for i in 0..n { 284 //! let span = span!(Level::TRACE, "my_loop", iteration = i); 285 //! let _enter = span.enter(); 286 //! // ... 287 //! } 288 //! ``` 289 //! 290 //! Depending on the circumstances, we might want to do either, or both. For 291 //! example, if we want to know how long was spent in the loop overall, we would 292 //! create a single span around the entire loop; whereas if we wanted to know how 293 //! much time was spent in each individual iteration, we would enter a new span 294 //! on every iteration. 295 //! 296 //! [fields]: ../field/index.html 297 //! [Metadata]: ../struct.Metadata.html 298 //! [`Id`]: struct.Id.html 299 //! [verbosity level]: ../struct.Level.html 300 //! [`span!`]: ../macro.span.html 301 //! [`trace_span!`]: ../macro.trace_span.html 302 //! [`debug_span!`]: ../macro.debug_span.html 303 //! [`info_span!`]: ../macro.info_span.html 304 //! [`warn_span!`]: ../macro.warn_span.html 305 //! [`error_span!`]: ../macro.error_span.html 306 //! [`clone_span`]: ../subscriber/trait.Subscriber.html#method.clone_span 307 //! [`drop_span`]: ../subscriber/trait.Subscriber.html#method.drop_span 308 //! [`exit`]: ../subscriber/trait.Subscriber.html#tymethod.exit 309 //! [`Subscriber`]: ../subscriber/trait.Subscriber.html 310 //! [`Attributes`]: struct.Attributes.html 311 //! [`enter`]: struct.Span.html#method.enter 312 //! [`in_scope`]: struct.Span.html#method.in_scope 313 //! [`follows_from`]: struct.Span.html#method.follows_from 314 //! [guard]: struct.Entered.html 315 //! [parent]: #span-relationships 316 pub use tracing_core::span::{Attributes, Id, Record}; 317 318 use crate::stdlib::{ 319 cmp, fmt, 320 hash::{Hash, Hasher}, 321 }; 322 use crate::{ 323 dispatcher::{self, Dispatch}, 324 field, Metadata, 325 }; 326 327 /// Trait implemented by types which have a span `Id`. 328 pub trait AsId: crate::sealed::Sealed { 329 /// Returns the `Id` of the span that `self` corresponds to, or `None` if 330 /// this corresponds to a disabled span. as_id(&self) -> Option<&Id>331 fn as_id(&self) -> Option<&Id>; 332 } 333 334 /// A handle representing a span, with the capability to enter the span if it 335 /// exists. 336 /// 337 /// If the span was rejected by the current `Subscriber`'s filter, entering the 338 /// span will silently do nothing. Thus, the handle can be used in the same 339 /// manner regardless of whether or not the trace is currently being collected. 340 #[derive(Clone)] 341 pub struct Span { 342 /// A handle used to enter the span when it is not executing. 343 /// 344 /// If this is `None`, then the span has either closed or was never enabled. 345 inner: Option<Inner>, 346 /// Metadata describing the span. 347 /// 348 /// This might be `Some` even if `inner` is `None`, in the case that the 349 /// span is disabled but the metadata is needed for `log` support. 350 meta: Option<&'static Metadata<'static>>, 351 } 352 353 /// A handle representing the capacity to enter a span which is known to exist. 354 /// 355 /// Unlike `Span`, this type is only constructed for spans which _have_ been 356 /// enabled by the current filter. This type is primarily used for implementing 357 /// span handles; users should typically not need to interact with it directly. 358 #[derive(Debug)] 359 pub(crate) struct Inner { 360 /// The span's ID, as provided by `subscriber`. 361 id: Id, 362 363 /// The subscriber that will receive events relating to this span. 364 /// 365 /// This should be the same subscriber that provided this span with its 366 /// `id`. 367 subscriber: Dispatch, 368 } 369 370 /// A guard representing a span which has been entered and is currently 371 /// executing. 372 /// 373 /// When the guard is dropped, the span will be exited. 374 /// 375 /// This is returned by the [`Span::enter`] function. 376 /// 377 /// [`Span::enter`]: ../struct.Span.html#method.enter 378 #[derive(Debug)] 379 #[must_use = "once a span has been entered, it should be exited"] 380 pub struct Entered<'a> { 381 span: &'a Span, 382 } 383 384 /// `log` target for all span lifecycle (creation/enter/exit/close) records. 385 #[cfg(feature = "log")] 386 const LIFECYCLE_LOG_TARGET: &str = "tracing::span"; 387 /// `log` target for span activity (enter/exit) records. 388 #[cfg(feature = "log")] 389 const ACTIVITY_LOG_TARGET: &str = "tracing::span::active"; 390 391 // ===== impl Span ===== 392 393 impl Span { 394 /// Constructs a new `Span` with the given [metadata] and set of 395 /// [field values]. 396 /// 397 /// The new span will be constructed by the currently-active [`Subscriber`], 398 /// with the current span as its parent (if one exists). 399 /// 400 /// After the span is constructed, [field values] and/or [`follows_from`] 401 /// annotations may be added to it. 402 /// 403 /// [metadata]: ../metadata 404 /// [`Subscriber`]: ../subscriber/trait.Subscriber.html 405 /// [field values]: ../field/struct.ValueSet.html 406 /// [`follows_from`]: ../struct.Span.html#method.follows_from new(meta: &'static Metadata<'static>, values: &field::ValueSet<'_>) -> Span407 pub fn new(meta: &'static Metadata<'static>, values: &field::ValueSet<'_>) -> Span { 408 dispatcher::get_default(|dispatch| Self::new_with(meta, values, dispatch)) 409 } 410 411 #[inline] 412 #[doc(hidden)] new_with( meta: &'static Metadata<'static>, values: &field::ValueSet<'_>, dispatch: &Dispatch, ) -> Span413 pub fn new_with( 414 meta: &'static Metadata<'static>, 415 values: &field::ValueSet<'_>, 416 dispatch: &Dispatch, 417 ) -> Span { 418 let new_span = Attributes::new(meta, values); 419 Self::make_with(meta, new_span, dispatch) 420 } 421 422 /// Constructs a new `Span` as the root of its own trace tree, with the 423 /// given [metadata] and set of [field values]. 424 /// 425 /// After the span is constructed, [field values] and/or [`follows_from`] 426 /// annotations may be added to it. 427 /// 428 /// [metadata]: ../metadata 429 /// [field values]: ../field/struct.ValueSet.html 430 /// [`follows_from`]: ../struct.Span.html#method.follows_from new_root(meta: &'static Metadata<'static>, values: &field::ValueSet<'_>) -> Span431 pub fn new_root(meta: &'static Metadata<'static>, values: &field::ValueSet<'_>) -> Span { 432 dispatcher::get_default(|dispatch| Self::new_root_with(meta, values, dispatch)) 433 } 434 435 #[inline] 436 #[doc(hidden)] new_root_with( meta: &'static Metadata<'static>, values: &field::ValueSet<'_>, dispatch: &Dispatch, ) -> Span437 pub fn new_root_with( 438 meta: &'static Metadata<'static>, 439 values: &field::ValueSet<'_>, 440 dispatch: &Dispatch, 441 ) -> Span { 442 let new_span = Attributes::new_root(meta, values); 443 Self::make_with(meta, new_span, dispatch) 444 } 445 446 /// Constructs a new `Span` as child of the given parent span, with the 447 /// given [metadata] and set of [field values]. 448 /// 449 /// After the span is constructed, [field values] and/or [`follows_from`] 450 /// annotations may be added to it. 451 /// 452 /// [metadata]: ../metadata 453 /// [field values]: ../field/struct.ValueSet.html 454 /// [`follows_from`]: ../struct.Span.html#method.follows_from child_of( parent: impl Into<Option<Id>>, meta: &'static Metadata<'static>, values: &field::ValueSet<'_>, ) -> Span455 pub fn child_of( 456 parent: impl Into<Option<Id>>, 457 meta: &'static Metadata<'static>, 458 values: &field::ValueSet<'_>, 459 ) -> Span { 460 let mut parent = parent.into(); 461 dispatcher::get_default(move |dispatch| { 462 Self::child_of_with(Option::take(&mut parent), meta, values, dispatch) 463 }) 464 } 465 466 #[inline] 467 #[doc(hidden)] child_of_with( parent: impl Into<Option<Id>>, meta: &'static Metadata<'static>, values: &field::ValueSet<'_>, dispatch: &Dispatch, ) -> Span468 pub fn child_of_with( 469 parent: impl Into<Option<Id>>, 470 meta: &'static Metadata<'static>, 471 values: &field::ValueSet<'_>, 472 dispatch: &Dispatch, 473 ) -> Span { 474 let new_span = match parent.into() { 475 Some(parent) => Attributes::child_of(parent, meta, values), 476 None => Attributes::new_root(meta, values), 477 }; 478 Self::make_with(meta, new_span, dispatch) 479 } 480 481 /// Constructs a new disabled span with the given `Metadata`. 482 /// 483 /// This should be used when a span is constructed from a known callsite, 484 /// but the subscriber indicates that it is disabled. 485 /// 486 /// Entering, exiting, and recording values on this span will not notify the 487 /// `Subscriber` but _may_ record log messages if the `log` feature flag is 488 /// enabled. 489 #[inline(always)] new_disabled(meta: &'static Metadata<'static>) -> Span490 pub fn new_disabled(meta: &'static Metadata<'static>) -> Span { 491 Self { 492 inner: None, 493 meta: Some(meta), 494 } 495 } 496 497 /// Constructs a new span that is *completely disabled*. 498 /// 499 /// This can be used rather than `Option<Span>` to represent cases where a 500 /// span is not present. 501 /// 502 /// Entering, exiting, and recording values on this span will do nothing. 503 #[inline(always)] none() -> Span504 pub const fn none() -> Span { 505 Self { 506 inner: None, 507 meta: None, 508 } 509 } 510 511 /// Returns a handle to the span [considered by the `Subscriber`] to be the 512 /// current span. 513 /// 514 /// If the subscriber indicates that it does not track the current span, or 515 /// that the thread from which this function is called is not currently 516 /// inside a span, the returned span will be disabled. 517 /// 518 /// [considered by the `Subscriber`]: ../subscriber/trait.Subscriber.html#method.current current() -> Span519 pub fn current() -> Span { 520 dispatcher::get_default(|dispatch| { 521 if let Some((id, meta)) = dispatch.current_span().into_inner() { 522 let id = dispatch.clone_span(&id); 523 Self { 524 inner: Some(Inner::new(id, dispatch)), 525 meta: Some(meta), 526 } 527 } else { 528 Self::none() 529 } 530 }) 531 } 532 make_with( meta: &'static Metadata<'static>, new_span: Attributes<'_>, dispatch: &Dispatch, ) -> Span533 fn make_with( 534 meta: &'static Metadata<'static>, 535 new_span: Attributes<'_>, 536 dispatch: &Dispatch, 537 ) -> Span { 538 let attrs = &new_span; 539 let id = dispatch.new_span(attrs); 540 let inner = Some(Inner::new(id, dispatch)); 541 542 let span = Self { 543 inner, 544 meta: Some(meta), 545 }; 546 547 if_log_enabled! {{ 548 let target = if attrs.is_empty() { 549 LIFECYCLE_LOG_TARGET 550 } else { 551 meta.target() 552 }; 553 span.log(target, level_to_log!(*meta.level()), format_args!("++ {}{}", meta.name(), FmtAttrs(attrs))); 554 }} 555 556 span 557 } 558 /// Enters this span, returning a guard that will exit the span when dropped. 559 /// 560 /// If this span is enabled by the current subscriber, then this function will 561 /// call [`Subscriber::enter`] with the span's [`Id`], and dropping the guard 562 /// will call [`Subscriber::exit`]. If the span is disabled, this does 563 /// nothing. 564 /// 565 /// # In Asynchronous Code 566 /// 567 /// **Warning**: in asynchronous code that uses [async/await syntax][syntax], 568 /// `Span::enter` should be used very carefully or avoided entirely. Holding 569 /// the drop guard returned by `Span::enter` across `.await` points will 570 /// result in incorrect traces. 571 /// 572 /// For example, 573 /// 574 /// ``` 575 /// # use tracing::info_span; 576 /// # async fn some_other_async_function() {} 577 /// async fn my_async_function() { 578 /// let span = info_span!("my_async_function"); 579 /// 580 /// // THIS WILL RESULT IN INCORRECT TRACES 581 /// let _enter = span.enter(); 582 /// some_other_async_function().await; 583 /// 584 /// // ... 585 /// } 586 /// ``` 587 /// 588 /// The drop guard returned by `Span::enter` exits the span when it is 589 /// dropped. When an async function or async block yields at an `.await` 590 /// point, the current scope is _exited_, but values in that scope are 591 /// **not** dropped (because the async block will eventually resume 592 /// execution from that await point). This means that _another_ task will 593 /// begin executing while _remaining_ in the entered span. This results in 594 /// an incorrect trace. 595 /// 596 /// Instead of using `Span::enter` in asynchronous code, prefer the 597 /// following: 598 /// 599 /// * To enter a span for a synchronous section of code within an async 600 /// block or function, prefer [`Span::in_scope`]. Since `in_scope` takes a 601 /// synchronous closure and exits the span when the closure returns, the 602 /// span will always be exited before the next await point. For example: 603 /// ``` 604 /// # use tracing::info_span; 605 /// # async fn some_other_async_function(_: ()) {} 606 /// async fn my_async_function() { 607 /// let span = info_span!("my_async_function"); 608 /// 609 /// let some_value = span.in_scope(|| { 610 /// // run some synchronous code inside the span... 611 /// }); 612 /// 613 /// // This is okay! The span has already been exited before we reach 614 /// // the await point. 615 /// some_other_async_function(some_value).await; 616 /// 617 /// // ... 618 /// } 619 /// ``` 620 /// * For instrumenting asynchronous code, `tracing` provides the 621 /// [`Future::instrument` combinator][instrument] for 622 /// attaching a span to a future (async function or block). This will 623 /// enter the span _every_ time the future is polled, and exit it whenever 624 /// the future yields. 625 /// 626 /// `Instrument` can be used with an async block inside an async function: 627 /// ```ignore 628 /// # use tracing::info_span; 629 /// use tracing::Instrument; 630 /// 631 /// # async fn some_other_async_function() {} 632 /// async fn my_async_function() { 633 /// let span = info_span!("my_async_function"); 634 /// async move { 635 /// // This is correct! If we yield here, the span will be exited, 636 /// // and re-entered when we resume. 637 /// some_other_async_function().await; 638 /// 639 /// //more asynchronous code inside the span... 640 /// 641 /// } 642 /// // instrument the async block with the span... 643 /// .instrument(span) 644 /// // ...and await it. 645 /// .await 646 /// } 647 /// ``` 648 /// 649 /// It can also be used to instrument calls to async functions at the 650 /// callsite: 651 /// ```ignore 652 /// # use tracing::debug_span; 653 /// use tracing::Instrument; 654 /// 655 /// # async fn some_other_async_function() {} 656 /// async fn my_async_function() { 657 /// let some_value = some_other_async_function() 658 /// .instrument(debug_span!("some_other_async_function")) 659 /// .await; 660 /// 661 /// // ... 662 /// } 663 /// ``` 664 /// 665 /// * The [`#[instrument]` attribute macro][attr] can automatically generate 666 /// correct code when used on an async function: 667 /// 668 /// ```ignore 669 /// # async fn some_other_async_function() {} 670 /// #[tracing::instrument(level = "info")] 671 /// async fn my_async_function() { 672 /// 673 /// // This is correct! If we yield here, the span will be exited, 674 /// // and re-entered when we resume. 675 /// some_other_async_function().await; 676 /// 677 /// // ... 678 /// 679 /// } 680 /// ``` 681 /// 682 /// [syntax]: https://rust-lang.github.io/async-book/01_getting_started/04_async_await_primer.html 683 /// [`Span::in_scope`]: #method.in_scope 684 /// [instrument]: https://docs.rs/tracing/latest/tracing/trait.Instrument.html 685 /// [attr]: ../../attr.instrument.html 686 /// 687 /// # Examples 688 /// 689 /// ``` 690 /// #[macro_use] extern crate tracing; 691 /// # use tracing::Level; 692 /// let span = span!(Level::INFO, "my_span"); 693 /// let guard = span.enter(); 694 /// 695 /// // code here is within the span 696 /// 697 /// drop(guard); 698 /// 699 /// // code here is no longer within the span 700 /// 701 /// ``` 702 /// 703 /// Guards need not be explicitly dropped: 704 /// 705 /// ``` 706 /// #[macro_use] extern crate tracing; 707 /// fn my_function() -> String { 708 /// // enter a span for the duration of this function. 709 /// let span = trace_span!("my_function"); 710 /// let _enter = span.enter(); 711 /// 712 /// // anything happening in functions we call is still inside the span... 713 /// my_other_function(); 714 /// 715 /// // returning from the function drops the guard, exiting the span. 716 /// return "Hello world".to_owned(); 717 /// } 718 /// 719 /// fn my_other_function() { 720 /// // ... 721 /// } 722 /// ``` 723 /// 724 /// Sub-scopes may be created to limit the duration for which the span is 725 /// entered: 726 /// 727 /// ``` 728 /// #[macro_use] extern crate tracing; 729 /// let span = info_span!("my_great_span"); 730 /// 731 /// { 732 /// let _enter = span.enter(); 733 /// 734 /// // this event occurs inside the span. 735 /// info!("i'm in the span!"); 736 /// 737 /// // exiting the scope drops the guard, exiting the span. 738 /// } 739 /// 740 /// // this event is not inside the span. 741 /// info!("i'm outside the span!") 742 /// ``` 743 /// 744 /// [`Subscriber::enter`]: ../subscriber/trait.Subscriber.html#method.enter 745 /// [`Subscriber::exit`]: ../subscriber/trait.Subscriber.html#method.exit 746 /// [`Id`]: ../struct.Id.html enter(&self) -> Entered<'_>747 pub fn enter(&self) -> Entered<'_> { 748 if let Some(ref inner) = self.inner.as_ref() { 749 inner.subscriber.enter(&inner.id); 750 } 751 752 if_log_enabled! {{ 753 if let Some(ref meta) = self.meta { 754 self.log(ACTIVITY_LOG_TARGET, log::Level::Trace, format_args!("-> {}", meta.name())); 755 } 756 }} 757 758 Entered { span: self } 759 } 760 761 /// Executes the given function in the context of this span. 762 /// 763 /// If this span is enabled, then this function enters the span, invokes `f` 764 /// and then exits the span. If the span is disabled, `f` will still be 765 /// invoked, but in the context of the currently-executing span (if there is 766 /// one). 767 /// 768 /// Returns the result of evaluating `f`. 769 /// 770 /// # Examples 771 /// 772 /// ``` 773 /// # #[macro_use] extern crate tracing; 774 /// # use tracing::Level; 775 /// let my_span = span!(Level::TRACE, "my_span"); 776 /// 777 /// my_span.in_scope(|| { 778 /// // this event occurs within the span. 779 /// trace!("i'm in the span!"); 780 /// }); 781 /// 782 /// // this event occurs outside the span. 783 /// trace!("i'm not in the span!"); 784 /// ``` 785 /// 786 /// Calling a function and returning the result: 787 /// ``` 788 /// # use tracing::{info_span, Level}; 789 /// fn hello_world() -> String { 790 /// "Hello world!".to_owned() 791 /// } 792 /// 793 /// let span = info_span!("hello_world"); 794 /// // the span will be entered for the duration of the call to 795 /// // `hello_world`. 796 /// let a_string = span.in_scope(hello_world); 797 /// in_scope<F: FnOnce() -> T, T>(&self, f: F) -> T798 pub fn in_scope<F: FnOnce() -> T, T>(&self, f: F) -> T { 799 let _enter = self.enter(); 800 f() 801 } 802 803 /// Returns a [`Field`](../field/struct.Field.html) for the field with the 804 /// given `name`, if one exists, field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field> where Q: field::AsField,805 pub fn field<Q: ?Sized>(&self, field: &Q) -> Option<field::Field> 806 where 807 Q: field::AsField, 808 { 809 self.metadata().and_then(|meta| field.as_field(meta)) 810 } 811 812 /// Returns true if this `Span` has a field for the given 813 /// [`Field`](../field/struct.Field.html) or field name. 814 #[inline] has_field<Q: ?Sized>(&self, field: &Q) -> bool where Q: field::AsField,815 pub fn has_field<Q: ?Sized>(&self, field: &Q) -> bool 816 where 817 Q: field::AsField, 818 { 819 self.field(field).is_some() 820 } 821 822 /// Records that the field described by `field` has the value `value`. 823 /// 824 /// This may be used with [`field::Empty`] to declare fields whose values 825 /// are not known when the span is created, and record them later: 826 /// ``` 827 /// use tracing::{trace_span, field}; 828 /// 829 /// // Create a span with two fields: `greeting`, with the value "hello world", and 830 /// // `parting`, without a value. 831 /// let span = trace_span!("my_span", greeting = "hello world", parting = field::Empty); 832 /// 833 /// // ... 834 /// 835 /// // Now, record a value for parting as well. 836 /// // (note that the field name is passed as a string slice) 837 /// span.record("parting", &"goodbye world!"); 838 /// ``` 839 /// However, it may also be used to record a _new_ value for a field whose 840 /// value was already recorded: 841 /// ``` 842 /// use tracing::info_span; 843 /// # fn do_something() -> Result<(), ()> { Err(()) } 844 /// 845 /// // Initially, let's assume that our attempt to do something is going okay... 846 /// let span = info_span!("doing_something", is_okay = true); 847 /// let _e = span.enter(); 848 /// 849 /// match do_something() { 850 /// Ok(something) => { 851 /// // ... 852 /// } 853 /// Err(_) => { 854 /// // Things are no longer okay! 855 /// span.record("is_okay", &false); 856 /// } 857 /// } 858 /// ``` 859 /// 860 /// <div class="information"> 861 /// <div class="tooltip ignore" style="">ⓘ<span class="tooltiptext">Note</span></div> 862 /// </div> 863 /// <div class="example-wrap" style="display:inline-block"> 864 /// <pre class="ignore" style="white-space:normal;font:inherit;"> 865 /// <strong>Note</strong>: The fields associated with a span are part of its 866 /// <a href="../struct.Metadata.html"><code>Metadata</code></a>. 867 /// The <a href="../struct.Metadata.html"><code>Metadata</code></a>. describing a particular 868 /// span is constructed statically when the span is created and cannot be extended later to 869 /// add new fields. Therefore, you cannot record a value for a field that was not specified 870 /// when the span was created:</pre></div> 871 /// 872 /// ``` 873 /// use tracing::{trace_span, field}; 874 /// 875 /// // Create a span with two fields: `greeting`, with the value "hello world", and 876 /// // `parting`, without a value. 877 /// let span = trace_span!("my_span", greeting = "hello world", parting = field::Empty); 878 /// 879 /// // ... 880 /// 881 /// // Now, you try to record a value for a new field, `new_field`, which was not 882 /// // declared as `Empty` or populated when you created `span`. 883 /// // You won't get any error, but the assignment will have no effect! 884 /// span.record("new_field", &"interesting_value_you_really_need"); 885 /// 886 /// // Instead, all fields that may be recorded after span creation should be declared up front, 887 /// // using field::Empty when a value is not known, as we did for `parting`. 888 /// // This `record` call will indeed replace field::Empty with "you will be remembered". 889 /// span.record("parting", &"you will be remembered"); 890 /// ``` 891 /// 892 /// [`field::Empty`]: ../field/struct.Empty.html 893 /// [`Metadata`]: ../struct.Metadata.html record<Q: ?Sized, V>(&self, field: &Q, value: &V) -> &Self where Q: field::AsField, V: field::Value,894 pub fn record<Q: ?Sized, V>(&self, field: &Q, value: &V) -> &Self 895 where 896 Q: field::AsField, 897 V: field::Value, 898 { 899 if let Some(ref meta) = self.meta { 900 if let Some(field) = field.as_field(meta) { 901 self.record_all( 902 &meta 903 .fields() 904 .value_set(&[(&field, Some(value as &dyn field::Value))]), 905 ); 906 } 907 } 908 909 self 910 } 911 912 /// Records all the fields in the provided `ValueSet`. record_all(&self, values: &field::ValueSet<'_>) -> &Self913 pub fn record_all(&self, values: &field::ValueSet<'_>) -> &Self { 914 let record = Record::new(values); 915 if let Some(ref inner) = self.inner { 916 inner.record(&record); 917 } 918 919 if_log_enabled! {{ 920 if let Some(ref meta) = self.meta { 921 let target = if record.is_empty() { 922 LIFECYCLE_LOG_TARGET 923 } else { 924 meta.target() 925 }; 926 self.log(target, level_to_log!(*meta.level()), format_args!("{}{}", meta.name(), FmtValues(&record))); 927 } 928 }} 929 930 self 931 } 932 933 /// Returns `true` if this span was disabled by the subscriber and does not 934 /// exist. 935 /// 936 /// See also [`is_none`]. 937 /// 938 /// [`is_none`]: #method.is_none 939 #[inline] is_disabled(&self) -> bool940 pub fn is_disabled(&self) -> bool { 941 self.inner.is_none() 942 } 943 944 /// Returns `true` if this span was constructed by [`Span::none`] and is 945 /// empty. 946 /// 947 /// If `is_none` returns `true` for a given span, then [`is_disabled`] will 948 /// also return `true`. However, when a span is disabled by the subscriber 949 /// rather than constructed by `Span::none`, this method will return 950 /// `false`, while `is_disabled` will return `true`. 951 /// 952 /// [`Span::none`]: #method.none 953 /// [`is_disabled`]: #method.is_disabled 954 #[inline] is_none(&self) -> bool955 pub fn is_none(&self) -> bool { 956 self.is_disabled() && self.meta.is_none() 957 } 958 959 /// Indicates that the span with the given ID has an indirect causal 960 /// relationship with this span. 961 /// 962 /// This relationship differs somewhat from the parent-child relationship: a 963 /// span may have any number of prior spans, rather than a single one; and 964 /// spans are not considered to be executing _inside_ of the spans they 965 /// follow from. This means that a span may close even if subsequent spans 966 /// that follow from it are still open, and time spent inside of a 967 /// subsequent span should not be included in the time its precedents were 968 /// executing. This is used to model causal relationships such as when a 969 /// single future spawns several related background tasks, et cetera. 970 /// 971 /// If this span is disabled, or the resulting follows-from relationship 972 /// would be invalid, this function will do nothing. 973 /// 974 /// # Examples 975 /// 976 /// Setting a `follows_from` relationship with a `Span`: 977 /// ``` 978 /// # use tracing::{span, Id, Level, Span}; 979 /// let span1 = span!(Level::INFO, "span_1"); 980 /// let span2 = span!(Level::DEBUG, "span_2"); 981 /// span2.follows_from(span1); 982 /// ``` 983 /// 984 /// Setting a `follows_from` relationship with the current span: 985 /// ``` 986 /// # use tracing::{span, Id, Level, Span}; 987 /// let span = span!(Level::INFO, "hello!"); 988 /// span.follows_from(Span::current()); 989 /// ``` 990 /// 991 /// Setting a `follows_from` relationship with a `Span` reference: 992 /// ``` 993 /// # use tracing::{span, Id, Level, Span}; 994 /// let span = span!(Level::INFO, "hello!"); 995 /// let curr = Span::current(); 996 /// span.follows_from(&curr); 997 /// ``` 998 /// 999 /// Setting a `follows_from` relationship with an `Id`: 1000 /// ``` 1001 /// # use tracing::{span, Id, Level, Span}; 1002 /// let span = span!(Level::INFO, "hello!"); 1003 /// let id = span.id(); 1004 /// span.follows_from(id); 1005 /// ``` follows_from(&self, from: impl Into<Option<Id>>) -> &Self1006 pub fn follows_from(&self, from: impl Into<Option<Id>>) -> &Self { 1007 if let Some(ref inner) = self.inner { 1008 if let Some(from) = from.into() { 1009 inner.follows_from(&from); 1010 } 1011 } 1012 self 1013 } 1014 1015 /// Returns this span's `Id`, if it is enabled. id(&self) -> Option<Id>1016 pub fn id(&self) -> Option<Id> { 1017 self.inner.as_ref().map(Inner::id) 1018 } 1019 1020 /// Returns this span's `Metadata`, if it is enabled. metadata(&self) -> Option<&'static Metadata<'static>>1021 pub fn metadata(&self) -> Option<&'static Metadata<'static>> { 1022 self.meta 1023 } 1024 1025 #[cfg(feature = "log")] 1026 #[inline] log(&self, target: &str, level: log::Level, message: fmt::Arguments<'_>)1027 fn log(&self, target: &str, level: log::Level, message: fmt::Arguments<'_>) { 1028 if let Some(ref meta) = self.meta { 1029 if level_to_log!(*meta.level()) <= log::max_level() { 1030 let logger = log::logger(); 1031 let log_meta = log::Metadata::builder().level(level).target(target).build(); 1032 if logger.enabled(&log_meta) { 1033 if let Some(ref inner) = self.inner { 1034 logger.log( 1035 &log::Record::builder() 1036 .metadata(log_meta) 1037 .module_path(meta.module_path()) 1038 .file(meta.file()) 1039 .line(meta.line()) 1040 .args(format_args!("{}; span={}", message, inner.id.into_u64())) 1041 .build(), 1042 ); 1043 } else { 1044 logger.log( 1045 &log::Record::builder() 1046 .metadata(log_meta) 1047 .module_path(meta.module_path()) 1048 .file(meta.file()) 1049 .line(meta.line()) 1050 .args(message) 1051 .build(), 1052 ); 1053 } 1054 } 1055 } 1056 } 1057 } 1058 1059 /// Invokes a function with a reference to this span's ID and subscriber. 1060 /// 1061 /// if this span is enabled, the provided function is called, and the result is returned. 1062 /// If the span is disabled, the function is not called, and this method returns `None` 1063 /// instead. with_subscriber<T>(&self, f: impl FnOnce((&Id, &Dispatch)) -> T) -> Option<T>1064 pub fn with_subscriber<T>(&self, f: impl FnOnce((&Id, &Dispatch)) -> T) -> Option<T> { 1065 self.inner 1066 .as_ref() 1067 .map(|inner| f((&inner.id, &inner.subscriber))) 1068 } 1069 } 1070 1071 impl cmp::PartialEq for Span { eq(&self, other: &Self) -> bool1072 fn eq(&self, other: &Self) -> bool { 1073 match (&self.meta, &other.meta) { 1074 (Some(this), Some(that)) => { 1075 this.callsite() == that.callsite() && self.inner == other.inner 1076 } 1077 _ => false, 1078 } 1079 } 1080 } 1081 1082 impl Hash for Span { hash<H: Hasher>(&self, hasher: &mut H)1083 fn hash<H: Hasher>(&self, hasher: &mut H) { 1084 self.inner.hash(hasher); 1085 } 1086 } 1087 1088 impl fmt::Debug for Span { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1089 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1090 let mut span = f.debug_struct("Span"); 1091 if let Some(ref meta) = self.meta { 1092 span.field("name", &meta.name()) 1093 .field("level", &meta.level()) 1094 .field("target", &meta.target()); 1095 1096 if let Some(ref inner) = self.inner { 1097 span.field("id", &inner.id()); 1098 } else { 1099 span.field("disabled", &true); 1100 } 1101 1102 if let Some(ref path) = meta.module_path() { 1103 span.field("module_path", &path); 1104 } 1105 1106 if let Some(ref line) = meta.line() { 1107 span.field("line", &line); 1108 } 1109 1110 if let Some(ref file) = meta.file() { 1111 span.field("file", &file); 1112 } 1113 } else { 1114 span.field("none", &true); 1115 } 1116 1117 span.finish() 1118 } 1119 } 1120 1121 impl<'a> Into<Option<&'a Id>> for &'a Span { into(self) -> Option<&'a Id>1122 fn into(self) -> Option<&'a Id> { 1123 self.inner.as_ref().map(|inner| &inner.id) 1124 } 1125 } 1126 1127 impl<'a> Into<Option<Id>> for &'a Span { into(self) -> Option<Id>1128 fn into(self) -> Option<Id> { 1129 self.inner.as_ref().map(Inner::id) 1130 } 1131 } 1132 1133 impl Into<Option<Id>> for Span { into(self) -> Option<Id>1134 fn into(self) -> Option<Id> { 1135 self.inner.as_ref().map(Inner::id) 1136 } 1137 } 1138 1139 impl Drop for Span { drop(&mut self)1140 fn drop(&mut self) { 1141 if let Some(Inner { 1142 ref id, 1143 ref subscriber, 1144 }) = self.inner 1145 { 1146 subscriber.try_close(id.clone()); 1147 } 1148 1149 if_log_enabled!({ 1150 if let Some(ref meta) = self.meta { 1151 self.log( 1152 LIFECYCLE_LOG_TARGET, 1153 log::Level::Trace, 1154 format_args!("-- {}", meta.name()), 1155 ); 1156 } 1157 }) 1158 } 1159 } 1160 1161 // ===== impl Inner ===== 1162 1163 impl Inner { 1164 /// Indicates that the span with the given ID has an indirect causal 1165 /// relationship with this span. 1166 /// 1167 /// This relationship differs somewhat from the parent-child relationship: a 1168 /// span may have any number of prior spans, rather than a single one; and 1169 /// spans are not considered to be executing _inside_ of the spans they 1170 /// follow from. This means that a span may close even if subsequent spans 1171 /// that follow from it are still open, and time spent inside of a 1172 /// subsequent span should not be included in the time its precedents were 1173 /// executing. This is used to model causal relationships such as when a 1174 /// single future spawns several related background tasks, et cetera. 1175 /// 1176 /// If this span is disabled, this function will do nothing. Otherwise, it 1177 /// returns `Ok(())` if the other span was added as a precedent of this 1178 /// span, or an error if this was not possible. follows_from(&self, from: &Id)1179 fn follows_from(&self, from: &Id) { 1180 self.subscriber.record_follows_from(&self.id, &from) 1181 } 1182 1183 /// Returns the span's ID. id(&self) -> Id1184 fn id(&self) -> Id { 1185 self.id.clone() 1186 } 1187 record(&self, values: &Record<'_>)1188 fn record(&self, values: &Record<'_>) { 1189 self.subscriber.record(&self.id, values) 1190 } 1191 new(id: Id, subscriber: &Dispatch) -> Self1192 fn new(id: Id, subscriber: &Dispatch) -> Self { 1193 Inner { 1194 id, 1195 subscriber: subscriber.clone(), 1196 } 1197 } 1198 } 1199 1200 impl cmp::PartialEq for Inner { eq(&self, other: &Self) -> bool1201 fn eq(&self, other: &Self) -> bool { 1202 self.id == other.id 1203 } 1204 } 1205 1206 impl Hash for Inner { hash<H: Hasher>(&self, state: &mut H)1207 fn hash<H: Hasher>(&self, state: &mut H) { 1208 self.id.hash(state); 1209 } 1210 } 1211 1212 impl Clone for Inner { clone(&self) -> Self1213 fn clone(&self) -> Self { 1214 Inner { 1215 id: self.subscriber.clone_span(&self.id), 1216 subscriber: self.subscriber.clone(), 1217 } 1218 } 1219 } 1220 1221 // ===== impl Entered ===== 1222 1223 impl<'a> Drop for Entered<'a> { 1224 #[inline] drop(&mut self)1225 fn drop(&mut self) { 1226 // Dropping the guard exits the span. 1227 // 1228 // Running this behaviour on drop rather than with an explicit function 1229 // call means that spans may still be exited when unwinding. 1230 if let Some(inner) = self.span.inner.as_ref() { 1231 inner.subscriber.exit(&inner.id); 1232 } 1233 1234 if_log_enabled! {{ 1235 if let Some(ref meta) = self.span.meta { 1236 self.span.log(ACTIVITY_LOG_TARGET, log::Level::Trace, format_args!("<- {}", meta.name())); 1237 } 1238 }} 1239 } 1240 } 1241 1242 #[cfg(feature = "log")] 1243 struct FmtValues<'a>(&'a Record<'a>); 1244 1245 #[cfg(feature = "log")] 1246 impl<'a> fmt::Display for FmtValues<'a> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1248 let mut res = Ok(()); 1249 let mut is_first = true; 1250 self.0.record(&mut |k: &field::Field, v: &dyn fmt::Debug| { 1251 res = write!(f, "{} {}={:?}", if is_first { ";" } else { "" }, k, v); 1252 is_first = false; 1253 }); 1254 res 1255 } 1256 } 1257 1258 #[cfg(feature = "log")] 1259 struct FmtAttrs<'a>(&'a Attributes<'a>); 1260 1261 #[cfg(feature = "log")] 1262 impl<'a> fmt::Display for FmtAttrs<'a> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1264 let mut res = Ok(()); 1265 let mut is_first = true; 1266 self.0.record(&mut |k: &field::Field, v: &dyn fmt::Debug| { 1267 res = write!(f, "{} {}={:?}", if is_first { ";" } else { "" }, k, v); 1268 is_first = false; 1269 }); 1270 res 1271 } 1272 } 1273 1274 #[cfg(test)] 1275 mod test { 1276 use super::*; 1277 1278 trait AssertSend: Send {} 1279 impl AssertSend for Span {} 1280 1281 trait AssertSync: Sync {} 1282 impl AssertSync for Span {} 1283 } 1284