Giter VIP home page Giter VIP logo

Comments (11)

davidbarsky avatar davidbarsky commented on July 17, 2024 2

@hawkw and I chatted about instrumenting async functions. Below is a brief summary.

An async function like the one below...

async fn call(req: Request<Body>) -> Result<Response<Body>, Error>> {
   // function body
} 

...desugars to something like:

fn call(req: Request<Body>) -> impl Future<Output=Result<Response<Body>, Error>>> {
   async move {
         // function body
   }
} 

We can use this knowledge and a sprinkling of syn-mid to instrument an async function's future. syn-mid exposes two structs: ItemFn and Block. The latter is a block whose body is not parsed. We can use this to instrument futures emitted by an async fn by writing something similar to:

use syn_mid::{Block, ItemFn};
use quote::quote;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn instrument(args: TokenStream, function: TokenStream) -> TokenStream {
    let mut function: ItemFn = parse_macro_input!(body);
    let body = function.body;
    *function.body = quote! {
        async move {
           #body
       }.instrument!(span)
    };
    function.into()
}

(cc: @yaahallo, this might be of interest to you given your interest in #15)

from tracing.

yaahc avatar yaahc commented on July 17, 2024 1

@davidbarsky yea I'm interested, I'll look into this more in depth tonight :)

from tracing.

mbilker avatar mbilker commented on July 17, 2024

I don't know how related this is but it does deal with the std::future::GenFuture returned from async functions.

I tried to write an Instrumented implementation for std::future::Future, but ran into issues because GenFuture implements !Unpin so you can't do Pin::new(inner) if you go by the futures::Future implementation.

I got around this by adding a boxed_instrument method which does Box::pin(self) and then I have an Instrumented<Pin<Box<T>>> to handle the actual polling of that.

from tracing.

hawkw avatar hawkw commented on July 17, 2024

@mbilker this is definitely relevant, thanks! I think having tokio-trace-futures support futures 0.3 is definitely a prerequisite for supporting async-await in the proc macros, thanks for looking into it. I'd love to see a branch with your solution!

from tracing.

mbilker avatar mbilker commented on July 17, 2024

Since I only have experience with futures 0.1, I took a look at futures 0.3 and futures::future::Future appears to be a re-export of std::future::Future, which means the code I have should work for futures 0.3.

from tracing.

mbilker avatar mbilker commented on July 17, 2024

I put up my changes at https://github.com/mbilker/tokio-trace-nursery/tree/std-future

from tracing.

mbilker avatar mbilker commented on July 17, 2024

If tokio-trace-futures is targeting versions before 1.33.0, then boxed_instrument needs to have an alternate implementation to use Box::new instead Box::pin as Box::pin was stabilized in 1.33.0.

from tracing.

yaahc avatar yaahc commented on July 17, 2024
        async move {
           #body
       }.instrument!(span)

This isn't a thing right? As in quote! doesn't do magic to allow postfix macros?

For context, my interest in proc-macros is based on a desire to learn them, not previous experience.

from tracing.

davidbarsky avatar davidbarsky commented on July 17, 2024

@yaahallo sorry, I didn't mean to do make .instrument!() a macro! I mean to use point at something like this: https://github.com/tokio-rs/tokio-trace-nursery/blob/08db36d475c4af28821434f60d4f4ed9748452ee/tokio-trace-futures/examples/proxy_server.rs#L76

from tracing.

davidbarsky avatar davidbarsky commented on July 17, 2024

Erm, the entire block, which looks is:

let client_to_server = copy(client_reader, server_writer)
    .and_then(|(n, _, server_writer)| {
        info!(size = n);
        shutdown(server_writer).map(move |_| n)
}).instrument(span!(Level::TRACE, "client_to_server"));

from tracing.

hawkw avatar hawkw commented on July 17, 2024
        async move {
           #body
       }.instrument!(span)

This isn't a thing right? As in quote! doesn't do magic to allow postfix macros?

Pretty sure that's a typo...

Edit: oh lol david beat me to it

from tracing.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.