Movatterモバイル変換


[0]ホーム

URL:


Docs.rs

tracing_futures/
lib.rs

1//! Futures compatibility for [`tracing`].2//!3//! # Overview4//!5//! [`tracing`] is a framework for instrumenting Rust programs to collect6//! structured, event-based diagnostic information. This crate provides utilities7//! for using `tracing` to instrument asynchronous code written using futures and8//! async/await.9//!10//! The crate provides the following traits:11//!12//! * [`Instrument`] allows a `tracing` [span] to be attached to a future, sink,13//!   stream, or executor.14//!15//! * [`WithSubscriber`] allows a `tracing` [`Subscriber`] to be attached to a16//!   future, sink, stream, or executor.17//!18//! *Compiler support: [requires `rustc` 1.42+][msrv]*19//!20//! [msrv]: #supported-rust-versions21//!22//! # Feature flags23//!24//! This crate provides a number of feature flags that enable compatibility25//! features with other crates in the asynchronous ecosystem:26//!27//! - `tokio`: Enables compatibility with the `tokio` crate, including28//!    [`Instrument`] and [`WithSubscriber`] implementations for29//!    `tokio::executor::Executor`, `tokio::runtime::Runtime`, and30//!    `tokio::runtime::current_thread`. Enabled by default.31//! - `tokio-executor`: Enables compatibility with the `tokio-executor`32//!    crate, including [`Instrument`] and [`WithSubscriber`]33//!    implementations for types implementing `tokio_executor::Executor`.34//!    This is intended primarily for use in crates which depend on35//!    `tokio-executor` rather than `tokio`; in general the `tokio` feature36//!    should be used instead.37//! - `std-future`: Enables compatibility with `std::future::Future`.38//! - `futures-01`: Enables compatibility with version 0.1.x of the [`futures`]39//!   crate.40//! - `futures-03`: Enables compatibility with version 0.3.x of the `futures`41//!   crate's `Spawn` and `LocalSpawn` traits.42//! - `tokio-alpha`: Enables compatibility with `tokio` 0.2's alpha releases,43//!   including the `tokio` 0.2 `Executor` and `TypedExecutor` traits.44//! - `std`: Depend on the Rust standard library.45//!46//!   `no_std` users may disable this feature with `default-features = false`:47//!48//!   ```toml49//!   [dependencies]50//!   tracing-futures = { version = "0.2.5", default-features = false }51//!   ```52//!53//! The `tokio`, `std-future` and `std` features are enabled by default.54//!55//! [`tracing`]: https://crates.io/crates/tracing56//! [span]: https://docs.rs/tracing/latest/tracing/span/index.html57//! [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/index.html58//! [`Instrument`]: trait.Instrument.html59//! [`WithSubscriber`]: trait.WithSubscriber.html60//! [`futures`]: https://crates.io/crates/futures61//!62//! ## Supported Rust Versions63//!64//! Tracing is built against the latest stable release. The minimum supported65//! version is 1.42. The current Tracing version is not guaranteed to build on66//! Rust versions earlier than the minimum supported version.67//!68//! Tracing follows the same compiler support policies as the rest of the Tokio69//! project. The current stable Rust compiler and the three most recent minor70//! versions before it will always be supported. For example, if the current71//! stable compiler version is 1.45, the minimum supported version will not be72//! increased past 1.42, three minor versions prior. Increasing the minimum73//! supported compiler version is not considered a semver breaking change as74//! long as doing so complies with this policy.75//!76#![doc(html_root_url ="https://docs.rs/tracing-futures/0.2.5")]77#![doc(78    html_logo_url ="https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",79    issue_tracker_base_url ="https://github.com/tokio-rs/tracing/issues/"80)]81#![warn(82    missing_debug_implementations,83    missing_docs,84    rust_2018_idioms,85    unreachable_pub,86    bad_style,87    const_err,88    dead_code,89    improper_ctypes,90    non_shorthand_field_patterns,91    no_mangle_generic_items,92    overflowing_literals,93    path_statements,94    patterns_in_fns_without_body,95    private_in_public,96    unconditional_recursion,97    unused,98    unused_allocation,99    unused_comparisons,100    unused_parens,101    while_true102)]103#![cfg_attr(not(feature ="std"), no_std)]104#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))]105#[cfg(feature ="std-future")]106usepin_project::pin_project;107108pub(crate)modstdlib;109110#[cfg(feature ="std-future")]111usecrate::stdlib::{pin::Pin, task::Context};112113#[cfg(feature ="std")]114usetracing::{dispatcher, Dispatch};115116usetracing::Span;117118/// Implementations for `Instrument`ed future executors.119pub modexecutor;120121/// Extension trait allowing futures, streams, sinks, and executors to be122/// instrumented with a `tracing` [span].123///124/// [span]: https://docs.rs/tracing/latest/tracing/span/index.html125pub traitInstrument: Sized {126/// Instruments this type with the provided `Span`, returning an127    /// `Instrumented` wrapper.128    ///129    /// If the instrumented type is a future, stream, or sink, the attached `Span`130    /// will be [entered] every time it is polled. If the instrumented type131    /// is a future executor, every future spawned on that executor will be132    /// instrumented by the attached `Span`.133    ///134    /// # Examples135    ///136    /// Instrumenting a future:137    ///138// TODO: ignored until async-await is stable...139/// ```rust,ignore140    /// use tracing_futures::Instrument;141    ///142    /// # async fn doc() {143    /// let my_future = async {144    ///     // ...145    /// };146    ///147    /// my_future148    ///     .instrument(tracing::info_span!("my_future"))149    ///     .await150    /// # }151    /// ```152    ///153    /// [entered]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.enter154fninstrument(self, span: Span) -> Instrumented<Self> {155        Instrumented { inner:self, span }156    }157158/// Instruments this type with the [current] `Span`, returning an159    /// `Instrumented` wrapper.160    ///161    /// If the instrumented type is a future, stream, or sink, the attached `Span`162    /// will be [entered] every time it is polled. If the instrumented type163    /// is a future executor, every future spawned on that executor will be164    /// instrumented by the attached `Span`.165    ///166    /// This can be used to propagate the current span when spawning a new future.167    ///168    /// # Examples169    ///170// TODO: ignored until async-await is stable...171/// ```rust,ignore172    /// use tracing_futures::Instrument;173    ///174    /// # async fn doc() {175    /// let span = tracing::info_span!("my_span");176    /// let _enter = span.enter();177    ///178    /// // ...179    ///180    /// let future = async {181    ///     tracing::debug!("this event will occur inside `my_span`");182    ///     // ...183    /// };184    /// tokio::spawn(future.in_current_span());185    /// # }186    /// ```187    ///188    /// [current]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.current189    /// [entered]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html#method.enter190#[inline]191fnin_current_span(self) -> Instrumented<Self> {192self.instrument(Span::current())193    }194}195196/// Extension trait allowing futures, streams, and sinks to be instrumented with197/// a `tracing` [`Subscriber`].198///199/// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html200#[cfg(feature ="std")]201#[cfg_attr(docsrs, doc(cfg(feature ="std")))]202pub traitWithSubscriber: Sized {203/// Attaches the provided [`Subscriber`] to this type, returning a204    /// `WithDispatch` wrapper.205    ///206    /// When the wrapped type is a future, stream, or sink, the attached207    /// subscriber will be set as the [default] while it is being polled.208    /// When the wrapped type is an executor, the subscriber will be set as the209    /// default for any futures spawned on that executor.210    ///211    /// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html212    /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber213fnwith_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>214where215S: Into<Dispatch>,216    {217        WithDispatch {218            inner:self,219            dispatch: subscriber.into(),220        }221    }222223/// Attaches the current [default] [`Subscriber`] to this type, returning a224    /// `WithDispatch` wrapper.225    ///226    /// When the wrapped type is a future, stream, or sink, the attached227    /// subscriber will be set as the [default] while it is being polled.228    /// When the wrapped type is an executor, the subscriber will be set as the229    /// default for any futures spawned on that executor.230    ///231    /// This can be used to propagate the current dispatcher context when232    /// spawning a new future.233    ///234    /// [`Subscriber`]: https://docs.rs/tracing/latest/tracing/subscriber/trait.Subscriber.html235    /// [default]: https://docs.rs/tracing/latest/tracing/dispatcher/index.html#setting-the-default-subscriber236#[inline]237fnwith_current_subscriber(self) -> WithDispatch<Self> {238        WithDispatch {239            inner:self,240            dispatch: dispatcher::get_default(|default| default.clone()),241        }242    }243}244245/// A future, stream, sink, or executor that has been instrumented with a `tracing` span.246#[cfg_attr(feature ="std-future", pin_project)]247#[derive(Debug, Clone)]248pub structInstrumented<T> {249#[cfg(feature ="std-future")]250    #[pin]251inner: T,252#[cfg(not(feature ="std-future"))]253inner: T,254    span: Span,255}256257/// A future, stream, sink, or executor that has been instrumented with a258/// `tracing` subscriber.259#[cfg(feature ="std")]260#[cfg_attr(docsrs, doc(cfg(feature ="std")))]261#[cfg_attr(feature ="std-future", pin_project)]262#[derive(Clone, Debug)]263pub structWithDispatch<T> {264// cfg_attr doesn't work inside structs, apparently...265#[cfg(feature ="std-future")]266    #[pin]267inner: T,268#[cfg(not(feature ="std-future"))]269inner: T,270    dispatch: Dispatch,271}272273impl<T: Sized> InstrumentforT {}274275#[cfg(feature ="std-future")]276#[cfg_attr(docsrs, doc(cfg(feature ="std-future")))]277impl<T:crate::stdlib::future::Future>crate::stdlib::future::FutureforInstrumented<T> {278typeOutput = T::Output;279280fnpoll(self: Pin<&mutSelf>, cx:&mutContext<'_>) ->crate::stdlib::task::Poll<Self::Output> {281letthis =self.project();282let_enter = this.span.enter();283        this.inner.poll(cx)284    }285}286287#[cfg(feature ="futures-01")]288#[cfg_attr(docsrs, doc(cfg(feature ="futures-01")))]289impl<T: futures_01::Future> futures_01::FutureforInstrumented<T> {290typeItem = T::Item;291typeError = T::Error;292293fnpoll(&mutself) -> futures_01::Poll<Self::Item,Self::Error> {294let_enter =self.span.enter();295self.inner.poll()296    }297}298299#[cfg(feature ="futures-01")]300#[cfg_attr(docsrs, doc(cfg(feature ="futures-01")))]301impl<T: futures_01::Stream> futures_01::StreamforInstrumented<T> {302typeItem = T::Item;303typeError = T::Error;304305fnpoll(&mutself) -> futures_01::Poll<Option<Self::Item>,Self::Error> {306let_enter =self.span.enter();307self.inner.poll()308    }309}310311#[cfg(feature ="futures-01")]312#[cfg_attr(docsrs, doc(cfg(feature ="futures-01")))]313impl<T: futures_01::Sink> futures_01::SinkforInstrumented<T> {314typeSinkItem = T::SinkItem;315typeSinkError = T::SinkError;316317fnstart_send(318&mutself,319        item:Self::SinkItem,320    ) -> futures_01::StartSend<Self::SinkItem,Self::SinkError> {321let_enter =self.span.enter();322self.inner.start_send(item)323    }324325fnpoll_complete(&mutself) -> futures_01::Poll<(),Self::SinkError> {326let_enter =self.span.enter();327self.inner.poll_complete()328    }329}330331#[cfg(all(feature ="futures-03", feature ="std-future"))]332#[cfg_attr(docsrs, doc(cfg(all(feature ="futures-03", feature ="std-future"))))]333impl<T: futures::Stream> futures::StreamforInstrumented<T> {334typeItem = T::Item;335336fnpoll_next(337self: Pin<&mutSelf>,338        cx:&mutContext<'_>,339    ) -> futures::task::Poll<Option<Self::Item>> {340letthis =self.project();341let_enter = this.span.enter();342        T::poll_next(this.inner, cx)343    }344}345346#[cfg(all(feature ="futures-03", feature ="std-future"))]347#[cfg_attr(docsrs, doc(cfg(all(feature ="futures-03", feature ="std-future"))))]348impl<I, T: futures::Sink<I>> futures::Sink<I>forInstrumented<T>349where350T: futures::Sink<I>,351{352typeError = T::Error;353354fnpoll_ready(355self: Pin<&mutSelf>,356        cx:&mutContext<'_>,357    ) -> futures::task::Poll<Result<(),Self::Error>> {358letthis =self.project();359let_enter = this.span.enter();360        T::poll_ready(this.inner, cx)361    }362363fnstart_send(self: Pin<&mutSelf>, item: I) ->Result<(),Self::Error> {364letthis =self.project();365let_enter = this.span.enter();366        T::start_send(this.inner, item)367    }368369fnpoll_flush(370self: Pin<&mutSelf>,371        cx:&mutContext<'_>,372    ) -> futures::task::Poll<Result<(),Self::Error>> {373letthis =self.project();374let_enter = this.span.enter();375        T::poll_flush(this.inner, cx)376    }377378fnpoll_close(379self: Pin<&mutSelf>,380        cx:&mutContext<'_>,381    ) -> futures::task::Poll<Result<(),Self::Error>> {382letthis =self.project();383let_enter = this.span.enter();384        T::poll_close(this.inner, cx)385    }386}387388impl<T> Instrumented<T> {389/// Borrows the `Span` that this type is instrumented by.390pub fnspan(&self) ->&Span {391&self.span392    }393394/// Mutably borrows the `Span` that this type is instrumented by.395pub fnspan_mut(&mutself) ->&mutSpan {396&mutself.span397    }398399/// Borrows the wrapped type.400pub fninner(&self) ->&T {401&self.inner402    }403404/// Mutably borrows the wrapped type.405pub fninner_mut(&mutself) ->&mutT {406&mutself.inner407    }408409/// Get a pinned reference to the wrapped type.410#[cfg(feature ="std-future")]411    #[cfg_attr(docsrs, doc(cfg(feature ="std-future")))]412pub fninner_pin_ref(self: Pin<&Self>) -> Pin<&T> {413self.project_ref().inner414    }415416/// Get a pinned mutable reference to the wrapped type.417#[cfg(feature ="std-future")]418    #[cfg_attr(docsrs, doc(cfg(feature ="std-future")))]419pub fninner_pin_mut(self: Pin<&mutSelf>) -> Pin<&mutT> {420self.project().inner421    }422423/// Consumes the `Instrumented`, returning the wrapped type.424    ///425    /// Note that this drops the span.426pub fninto_inner(self) -> T {427self.inner428    }429}430431#[cfg(feature ="std")]432impl<T: Sized> WithSubscriberforT {}433434#[cfg(all(feature ="futures-01", feature ="std"))]435#[cfg_attr(docsrs, doc(cfg(all(feature ="futures-01", feature ="std"))))]436impl<T: futures_01::Future> futures_01::FutureforWithDispatch<T> {437typeItem = T::Item;438typeError = T::Error;439440fnpoll(&mutself) -> futures_01::Poll<Self::Item,Self::Error> {441letinner =&mutself.inner;442        dispatcher::with_default(&self.dispatch, || inner.poll())443    }444}445446#[cfg(all(feature ="std-future", feature ="std"))]447#[cfg_attr(docsrs, doc(cfg(all(feature ="std-future", feature ="std"))))]448impl<T:crate::stdlib::future::Future>crate::stdlib::future::FutureforWithDispatch<T> {449typeOutput = T::Output;450451fnpoll(self: Pin<&mutSelf>, cx:&mutContext<'_>) ->crate::stdlib::task::Poll<Self::Output> {452letthis =self.project();453letdispatch = this.dispatch;454letfuture = this.inner;455        dispatcher::with_default(dispatch, || future.poll(cx))456    }457}458459#[cfg(feature ="std")]460impl<T> WithDispatch<T> {461/// Wrap a future, stream, sink or executor with the same subscriber as this WithDispatch.462pub fnwith_dispatch<U>(&self, inner: U) -> WithDispatch<U> {463        WithDispatch {464            dispatch:self.dispatch.clone(),465            inner,466        }467    }468469/// Borrows the `Dispatch` that this type is instrumented by.470pub fndispatch(&self) ->&Dispatch {471&self.dispatch472    }473474/// Get a pinned reference to the wrapped type.475#[cfg(feature ="std-future")]476    #[cfg_attr(docsrs, doc(cfg(feature ="std-future")))]477pub fninner_pin_ref(self: Pin<&Self>) -> Pin<&T> {478self.project_ref().inner479    }480481/// Get a pinned mutable reference to the wrapped type.482#[cfg(feature ="std-future")]483    #[cfg_attr(docsrs, doc(cfg(feature ="std-future")))]484pub fninner_pin_mut(self: Pin<&mutSelf>) -> Pin<&mutT> {485self.project().inner486    }487488/// Borrows the wrapped type.489pub fninner(&self) ->&T {490&self.inner491    }492493/// Mutably borrows the wrapped type.494pub fninner_mut(&mutself) ->&mutT {495&mutself.inner496    }497498/// Consumes the `WithDispatch`, returning the wrapped type.499pub fninto_inner(self) -> T {500self.inner501    }502}503504#[cfg(test)]505pub(crate)useself::supportastest_support;506// This has to have the same name as the module in `tracing`.507#[path ="../../tracing/tests/support/mod.rs"]508#[cfg(test)]509#[allow(unreachable_pub)]510pub(crate)modsupport;511512#[cfg(test)]513modtests {514use super::{test_support::*,*};515516#[cfg(feature ="futures-01")]517modfutures_01_tests {518usefutures_01::{future, stream, task, Async, Future, Stream};519usetracing::subscriber::with_default;520521use super::*;522523structPollN<T, E> {524            and_return:Option<Result<T, E>>,525            finish_at: usize,526            polls: usize,527        }528529implPollN<(), ()> {530fnnew_ok(finish_at: usize) ->Self{531Self{532                    and_return:Some(Ok(())),533                    finish_at,534                    polls:0,535                }536            }537538fnnew_err(finish_at: usize) ->Self{539Self{540                    and_return:Some(Err(())),541                    finish_at,542                    polls:0,543                }544            }545        }546547impl<T, E> futures_01::FutureforPollN<T, E> {548typeItem = T;549typeError = E;550fnpoll(&mutself) -> futures_01::Poll<Self::Item,Self::Error> {551self.polls +=1;552ifself.polls ==self.finish_at {553self.and_return554                        .take()555                        .expect("polled after ready")556                        .map(Async::Ready)557                }else{558                    task::current().notify();559Ok(Async::NotReady)560                }561            }562        }563564#[test]565fnfuture_enter_exit_is_reasonable() {566let(subscriber, handle) = subscriber::mock()567                .enter(span::mock().named("foo"))568                .exit(span::mock().named("foo"))569                .enter(span::mock().named("foo"))570                .exit(span::mock().named("foo"))571                .drop_span(span::mock().named("foo"))572                .done()573                .run_with_handle();574            with_default(subscriber, || {575                PollN::new_ok(2)576                    .instrument(tracing::trace_span!("foo"))577                    .wait()578                    .unwrap();579            });580            handle.assert_finished();581        }582583#[test]584fnfuture_error_ends_span() {585let(subscriber, handle) = subscriber::mock()586                .enter(span::mock().named("foo"))587                .exit(span::mock().named("foo"))588                .enter(span::mock().named("foo"))589                .exit(span::mock().named("foo"))590                .drop_span(span::mock().named("foo"))591                .done()592                .run_with_handle();593            with_default(subscriber, || {594                PollN::new_err(2)595                    .instrument(tracing::trace_span!("foo"))596                    .wait()597                    .unwrap_err();598            });599600            handle.assert_finished();601        }602603#[test]604fnstream_enter_exit_is_reasonable() {605let(subscriber, handle) = subscriber::mock()606                .enter(span::mock().named("foo"))607                .exit(span::mock().named("foo"))608                .enter(span::mock().named("foo"))609                .exit(span::mock().named("foo"))610                .enter(span::mock().named("foo"))611                .exit(span::mock().named("foo"))612                .enter(span::mock().named("foo"))613                .exit(span::mock().named("foo"))614                .drop_span(span::mock().named("foo"))615                .run_with_handle();616            with_default(subscriber, || {617                stream::iter_ok::<_, ()>(&[1,2,3])618                    .instrument(tracing::trace_span!("foo"))619                    .for_each(|_| future::ok(()))620                    .wait()621                    .unwrap();622            });623            handle.assert_finished();624        }625626#[test]627fnspan_follows_future_onto_threadpool() {628let(subscriber, handle) = subscriber::mock()629                .enter(span::mock().named("a"))630                .enter(span::mock().named("b"))631                .exit(span::mock().named("b"))632                .enter(span::mock().named("b"))633                .exit(span::mock().named("b"))634                .drop_span(span::mock().named("b"))635                .exit(span::mock().named("a"))636                .drop_span(span::mock().named("a"))637                .done()638                .run_with_handle();639letmutruntime = tokio::runtime::Runtime::new().unwrap();640            with_default(subscriber, || {641tracing::trace_span!("a").in_scope(|| {642letfuture = PollN::new_ok(2)643                        .instrument(tracing::trace_span!("b"))644                        .map(|_| {645tracing::trace_span!("c").in_scope(|| {646// "c" happens _outside_ of the instrumented future's647                                // span, so we don't expect it.648})649                        });650                    runtime.block_on(Box::new(future)).unwrap();651                })652            });653            handle.assert_finished();654        }655    }656657#[cfg(all(feature ="futures-03", feature ="std-future"))]658modfutures_03_tests {659usefutures::{future, sink, stream, FutureExt, SinkExt, StreamExt};660usetracing::subscriber::with_default;661662use super::*;663664#[test]665fnstream_enter_exit_is_reasonable() {666let(subscriber, handle) = subscriber::mock()667                .enter(span::mock().named("foo"))668                .exit(span::mock().named("foo"))669                .enter(span::mock().named("foo"))670                .exit(span::mock().named("foo"))671                .enter(span::mock().named("foo"))672                .exit(span::mock().named("foo"))673                .enter(span::mock().named("foo"))674                .exit(span::mock().named("foo"))675                .drop_span(span::mock().named("foo"))676                .run_with_handle();677            with_default(subscriber, || {678                Instrument::instrument(stream::iter(&[1,2,3]),tracing::trace_span!("foo"))679                    .for_each(|_| future::ready(()))680                    .now_or_never()681                    .unwrap();682            });683            handle.assert_finished();684        }685686#[test]687fnsink_enter_exit_is_reasonable() {688let(subscriber, handle) = subscriber::mock()689                .enter(span::mock().named("foo"))690                .exit(span::mock().named("foo"))691                .enter(span::mock().named("foo"))692                .exit(span::mock().named("foo"))693                .enter(span::mock().named("foo"))694                .exit(span::mock().named("foo"))695                .drop_span(span::mock().named("foo"))696                .run_with_handle();697            with_default(subscriber, || {698                Instrument::instrument(sink::drain(),tracing::trace_span!("foo"))699                    .send(1u8)700                    .now_or_never()701                    .unwrap()702                    .unwrap()703            });704            handle.assert_finished();705        }706    }707}

[8]ページ先頭

©2009-2025 Movatter.jp