-
-
Notifications
You must be signed in to change notification settings - Fork 85
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
cross-project bug: async_trait and tracing::instrument are incompatible #45
Comments
@dtolnay I wanted to check: how would you suggest resolving this? Since the |
I think this would be the most reliable pattern to identify: https://github.com/dtolnay/async-trait/blob/1.0.15/src/expand.rs#L402-L403 So if you find a function whose body consists of: async fn f<...>(...) {...}
Box::pin(f::<...>(...)) then treat the instrument macro as if it had been applied to the inner function not the outer one. |
I'll probably start with that. I wonder if this can/should be generalized. For instance, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
## Motivation As outlined in #399, right now `tracing-futures` (or more precisely, the code generated by `#[instrument]`) is not working well with async-trait. What happens is that async-trait rewrites the trait method as a non-async function, insides of which it pins the async method we want to instrument, and we end up instrumenting the wrapper instead of the async fn. This will allow people to use traits with (seemingly) async functions along with `#[instrument]`. ## Solution I decided to follow the discussion at dtolnay/async-trait#45 and see if I could make it working. Right now I would describe its state as "works for me, and *should* work for everyone". The `instrument` macro will now: * Rewrite the block when it looks like there is async_trait involved to wrap the internal async function instead of the wrapper generated by `async-trait` * Rewrite '_self' as 'self' when using #[instrument] jointly with `async-trait` Fixes #399
This should be fixed now by the merge request above. Thanks @dtolnay for outlining the pattern to look for to identify async_trait, I followed your suggestion and it works great ! |
Wow, thanks @nightmared. Would you be able to follow up with a PR in async-trait to add a test with #[instrument] so that we avoid inadvertently breaking it? |
You want to add a reverse test ? I'm not sure we can use the mock tests inside tracing outside of the crate. Otherwise we could do something like https://github.com/tokio-rs/tracing/blob/369b0c5e1d770f26c5e98a3e9f8fd9d4c6dfde8c/tracing-attributes/tests/async_fn.rs#L69-L152. I will think about it in upcoming days -- |
There has been some discussion about publishing the test-support code as its own crate (see tokio-rs/tracing#539). If we were to do that, it could be pretty easy for |
But is there no way to test this in a setup that is representative of how downstream crates use async_trait + tracing? I don't know anything about tracing but I feel like we shouldn't need to depend on internal test-support code for this. |
@dtolnay The best way to test that everything works correctly is to write an implementation of the It would also be possible to test this using a |
Thanks for the explanation and links! I'd be fine having a small tracing::Subscriber impl dedicated to this one test. For an async trait method containing one event, all we care about in this crate is that the event happens before the exit (as opposed to before @nightmared's fix, where the exit would happen as soon as the BoxFuture was created). A struct with a Cell<bool>, or even a static with an AtomicBool, would be enough for our purposes. |
Yup, I think that's probably fine. We might also want to assert that if the future is polled, the span is re-entered as expected, and exited when the poll returns. This could definitely be done with a handwritten test subscriber — the test support code is mostly useful in the context of |
I hacked together a prototype at nightmared@b544a1b. Would something similar be okay ? |
Something like that looks reasonable to me. |
The combination of macros results in the
instrument
macro thinking the instrumented function is not in fact async and generating the wrong code.see full writeup here, cross-posting b/c someone on the tonic/tracing/etc discord suggested it. Thanks for providing this crate!
The text was updated successfully, but these errors were encountered: