Skip to content

Feature (sync): #[trace(recurse=all)] #134

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

Closed
taqtiqa-mark opened this issue Mar 30, 2022 · 7 comments
Closed

Feature (sync): #[trace(recurse=all)] #134

taqtiqa-mark opened this issue Mar 30, 2022 · 7 comments

Comments

@taqtiqa-mark
Copy link
Contributor

taqtiqa-mark commented Mar 30, 2022

Need to evaluate the defaults in #133 in light of the following behavior - are those defaults the least restrictive? Here we'll need to have the test suite be more comprehensive.

The model phase of #113 is taking shape.

The following two cases should be possible (initially sync only):

Tracing inner functions

#[trace(recurse=all)]
pub fn outer() {
    defined_later();

    fn defined_later() {
        println!("I'm traced too"):
    }
}

Where all setting from the outer trace percolate down. It is the users responsibility to ensure the settings are appropriate for the child functions.

Tracing a module

More tricky, but likely possible, and empowering for novice-users when debugging:

#[trace(recurse=all)]
mod traced {
    fn outer() {
       println!("Look Dad, I'm traced!");
        defined_later();

        pub fn defined_later() {
            println!("I'm traced too");
        }
    }
}

async and entry on poll traces should also be possible, but can be second phase.

A natural extension is to have option settings:

#[trace(recurse=all)]
#[trace(recurse=public)]
#[trace(recurse=private)]

Thoughts?

@taqtiqa-mark taqtiqa-mark changed the title Feature (sync): #[trace(recurse=true)] Feature (sync): #[trace(recurse=all)] Mar 30, 2022
@taqtiqa-mark
Copy link
Contributor Author

taqtiqa-mark commented Mar 31, 2022

Just recording reasoning around hierarchy/precedence, more likely to arise when tracing a mod:

#[trace("a", recurse=all)]
pub fn outer() {
    defined_later();
    defined_later_too();

    #trace["b", recurse=false]
    fn defined_later_too() {
        println!("I'm traced with 'b' options/settings"):
        fn defined_lastish(){
            println!("I'm traced with 'a'  options/settings"):
        }
    }

    fn defined_later() {
        println!("I'm traced with 'a'  options/settings too"):
    }
}

@taqtiqa-mark
Copy link
Contributor Author

taqtiqa-mark commented Mar 31, 2022

Also, with #[trace("a", recurse=all)] the "a" becomes a prefix added to child trace names, which default to the function name, so names in the above are:

  • a_outer
  • b_defined_later_too
  • a_defined_last
  • a_defined_later

When using #[trace(recurse=all|private|public)], names would be:

  • outer
  • defined_later_too
  • outer_defined_lastish
  • outer_defined_later

@taqtiqa-mark
Copy link
Contributor Author

taqtiqa-mark commented Apr 11, 2022

Whenever this is implemented... we will need to explicitly document that when recurse=all|private|public then nested #[trace(...)] settings are not cumulative.

Specifically, for example:

#[trace(recurse=all, option_a="some")]
fn f() {
    #[trace(option_b="thing")]
    fn g(){
        fn x() {
            // not traced
        }
    }
    fn h(){
        fn y(){
            // is traced
        }
    }
}

is not equivalent to the second macro being#[trace(option_a="some", option_b="thing")].
In this case:

  • h and y would be traced with settings #[trace(recurse=all, option_a="some")]
  • g is traced with settings #[trace(option_b="thing")]
  • x is not traced.

@andylokandy
Copy link
Collaborator

I feel uncomfortable adding implicit tracing because:

  1. tracing has significant overhead, even though minitrace has minimized it as much as possible.
  2. most functions have no value to be traced

What's the scenario is recurse for?

@taqtiqa-mark
Copy link
Contributor Author

taqtiqa-mark commented Apr 13, 2022

What's the scenario is recurse for?

Pure convenience when debugging the scenario is you have a bug of unknown provenance in a non-trivial async context. Without such a switch to 'inject' tracing in chunks (per module) or globally, the only alternative is the time consuming and painful process of manually adding them until you discover the root cause.

Not for prod or even dev - unless of course you're disciplined and place all you traceable functions in a single module.

Ack the costs of tracing. As always - Caveat emptor.

taqtiqa-mark added a commit to taqtiqa-mark/utrace-rust that referenced this issue Apr 27, 2022
@andylokandy
Copy link
Collaborator

I believe incorporating this feature could be beneficial for debugging and should integrate well with minitrace. However, a question arises: isn't this feature sufficiently general to warrant its own crate? For instance, we can recursively annotate an entire module using log_derive, can't we? Consequently, minitrace could potentially leverage this capability at no additional effort!

@andylokandy
Copy link
Collaborator

Closing it for now since it's not entirely related to minitrace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants