tracing-futures-0.2.5/.cargo_vcs_info.json0000644000000001121401303311100141750ustar { "git": { "sha1": "f8b7d699977025743e4a5a97e4f2a11e388c2700" } } tracing-futures-0.2.5/CHANGELOG.md010064400017500000144000000035101401303307000146140ustar 00000000000000# 0.2.5 (February 16, 2021) ### Changed - Updated `pin-project` dependency to 1.0 ([#1038]) ### Fixed - Several documentation fixes and improvements ([#832], [#911], [#913], [#941], [#953], [#981]) [#1038]: https://github.com/tokio-rs/tracing/pulls/1038 [#832]: https://github.com/tokio-rs/tracing/pulls/832 [#911]: https://github.com/tokio-rs/tracing/pulls/911 [#913]: https://github.com/tokio-rs/tracing/pulls/913 [#941]: https://github.com/tokio-rs/tracing/pulls/941 [#953]: https://github.com/tokio-rs/tracing/pulls/953 [#981]: https://github.com/tokio-rs/tracing/pulls/981 # 0.2.4 (April 21, 2020) ### Fixed - docs.rs build failures (#618) - Spelling in documentation skins -> sinks (#643) # 0.2.3 (Feb 26, 2020) ### Added - `WithDispatch::inner` and `WithDispatch::inner_mut` methods to allow borrowing the wrapped type (#589) - `WithDispatch::with_dispatch` method, to propagate the subscriber to another type (#589) - `inner_pin_ref` and `inner_pin_mut` methods to `Instrumented` and `WithDispatch` to project to the inner future when pinned (#590) # 0.2.2 (Feb 14, 2020) ### Added - Support for `futures` 0.3 `Stream`s and `Sink`s (#544) ### Fixed - Compilation errors when using the `futures-03` feature (#576) Thanks to @obergner and @najamelan for their contributions to this release! # 0.2.1 (Jan 15, 2020) ### Added - API documentation now shows which features are required by feature-flagged items (#523) - `no_std` support (#498) # 0.2.0 (Dec 3, 2019) ### Changed - **Breaking Change**: the default `Future` implementation comes from the `std-future` feature. Compatibility with futures v0.1 is available via the `futures-01` feature. # 0.1.1 (Oct 25, 2019) ### Added - `Instrumented::inner` and `inner_mut` methods that expose access to the instrumented future (#386) # 0.1.0 (Oct 8, 2019) - Initial release tracing-futures-0.2.5/Cargo.toml0000644000000036211401303311100122030ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "tracing-futures" version = "0.2.5" authors = ["Eliza Weisman ", "Tokio Contributors "] description = "Utilities for instrumenting `futures` with `tracing`.\n" homepage = "https://tokio.rs" readme = "README.md" keywords = ["logging", "profiling", "tracing", "futures", "async"] categories = ["development-tools::debugging", "development-tools::profiling", "asynchronous"] license = "MIT" repository = "https://github.com/tokio-rs/tracing" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies.futures] version = "0.3.0" optional = true [dependencies.futures-task] version = "0.3" optional = true [dependencies.futures_01] version = "0.1" optional = true package = "futures" [dependencies.pin-project] version = "1.0" optional = true [dependencies.tokio] version = "0.1" optional = true [dependencies.tokio-executor] version = "0.1" optional = true [dependencies.tracing] version = "0.1" default-features = false [dev-dependencies.tokio] version = "0.1.22" [dev-dependencies.tokio-test] version = "0.2" [dev-dependencies.tracing-core] version = "0.1.2" [features] default = ["std-future", "std"] futures-01 = ["futures_01", "std"] futures-03 = ["std-future", "futures", "futures-task", "std"] std = ["tracing/std"] std-future = ["pin-project"] [badges.maintenance] status = "actively-developed" tracing-futures-0.2.5/Cargo.toml.orig010064400017500000144000000025601401303307000156760ustar 00000000000000[package] name = "tracing-futures" version = "0.2.5" authors = ["Eliza Weisman ", "Tokio Contributors "] edition = "2018" repository = "https://github.com/tokio-rs/tracing" readme = "README.md" homepage = "https://tokio.rs" description = """ Utilities for instrumenting `futures` with `tracing`. """ categories = [ "development-tools::debugging", "development-tools::profiling", "asynchronous", ] keywords = ["logging", "profiling", "tracing", "futures", "async"] license = "MIT" [features] default = ["std-future", "std"] futures-01 = ["futures_01", "std"] futures-03 = ["std-future", "futures", "futures-task", "std"] std-future = ["pin-project"] std = ["tracing/std"] [dependencies] futures_01 = { package = "futures", version = "0.1", optional = true } futures = { version = "0.3.0", optional = true } futures-task = { version = "0.3", optional = true } pin-project = { version = "1.0", optional = true } tracing = { path = "../tracing", version = "0.1", default-features = false } tokio-executor = { version = "0.1", optional = true } tokio = { version = "0.1", optional = true } [dev-dependencies] tokio = "0.1.22" tokio-test = "0.2" tracing-core = { path = "../tracing-core", version = "0.1.2" } [badges] maintenance = { status = "actively-developed" } [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] tracing-futures-0.2.5/LICENSE010064400017500000144000000020461371263424100140270ustar 00000000000000Copyright (c) 2019 Tokio Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tracing-futures-0.2.5/README.md010064400017500000144000000065441401303307000142740ustar 00000000000000![Tracing — Structured, application-level diagnostics][splash] [splash]: https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/splash.svg # tracing-futures Utilities for instrumenting futures-based code with [`tracing`]. [![Crates.io][crates-badge]][crates-url] [![Documentation][docs-badge]][docs-url] [![Documentation (master)][docs-master-badge]][docs-master-url] [![MIT licensed][mit-badge]][mit-url] [![Build Status][actions-badge]][actions-url] [![Discord chat][discord-badge]][discord-url] ![maintenance status][maint-badge] [Documentation][docs-url] | [Chat][discord-url] [crates-badge]: https://img.shields.io/crates/v/tracing-futures.svg [crates-url]: https://crates.io/crates/tracing-futures/0.2.5 [docs-badge]: https://docs.rs/tracing-futures/badge.svg [docs-url]: https://docs.rs/tracing-futures/0.2.5/tracing_futures [docs-master-badge]: https://img.shields.io/badge/docs-master-blue [docs-master-url]: https://tracing-rs.netlify.com/tracing_futures [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg [mit-url]: LICENSE [actions-badge]: https://github.com/tokio-rs/tracing/workflows/CI/badge.svg [actions-url]:https://github.com/tokio-rs/tracing/actions?query=workflow%3ACI [discord-badge]: https://img.shields.io/discord/500028886025895936?logo=discord&label=discord&logoColor=white [discord-url]: https://discord.gg/EeF3cQw [maint-badge]: https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg ## Overview [`tracing`] is a framework for instrumenting Rust programs to collect structured, event-based diagnostic information. This crate provides utilities for using `tracing` to instrument asynchronous code written using futures and async/await. The crate provides the following traits: * [`Instrument`] allows a `tracing` [span] to be attached to a future, sink, stream, or executor. * [`WithSubscriber`] allows a `tracing` [`Subscriber`] to be attached to a future, sink, stream, or executor. [`Instrument`]: https://docs.rs/tracing-futures/0.2.5/tracing_futures/trait.Instrument.html [`WithSubscriber`]: https://docs.rs/tracing-futures/0.2.5/tracing_futures/trait.WithSubscriber.html [span]: https://docs.rs/tracing/latest/tracing/span/index.html [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/index.html [`tracing`]: https://crates.io/tracing *Compiler support: [requires `rustc` 1.42+][msrv]* [msrv]: #supported-rust-versions ## Supported Rust Versions Tracing is built against the latest stable release. The minimum supported version is 1.42. The current Tracing version is not guaranteed to build on Rust versions earlier than the minimum supported version. Tracing follows the same compiler support policies as the rest of the Tokio project. The current stable Rust compiler and the three most recent minor versions before it will always be supported. For example, if the current stable compiler version is 1.45, the minimum supported version will not be increased past 1.42, three minor versions prior. Increasing the minimum supported compiler version is not considered a semver breaking change as long as doing so complies with this policy. ## License This project is licensed under the [MIT license](LICENSE). ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Tracing by you, shall be licensed as MIT, without any additional terms or conditions. tracing-futures-0.2.5/src/executor/futures_01.rs010064400017500000144000000317241366773164000200310ustar 00000000000000use crate::{Instrument, Instrumented, WithDispatch}; use futures_01::{ future::{ExecuteError, Executor}, Future, }; macro_rules! deinstrument_err { ($e:expr) => { $e.map_err(|e| { let kind = e.kind(); let future = e.into_future().inner; ExecuteError::new(kind, future) }) }; } impl Executor for Instrumented where T: Executor>, F: Future, { fn execute(&self, future: F) -> Result<(), ExecuteError> { let future = future.instrument(self.span.clone()); deinstrument_err!(self.inner.execute(future)) } } impl Executor for WithDispatch where T: Executor>, F: Future, { fn execute(&self, future: F) -> Result<(), ExecuteError> { let future = self.with_dispatch(future); deinstrument_err!(self.inner.execute(future)) } } #[cfg(feature = "tokio")] #[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 pub use self::tokio::*; #[cfg(feature = "tokio")] mod tokio { use crate::{Instrument, Instrumented, WithDispatch}; use futures_01::Future; use tokio::{ executor::{Executor, SpawnError, TypedExecutor}, runtime::{current_thread, Runtime, TaskExecutor}, }; impl Executor for Instrumented where T: Executor, { fn spawn( &mut self, future: Box + 'static + Send>, ) -> Result<(), SpawnError> { // TODO: get rid of double box somehow? let future = Box::new(future.instrument(self.span.clone())); self.inner.spawn(future) } } impl TypedExecutor for Instrumented where T: TypedExecutor>, { fn spawn(&mut self, future: F) -> Result<(), SpawnError> { self.inner.spawn(future.instrument(self.span.clone())) } fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl Instrumented { /// Spawn an instrumented future onto the Tokio runtime. /// /// This spawns the given future onto the runtime's executor, usually a /// thread pool. The thread pool is then responsible for polling the /// future until it completes. /// /// This method simply wraps a call to `tokio::runtime::Runtime::spawn`, /// instrumenting the spawned future beforehand. pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + Send + 'static, { let future = future.instrument(self.span.clone()); self.inner.spawn(future); self } /// Run an instrumented future to completion on the Tokio runtime. /// /// This runs the given future on the runtime, blocking until it is /// complete, and yielding its resolved result. Any tasks or timers which /// the future spawns internally will be executed on the runtime. /// /// This method should not be called from an asynchronous context. /// /// This method simply wraps a call to `tokio::runtime::Runtime::block_on`, /// instrumenting the spawned future beforehand. /// /// # Panics /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. pub fn block_on(&mut self, future: F) -> Result where F: Send + 'static + Future, R: Send + 'static, E: Send + 'static, { let future = future.instrument(self.span.clone()); self.inner.block_on(future) } /// Return an instrumented handle to the runtime's executor. /// /// The returned handle can be used to spawn tasks that run on this runtime. /// /// The instrumented handle functions identically to a /// `tokio::runtime::TaskExecutor`, but instruments the spawned /// futures prior to spawning them. pub fn executor(&self) -> Instrumented { self.inner.executor().instrument(self.span.clone()) } } impl Instrumented { /// Spawn an instrumented future onto the single-threaded Tokio runtime. /// /// This method simply wraps a call to `current_thread::Runtime::spawn`, /// instrumenting the spawned future beforehand. pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + 'static, { let future = future.instrument(self.span.clone()); self.inner.spawn(future); self } /// Instruments and runs the provided future, blocking the current thread /// until the future completes. /// /// This function can be used to synchronously block the current thread /// until the provided `future` has resolved either successfully or with an /// error. The result of the future is then returned from this function /// call. /// /// Note that this function will **also** execute any spawned futures on the /// current thread, but will **not** block until these other spawned futures /// have completed. Once the function returns, any uncompleted futures /// remain pending in the `Runtime` instance. These futures will not run /// until `block_on` or `run` is called again. /// /// The caller is responsible for ensuring that other spawned futures /// complete execution by calling `block_on` or `run`. /// /// This method simply wraps a call to `current_thread::Runtime::block_on`, /// instrumenting the spawned future beforehand. /// /// # Panics /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. pub fn block_on(&mut self, future: F) -> Result where F: 'static + Future, R: 'static, E: 'static, { let future = future.instrument(self.span.clone()); self.inner.block_on(future) } /// Get a new instrumented handle to spawn futures on the single-threaded /// Tokio runtime /// /// Different to the runtime itself, the handle can be sent to different /// threads. /// /// The instrumented handle functions identically to a /// `tokio::runtime::current_thread::Handle`, but instruments the spawned /// futures prior to spawning them. pub fn handle(&self) -> Instrumented { self.inner.handle().instrument(self.span.clone()) } } impl Executor for WithDispatch where T: Executor, { fn spawn( &mut self, future: Box + 'static + Send>, ) -> Result<(), SpawnError> { // TODO: get rid of double box? let future = Box::new(self.with_dispatch(future)); self.inner.spawn(future) } } impl TypedExecutor for WithDispatch where T: TypedExecutor>, { fn spawn(&mut self, future: F) -> Result<(), SpawnError> { self.inner.spawn(self.with_dispatch(future)) } fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl WithDispatch { /// Spawn a future onto the Tokio runtime, in the context of this /// `WithDispatch`'s trace dispatcher. /// /// This spawns the given future onto the runtime's executor, usually a /// thread pool. The thread pool is then responsible for polling the /// future until it completes. /// /// This method simply wraps a call to `tokio::runtime::Runtime::spawn`, /// instrumenting the spawned future beforehand. pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + Send + 'static, { let future = self.with_dispatch(future); self.inner.spawn(future); self } /// Run a future to completion on the Tokio runtime, in the context of this /// `WithDispatch`'s trace dispatcher. /// /// This runs the given future on the runtime, blocking until it is /// complete, and yielding its resolved result. Any tasks or timers which /// the future spawns internally will be executed on the runtime. /// /// This method should not be called from an asynchronous context. /// /// This method simply wraps a call to `tokio::runtime::Runtime::block_on`, /// instrumenting the spawned future beforehand. /// /// # Panics /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. pub fn block_on(&mut self, future: F) -> Result where F: Send + 'static + Future, R: Send + 'static, E: Send + 'static, { let future = self.with_dispatch(future); self.inner.block_on(future) } /// Return a handle to the runtime's executor, in the context of this /// `WithDispatch`'s trace dispatcher. /// /// The returned handle can be used to spawn tasks that run on this runtime. /// /// The instrumented handle functions identically to a /// `tokio::runtime::TaskExecutor`, but instruments the spawned /// futures prior to spawning them. pub fn executor(&self) -> WithDispatch { self.with_dispatch(self.inner.executor()) } } impl WithDispatch { /// Spawn a future onto the single-threaded Tokio runtime, in the context /// of this `WithDispatch`'s trace dispatcher. /// /// This method simply wraps a call to `current_thread::Runtime::spawn`, /// instrumenting the spawned future beforehand. pub fn spawn(&mut self, future: F) -> &mut Self where F: Future + 'static, { let future = self.with_dispatch(future); self.inner.spawn(future); self } /// Runs the provided future in the context of this `WithDispatch`'s trace /// dispatcher, blocking the current thread until the future completes. /// /// This function can be used to synchronously block the current thread /// until the provided `future` has resolved either successfully or with an /// error. The result of the future is then returned from this function /// call. /// /// Note that this function will **also** execute any spawned futures on the /// current thread, but will **not** block until these other spawned futures /// have completed. Once the function returns, any uncompleted futures /// remain pending in the `Runtime` instance. These futures will not run /// until `block_on` or `run` is called again. /// /// The caller is responsible for ensuring that other spawned futures /// complete execution by calling `block_on` or `run`. /// /// This method simply wraps a call to `current_thread::Runtime::block_on`, /// instrumenting the spawned future beforehand. /// /// # Panics /// /// This function panics if the executor is at capacity, if the provided /// future panics, or if called within an asynchronous execution context. pub fn block_on(&mut self, future: F) -> Result where F: 'static + Future, R: 'static, E: 'static, { let future = self.with_dispatch(future); self.inner.block_on(future) } /// Get a new handle to spawn futures on the single-threaded Tokio runtime, /// in the context of this `WithDispatch`'s trace dispatcher.\ /// /// Different to the runtime itself, the handle can be sent to different /// threads. /// /// The instrumented handle functions identically to a /// `tokio::runtime::current_thread::Handle`, but the spawned /// futures are run in the context of the trace dispatcher. pub fn handle(&self) -> WithDispatch { self.with_dispatch(self.inner.handle()) } } } tracing-futures-0.2.5/src/executor/futures_03.rs010064400017500000144000000101241366773164000200220ustar 00000000000000use crate::{Instrument, Instrumented, WithDispatch}; use futures_task::{FutureObj, LocalFutureObj, LocalSpawn, Spawn, SpawnError}; impl Spawn for Instrumented where T: Spawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { let future = future.instrument(self.span.clone()); self.inner.spawn_obj(FutureObj::new(Box::new(future))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl Spawn for WithDispatch where T: Spawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_obj(&self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { self.inner .spawn_obj(FutureObj::new(Box::new(self.with_dispatch(future)))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl LocalSpawn for Instrumented where T: LocalSpawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { let future = future.instrument(self.span.clone()); self.inner .spawn_local_obj(LocalFutureObj::new(Box::new(future))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status_local(&self) -> Result<(), SpawnError> { self.inner.status_local() } } impl LocalSpawn for WithDispatch where T: LocalSpawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_local_obj(&self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { self.inner .spawn_local_obj(LocalFutureObj::new(Box::new(self.with_dispatch(future)))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status_local(&self) -> Result<(), SpawnError> { self.inner.status_local() } } tracing-futures-0.2.5/src/executor/futures_preview.rs010064400017500000144000000100611401302506500212400ustar 00000000000000use crate::stdlib::future::Future; use crate::{Instrument, Instrumented, WithDispatch}; use futures_core_preview::{ future::FutureObj, task::{LocalSpawn, Spawn, SpawnError}, }; impl Spawn for Instrumented where T: Spawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_obj(&mut self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { let future = future.instrument(self.span.clone()); self.inner.spawn_obj(Box::pin(future)) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl Spawn for WithDispatch where T: Spawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_obj(&mut self, future: FutureObj<'static, ()>) -> Result<(), SpawnError> { self.inner.spawn_obj(Box::pin(self.with_dispatch(future))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status(&self) -> Result<(), SpawnError> { self.inner.status() } } impl LocalSpawn for Instrumented where T: LocalSpawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { let future = future.instrument(self.span.clone()); self.inner.spawn_local_obj(Box::pin(future)) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status_local(&self) -> Result<(), SpawnError> { self.inner.status_local() } } impl LocalSpawn for WithDispatch where T: Spawn, { /// Spawns a future that will be run to completion. /// /// # Errors /// /// The executor may be unable to spawn tasks. Spawn errors should /// represent relatively rare scenarios, such as the executor /// having been shut down so that it is no longer able to accept /// tasks. fn spawn_local_obj(&mut self, future: LocalFutureObj<'static, ()>) -> Result<(), SpawnError> { self.inner .spawn_local_obj(Box::pin(self.with_dispatch(future))) } /// Determines whether the executor is able to spawn new tasks. /// /// This method will return `Ok` when the executor is *likely* /// (but not guaranteed) to accept a subsequent spawn attempt. /// Likewise, an `Err` return means that `spawn` is likely, but /// not guaranteed, to yield an error. #[inline] fn status_local(&self) -> Result<(), SpawnError> { self.inner.status_local() } } tracing-futures-0.2.5/src/executor/mod.rs010064400017500000144000000005271366773164000166100ustar 00000000000000#[cfg(feature = "futures-01")] mod futures_01; #[cfg(feature = "futures-01")] pub use self::futures_01::*; #[cfg(feature = "futures_preview")] mod futures_preview; #[cfg(feature = "futures_preview")] pub use self::futures_preview::*; #[cfg(feature = "futures-03")] mod futures_03; #[cfg(feature = "futures-03")] pub use self::futures_03::*; tracing-futures-0.2.5/src/lib.rs010064400017500000144000000573421401303307000147220ustar 00000000000000//! Futures compatibility for [`tracing`]. //! //! # Overview //! //! [`tracing`] is a framework for instrumenting Rust programs to collect //! structured, event-based diagnostic information. This crate provides utilities //! for using `tracing` to instrument asynchronous code written using futures and //! async/await. //! //! The crate provides the following traits: //! //! * [`Instrument`] allows a `tracing` [span] to be attached to a future, sink, //! stream, or executor. //! //! * [`WithSubscriber`] allows a `tracing` [`Subscriber`] to be attached to a //! future, sink, stream, or executor. //! //! *Compiler support: [requires `rustc` 1.42+][msrv]* //! //! [msrv]: #supported-rust-versions //! //! # Feature flags //! //! This crate provides a number of feature flags that enable compatibility //! features with other crates in the asynchronous ecosystem: //! //! - `tokio`: Enables compatibility with the `tokio` crate, including //! [`Instrument`] and [`WithSubscriber`] implementations for //! `tokio::executor::Executor`, `tokio::runtime::Runtime`, and //! `tokio::runtime::current_thread`. Enabled by default. //! - `tokio-executor`: Enables compatibility with the `tokio-executor` //! crate, including [`Instrument`] and [`WithSubscriber`] //! implementations for types implementing `tokio_executor::Executor`. //! This is intended primarily for use in crates which depend on //! `tokio-executor` rather than `tokio`; in general the `tokio` feature //! should be used instead. //! - `std-future`: Enables compatibility with `std::future::Future`. //! - `futures-01`: Enables compatibility with version 0.1.x of the [`futures`] //! crate. //! - `futures-03`: Enables compatibility with version 0.3.x of the `futures` //! crate's `Spawn` and `LocalSpawn` traits. //! - `tokio-alpha`: Enables compatibility with `tokio` 0.2's alpha releases, //! including the `tokio` 0.2 `Executor` and `TypedExecutor` traits. //! - `std`: Depend on the Rust standard library. //! //! `no_std` users may disable this feature with `default-features = false`: //! //! ```toml //! [dependencies] //! tracing-futures = { version = "0.2.5", default-features = false } //! ``` //! //! The `tokio`, `std-future` and `std` features are enabled by default. //! //! [`tracing`]: https://crates.io/crates/tracing //! [span]: https://docs.rs/tracing/latest/tracing/span/index.html //! [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/index.html //! [`Instrument`]: trait.Instrument.html //! [`WithSubscriber`]: trait.WithSubscriber.html //! [`futures`]: https://crates.io/crates/futures //! //! ## Supported Rust Versions //! //! Tracing is built against the latest stable release. The minimum supported //! version is 1.42. The current Tracing version is not guaranteed to build on //! Rust versions earlier than the minimum supported version. //! //! Tracing follows the same compiler support policies as the rest of the Tokio //! project. The current stable Rust compiler and the three most recent minor //! versions before it will always be supported. For example, if the current //! stable compiler version is 1.45, the minimum supported version will not be //! increased past 1.42, three minor versions prior. Increasing the minimum //! supported compiler version is not considered a semver breaking change as //! long as doing so complies with this policy. //! #![doc(html_root_url = "https://docs.rs/tracing-futures/0.2.5")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] #![warn( missing_debug_implementations, missing_docs, rust_2018_idioms, unreachable_pub, bad_style, const_err, dead_code, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, path_statements, patterns_in_fns_without_body, private_in_public, unconditional_recursion, unused, unused_allocation, unused_comparisons, unused_parens, while_true )] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] #[cfg(feature = "std-future")] use pin_project::pin_project; pub(crate) mod stdlib; #[cfg(feature = "std-future")] use crate::stdlib::{pin::Pin, task::Context}; #[cfg(feature = "std")] use tracing::{dispatcher, Dispatch}; use tracing::Span; /// Implementations for `Instrument`ed future executors. pub mod executor; /// Extension trait allowing futures, streams, sinks, and executors to be /// instrumented with a `tracing` [span]. /// /// [span]: https://docs.rs/tracing/latest/tracing/span/index.html pub trait Instrument: Sized { /// Instruments this type with the provided `Span`, returning an /// `Instrumented` wrapper. /// /// If the instrumented type is a future, stream, or sink, the attached `Span` /// will be [entered] every time it is polled. If the instrumented type /// is a future executor, every future spawned on that executor will be /// instrumented by the attached `Span`. /// /// # Examples /// /// Instrumenting a future: /// // TODO: ignored until async-await is stable... /// ```rust,ignore /// use tracing_futures::Instrument; /// /// # async fn doc() { /// let my_future = async { /// // ... /// }; /// /// my_future /// .instrument(tracing::info_span!("my_future")) /// .await /// # } /// ``` /// /// [entered]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.enter fn instrument(self, span: Span) -> Instrumented { Instrumented { inner: self, span } } /// Instruments this type with the [current] `Span`, returning an /// `Instrumented` wrapper. /// /// If the instrumented type is a future, stream, or sink, the attached `Span` /// will be [entered] every time it is polled. If the instrumented type /// is a future executor, every future spawned on that executor will be /// instrumented by the attached `Span`. /// /// This can be used to propagate the current span when spawning a new future. /// /// # Examples /// // TODO: ignored until async-await is stable... /// ```rust,ignore /// use tracing_futures::Instrument; /// /// # async fn doc() { /// let span = tracing::info_span!("my_span"); /// let _enter = span.enter(); /// /// // ... /// /// let future = async { /// tracing::debug!("this event will occur inside `my_span`"); /// // ... /// }; /// tokio::spawn(future.in_current_span()); /// # } /// ``` /// /// [current]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.current /// [entered]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.enter #[inline] fn in_current_span(self) -> Instrumented { self.instrument(Span::current()) } } /// Extension trait allowing futures, streams, and sinks to be instrumented with /// a `tracing` [`Subscriber`]. /// /// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub trait WithSubscriber: Sized { /// Attaches the provided [`Subscriber`] to this type, returning a /// `WithDispatch` wrapper. /// /// When the wrapped type is a future, stream, or sink, the attached /// subscriber will be set as the [default] while it is being polled. /// When the wrapped type is an executor, the subscriber will be set as the /// default for any futures spawned on that executor. /// /// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber fn with_subscriber(self, subscriber: S) -> WithDispatch where S: Into, { WithDispatch { inner: self, dispatch: subscriber.into(), } } /// Attaches the current [default] [`Subscriber`] to this type, returning a /// `WithDispatch` wrapper. /// /// When the wrapped type is a future, stream, or sink, the attached /// subscriber will be set as the [default] while it is being polled. /// When the wrapped type is an executor, the subscriber will be set as the /// default for any futures spawned on that executor. /// /// This can be used to propagate the current dispatcher context when /// spawning a new future. /// /// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber #[inline] fn with_current_subscriber(self) -> WithDispatch { WithDispatch { inner: self, dispatch: dispatcher::get_default(|default| default.clone()), } } } /// A future, stream, sink, or executor that has been instrumented with a `tracing` span. #[cfg_attr(feature = "std-future", pin_project)] #[derive(Debug, Clone)] pub struct Instrumented { #[cfg(feature = "std-future")] #[pin] inner: T, #[cfg(not(feature = "std-future"))] inner: T, span: Span, } /// A future, stream, sink, or executor that has been instrumented with a /// `tracing` subscriber. #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(feature = "std-future", pin_project)] #[derive(Clone, Debug)] pub struct WithDispatch { // cfg_attr doesn't work inside structs, apparently... #[cfg(feature = "std-future")] #[pin] inner: T, #[cfg(not(feature = "std-future"))] inner: T, dispatch: Dispatch, } impl Instrument for T {} #[cfg(feature = "std-future")] #[cfg_attr(docsrs, doc(cfg(feature = "std-future")))] impl crate::stdlib::future::Future for Instrumented { type Output = T::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> crate::stdlib::task::Poll { let this = self.project(); let _enter = this.span.enter(); this.inner.poll(cx) } } #[cfg(feature = "futures-01")] #[cfg_attr(docsrs, doc(cfg(feature = "futures-01")))] impl futures_01::Future for Instrumented { type Item = T::Item; type Error = T::Error; fn poll(&mut self) -> futures_01::Poll { let _enter = self.span.enter(); self.inner.poll() } } #[cfg(feature = "futures-01")] #[cfg_attr(docsrs, doc(cfg(feature = "futures-01")))] impl futures_01::Stream for Instrumented { type Item = T::Item; type Error = T::Error; fn poll(&mut self) -> futures_01::Poll, Self::Error> { let _enter = self.span.enter(); self.inner.poll() } } #[cfg(feature = "futures-01")] #[cfg_attr(docsrs, doc(cfg(feature = "futures-01")))] impl futures_01::Sink for Instrumented { type SinkItem = T::SinkItem; type SinkError = T::SinkError; fn start_send( &mut self, item: Self::SinkItem, ) -> futures_01::StartSend { let _enter = self.span.enter(); self.inner.start_send(item) } fn poll_complete(&mut self) -> futures_01::Poll<(), Self::SinkError> { let _enter = self.span.enter(); self.inner.poll_complete() } } #[cfg(all(feature = "futures-03", feature = "std-future"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "futures-03", feature = "std-future"))))] impl futures::Stream for Instrumented { type Item = T::Item; fn poll_next( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> futures::task::Poll> { let this = self.project(); let _enter = this.span.enter(); T::poll_next(this.inner, cx) } } #[cfg(all(feature = "futures-03", feature = "std-future"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "futures-03", feature = "std-future"))))] impl> futures::Sink for Instrumented where T: futures::Sink, { type Error = T::Error; fn poll_ready( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> futures::task::Poll> { let this = self.project(); let _enter = this.span.enter(); T::poll_ready(this.inner, cx) } fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> { let this = self.project(); let _enter = this.span.enter(); T::start_send(this.inner, item) } fn poll_flush( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> futures::task::Poll> { let this = self.project(); let _enter = this.span.enter(); T::poll_flush(this.inner, cx) } fn poll_close( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> futures::task::Poll> { let this = self.project(); let _enter = this.span.enter(); T::poll_close(this.inner, cx) } } impl Instrumented { /// Borrows the `Span` that this type is instrumented by. pub fn span(&self) -> &Span { &self.span } /// Mutably borrows the `Span` that this type is instrumented by. pub fn span_mut(&mut self) -> &mut Span { &mut self.span } /// Borrows the wrapped type. pub fn inner(&self) -> &T { &self.inner } /// Mutably borrows the wrapped type. pub fn inner_mut(&mut self) -> &mut T { &mut self.inner } /// Get a pinned reference to the wrapped type. #[cfg(feature = "std-future")] #[cfg_attr(docsrs, doc(cfg(feature = "std-future")))] pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { self.project_ref().inner } /// Get a pinned mutable reference to the wrapped type. #[cfg(feature = "std-future")] #[cfg_attr(docsrs, doc(cfg(feature = "std-future")))] pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { self.project().inner } /// Consumes the `Instrumented`, returning the wrapped type. /// /// Note that this drops the span. pub fn into_inner(self) -> T { self.inner } } #[cfg(feature = "std")] impl WithSubscriber for T {} #[cfg(all(feature = "futures-01", feature = "std"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "futures-01", feature = "std"))))] impl futures_01::Future for WithDispatch { type Item = T::Item; type Error = T::Error; fn poll(&mut self) -> futures_01::Poll { let inner = &mut self.inner; dispatcher::with_default(&self.dispatch, || inner.poll()) } } #[cfg(all(feature = "std-future", feature = "std"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std-future", feature = "std"))))] impl crate::stdlib::future::Future for WithDispatch { type Output = T::Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> crate::stdlib::task::Poll { let this = self.project(); let dispatch = this.dispatch; let future = this.inner; dispatcher::with_default(dispatch, || future.poll(cx)) } } #[cfg(feature = "std")] impl WithDispatch { /// Wrap a future, stream, sink or executor with the same subscriber as this WithDispatch. pub fn with_dispatch(&self, inner: U) -> WithDispatch { WithDispatch { dispatch: self.dispatch.clone(), inner, } } /// Borrows the `Dispatch` that this type is instrumented by. pub fn dispatch(&self) -> &Dispatch { &self.dispatch } /// Get a pinned reference to the wrapped type. #[cfg(feature = "std-future")] #[cfg_attr(docsrs, doc(cfg(feature = "std-future")))] pub fn inner_pin_ref(self: Pin<&Self>) -> Pin<&T> { self.project_ref().inner } /// Get a pinned mutable reference to the wrapped type. #[cfg(feature = "std-future")] #[cfg_attr(docsrs, doc(cfg(feature = "std-future")))] pub fn inner_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { self.project().inner } /// Borrows the wrapped type. pub fn inner(&self) -> &T { &self.inner } /// Mutably borrows the wrapped type. pub fn inner_mut(&mut self) -> &mut T { &mut self.inner } /// Consumes the `WithDispatch`, returning the wrapped type. pub fn into_inner(self) -> T { self.inner } } #[cfg(test)] pub(crate) use self::support as test_support; // This has to have the same name as the module in `tracing`. #[path = "../../tracing/tests/support/mod.rs"] #[cfg(test)] #[allow(unreachable_pub)] pub(crate) mod support; #[cfg(test)] mod tests { use super::{test_support::*, *}; #[cfg(feature = "futures-01")] mod futures_01_tests { use futures_01::{future, stream, task, Async, Future, Stream}; use tracing::subscriber::with_default; use super::*; struct PollN { and_return: Option>, finish_at: usize, polls: usize, } impl PollN<(), ()> { fn new_ok(finish_at: usize) -> Self { Self { and_return: Some(Ok(())), finish_at, polls: 0, } } fn new_err(finish_at: usize) -> Self { Self { and_return: Some(Err(())), finish_at, polls: 0, } } } impl futures_01::Future for PollN { type Item = T; type Error = E; fn poll(&mut self) -> futures_01::Poll { self.polls += 1; if self.polls == self.finish_at { self.and_return .take() .expect("polled after ready") .map(Async::Ready) } else { task::current().notify(); Ok(Async::NotReady) } } } #[test] fn future_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .done() .run_with_handle(); with_default(subscriber, || { PollN::new_ok(2) .instrument(tracing::trace_span!("foo")) .wait() .unwrap(); }); handle.assert_finished(); } #[test] fn future_error_ends_span() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .done() .run_with_handle(); with_default(subscriber, || { PollN::new_err(2) .instrument(tracing::trace_span!("foo")) .wait() .unwrap_err(); }); handle.assert_finished(); } #[test] fn stream_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .run_with_handle(); with_default(subscriber, || { stream::iter_ok::<_, ()>(&[1, 2, 3]) .instrument(tracing::trace_span!("foo")) .for_each(|_| future::ok(())) .wait() .unwrap(); }); handle.assert_finished(); } #[test] fn span_follows_future_onto_threadpool() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("a")) .enter(span::mock().named("b")) .exit(span::mock().named("b")) .enter(span::mock().named("b")) .exit(span::mock().named("b")) .drop_span(span::mock().named("b")) .exit(span::mock().named("a")) .drop_span(span::mock().named("a")) .done() .run_with_handle(); let mut runtime = tokio::runtime::Runtime::new().unwrap(); with_default(subscriber, || { tracing::trace_span!("a").in_scope(|| { let future = PollN::new_ok(2) .instrument(tracing::trace_span!("b")) .map(|_| { tracing::trace_span!("c").in_scope(|| { // "c" happens _outside_ of the instrumented future's // span, so we don't expect it. }) }); runtime.block_on(Box::new(future)).unwrap(); }) }); handle.assert_finished(); } } #[cfg(all(feature = "futures-03", feature = "std-future"))] mod futures_03_tests { use futures::{future, sink, stream, FutureExt, SinkExt, StreamExt}; use tracing::subscriber::with_default; use super::*; #[test] fn stream_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .run_with_handle(); with_default(subscriber, || { Instrument::instrument(stream::iter(&[1, 2, 3]), tracing::trace_span!("foo")) .for_each(|_| future::ready(())) .now_or_never() .unwrap(); }); handle.assert_finished(); } #[test] fn sink_enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .run_with_handle(); with_default(subscriber, || { Instrument::instrument(sink::drain(), tracing::trace_span!("foo")) .send(1u8) .now_or_never() .unwrap() .unwrap() }); handle.assert_finished(); } } } tracing-futures-0.2.5/src/stdlib.rs010064400017500000144000000025261401302506500154340ustar 00000000000000//! Re-exports either the Rust `std` library or `core` and `alloc` when `std` is //! disabled. //! //! `crate::stdlib::...` should be used rather than `std::` when adding code that //! will be available with the standard library disabled. //! //! Note that this module is called `stdlib` rather than `std`, as Rust 1.34.0 //! does not permit redefining the name `stdlib` (although this works on the //! latest stable Rust). #[cfg(feature = "std")] pub(crate) use std::*; #[cfg(not(feature = "std"))] pub(crate) use self::no_std::*; #[cfg(not(feature = "std"))] mod no_std { // We pre-emptively export everything from libcore/liballoc, (even modules // we aren't using currently) to make adding new code easier. Therefore, // some of these imports will be unused. #![allow(unused_imports)] pub(crate) use core::{ any, array, ascii, cell, char, clone, cmp, convert, default, f32, f64, ffi, future, hash, hint, i128, i16, i8, isize, iter, marker, mem, num, ops, option, pin, ptr, result, task, time, u128, u16, u32, u8, usize, }; pub(crate) mod borrow { pub(crate) use core::borrow::*; } pub(crate) mod fmt { pub(crate) use core::fmt::*; } pub(crate) mod slice { pub(crate) use core::slice::*; } pub(crate) mod str { pub(crate) use core::str::*; } } tracing-futures-0.2.5/tests/std_future.rs010064400017500000144000000022571401302506500167130ustar 00000000000000mod support; use support::*; use tracing::Instrument; use tracing::{subscriber::with_default, Level}; #[test] fn enter_exit_is_reasonable() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .done() .run_with_handle(); with_default(subscriber, || { let future = PollN::new_ok(2).instrument(tracing::span!(Level::TRACE, "foo")); block_on_future(future).unwrap(); }); handle.assert_finished(); } #[test] fn error_ends_span() { let (subscriber, handle) = subscriber::mock() .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .enter(span::mock().named("foo")) .exit(span::mock().named("foo")) .drop_span(span::mock().named("foo")) .done() .run_with_handle(); with_default(subscriber, || { let future = PollN::new_err(2).instrument(tracing::span!(Level::TRACE, "foo")); block_on_future(future).unwrap_err(); }); handle.assert_finished(); } tracing-futures-0.2.5/tests/support.rs010064400017500000144000000026761366773164000162710ustar 00000000000000// this is the only way to make the path attribute play nice with `in // crate::support`... #[allow(clippy::module_inception)] #[path = "../../tracing/tests/support/mod.rs"] mod support; use std::{ future::Future, pin::Pin, task::{Context, Poll}, }; pub use support::*; use tokio_test::task; pub struct PollN { and_return: Option>, finish_at: usize, polls: usize, } impl std::future::Future for PollN where T: Unpin, E: Unpin, { type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { let this = self.get_mut(); this.polls += 1; if this.polls == this.finish_at { let value = this.and_return.take().expect("polled after ready"); Poll::Ready(value) } else { cx.waker().wake_by_ref(); Poll::Pending } } } impl PollN<(), ()> { pub fn new_ok(finish_at: usize) -> Self { Self { and_return: Some(Ok(())), finish_at, polls: 0, } } pub fn new_err(finish_at: usize) -> Self { Self { and_return: Some(Err(())), finish_at, polls: 0, } } } pub fn block_on_future(future: F) -> F::Output where F: Future, { let mut task = task::spawn(future); loop { if let Poll::Ready(v) = task.poll() { break v; } } }