-
Notifications
You must be signed in to change notification settings - Fork 750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
futures: add support for std::futures::Future #40
Conversation
ac50c45
to
c51bfd9
Compare
d06efbc
to
2d09719
Compare
55bc69f
to
3aaf140
Compare
@mbilker I took a look at this, and I found a potential solution for supporting Here's the diff for my solution.diff --git a/tracing-futures/Cargo.toml b/tracing-futures/Cargo.toml
index 791e3a49..09fbf75b 100644
--- a/tracing-futures/Cargo.toml
+++ b/tracing-futures/Cargo.toml
@@ -12,6 +12,7 @@ futures = "0.1"
tracing = "0.1"
tokio = { version = "0.1", optional = true }
tokio-executor = { version = "0.1", optional = true }
+pin-utils = "0.1.0-alpha.4"
[dev-dependencies]
tokio = "0.1.22"
diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs
index 55d63746..a4531493 100644
--- a/tracing-futures/src/lib.rs
+++ b/tracing-futures/src/lib.rs
@@ -37,10 +37,6 @@ pub trait Instrument: Sized {
fn instrument(self, span: Span) -> Instrumented<Self> {
Instrumented { inner: self, span }
}
-
- fn boxed_instrument(self, span: Span) -> Instrumented<Pin<Box<Self>>> {
- Instrumented { inner: Box::pin(self), span }
- }
}
pub trait WithSubscriber: Sized {
@@ -69,16 +65,23 @@ pub struct WithDispatch<T> {
impl<T: Sized> Instrument for T {}
-impl<P: std::future::Future + Unpin> std::future::Future for Instrumented<P> {
- type Output = P::Output;
- fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> {
- let this = self.get_mut();
- let _enter = this.span.enter();
- Pin::new(&mut this.inner).poll(lw)
+impl<F: std::future::Future> Instrumented<F> {
+ pin_utils::unsafe_pinned!(inner: F);
+}
+
+impl<F: std::future::Future> std::future::Future for Instrumented<F> {
+ type Output = F::Output;
+
+ fn poll(mut self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> {
+ let span = self.as_ref().span.clone();
+ let _enter = span.enter();
+ self.as_mut().inner().poll(lw)
}
}
+impl<F: std::future::Future + Unpin> Unpin for Instrumented<F> {}
+
impl<T: futures::Future> futures::Future for Instrumented<T> {
type Item = T::Item;
type Error = T::Error;
@@ -115,16 +118,6 @@ impl<T: Sink> Sink for Instrumented<T> {
}
impl<T> Instrumented<T> {
- /// 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
- }
-
/// Consumes the `Instrumented`, returning the wrapped type.
///
/// Note that this drops the span. As an aside, it looks like your CI build is currently failing on the stable and Rust 1.34 builds. I think we should feature-flag We should also update the CI configuration so that the beta and nightly builds enable the Once we make those changes, I'd be happy to merge this! Thanks for working on it! |
@hawkw Thanks for looking into this! I actually had this feature flagged before with the name I originally removed the feature flag since |
I'd probably call the feature flags |
I like those too. Would [features]
"futures-0.1" = ["futures"] |
Hmm, I suppose to avoid quoting, we ought to go with |
If I make tracing/tracing-futures/src/executor.rs Lines 2 to 5 in f4752ff
|
Probably, when the tokio feature is enabled. I think we may just want to use fully qualified imports for everything now (rather than conditionally importing |
Alright, I rebased this on the current master branch and pushed a new commit with your suggestions and |
I will mark this PR as ready to review when I write some tests or rework the futures 0.1 tests into ones for |
It's actually pretty difficult to use In a project where I am using hyper, tokio, and |
I'm not sure if we'll need tokio to implement most of the fairly simple tests in |
Hi @mbilker, what's the current status of this? It would be great to merge this soon! |
I have tested it with a project of mine that is using async functions and the await features enabled and it’s working there. I am still trying to get tokio-test up and running in the test suite. |
I do still need to test variations of this pattern as there was a case a few weeks back where if I didn’t do an instrument on a future and awaited that future, then the future wouldn’t follow the current span. |
Okay, if there anything I can do to help out, please let me know! |
I went ahead and used The tests run successfully on my machine with Here is where I'll ask for your help, is there a way to only conditionally include |
I can do that |
- To support async functions, the inner future must be boxed. - If someone can figure out how to support !Unpin futures, please do so.
- Thank you Eliza Weisman (hawkw) for the solution using the pin-utils crate - Added feature gates for the futures 0.1, tokio, and std::future implementations
Actually, since the |
I put up the tests over at https://github.com/mbilker/tracing/tree/std-future-test |
Since I did a push (and rebase) with and added Travis section to test all features from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM and I'm happy to merge it as-is.
From a code organisation perspective, I'm wondering if it might be nicer to put the feature-flagged code for futures-01
and std-future
in separate modules, with the cfg
attributes on the modules, and then re-export the contents of those modules? It would mean we wouldn't have to feature-flag as many individual items. However, this isn't a blocker and we can always re-organise the code later.
tracing-futures/src/lib.rs
Outdated
@@ -157,7 +191,9 @@ mod tests { | |||
extern crate tokio; | |||
|
|||
use super::{test_support::*, *}; | |||
use futures::{future, stream, task, Async}; | |||
|
|||
#[cfg(feature = "futures-01")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of putting cfg
attributes on each individual import and test in this module, what do you think of having separate test modules for futures-01
and std-future
? Then we can just feature-flag the entire module, and not have to worry about individual items within that module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works for me. Both test modules would use the same base PollN
so there will also need to be a third module that is used by both testing modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The feature-flagged modules could be submodules of the main test module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It definitely works like that. I can make it a separate top-level module, but then I have to mark PollN
as pub(crate)
and it's two constructors as pub(crate)
.
Also, how would you feel about just merging the tests added in https://github.com/mbilker/tracing/tree/std-future-test into this branch, and merging the whole thing in one commit? I'd prefer to add tests and new code together when practical. |
That works for me, but do note the addition of |
But! I wonder if moving those tests to a separate subcrate, like the tracing tests with the |
Ah, right, I had forgotten about that. Let's merge this PR now, and merge the tests later. My bad.
Yeah, if it's not in the workspace, we can run those tests only on nightly builds. Sounds good to me. |
That should be everything. Please take a look and leave comments on what I should clarify. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Thanks for the contribution.
- test_std_future is part of the namespace so having std_future as part of the test function name is not needed
This looks great, thanks for fixing the last nit around test names (which was entirely optional). I'm going to merge this now. Thanks again for all the work that went into this change, @mbilker! I know it took a while to get through, and all your time is really appreciated. |
This PR adds a
std::future::Future
implementation toInstrumented<T>
, but with some caveats:- To supportasync
functions, the inner future must be boxed.- If someone can figure out how to supportThanks hawkw!!Unpin
futures without boxing, please do so.