-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Use tracing
spans to trace the entire MIR interp stack
#75143
Conversation
I think I can get I also think it should be possible to get something that can be dynamically switched between |
Oh interesting! So we could turn on
Uh, so... logs would not show until a thread is done with a span? So the entire span content would be buffered? That seems ok to me in most cases. We just need to turn all that off when debugging threading issues. |
I think I would personally prefer that we not try to introduce locks or anything into rustc itself but rather have a separate tool that parses and re-shuffles logger output -- is that feasible? Too hard? |
You should be able to use a filter like |
I was considering that, too. Shouldn't be too hard to just prepend all log messages with a thread index (only if rustc is configured to use threads), then you can easily filter with just ripgrep. |
I tried |
rustc always uses threads for LLVM, at least, so it probably makes sense to just always include a thread ID. |
Ugh, that's a bummer...I guess the "static" (target-based) filter takes priority. As I mentioned, the filtering code is pretty hairy...we need to make some changes so it behaves more reasonably with complex filters.
|
Maybe?
I think so!
Fair enough, that's a good point!
In either case, I'll hold off on any changes. Do you mind commenting on tokio-rs/tracing#884 with your needs and requirements? |
So regarding this concrete PR, that's very interesting! But I feel like having the entire stacktrace on every line is way too verbose. Consider what this will look like in Miri where stacks are at least 10 frames high from the libstd But I agree that our traces could be made easier to read. Some random ideas:
|
// we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we | ||
// can't protect the tracing stack, but that'll just lead to weird logging, no actual | ||
// problems. | ||
*self = Self(span); |
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.
Wow this is super confusing and IMO needs more comments.^^
So the thing we do here is that SpanGuard
calls "enter" on something in log::dispacher
inside SpanGuard::enter
, and it calls exit
on drop. But we call the exit after the enter, and somehow it still works? And what if we create a SpanGaurd
and never enter
it, then we exit
something that was never entered?
It doesn't help that Span
is already something very different in rustc so my brain just makes all the wrong connections all the time.^^
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.
Yea, the ordering wasn't ideal (I changed it), but also technically irrelevant as enter
never gets called twice, but if it were, this would be sane.
I documented all this on the new´ and
enter` methods
Hm... that looks promising yes. Is there some way to cap this so that when we have 70 nested frames we don't have a terminal full of vertical bars? Maybe after depth 50, reset to 0 and start over with the nesting or so? |
I'll have a look, that should be doable |
Note that with the appropriate filters we can hide arbitrary levels. So we could set it up that the logs only start after a specific frame has been pushed and stop after that frame is popped. We'd could build a list of useful filters for ppl to pass to |
All the features discussed in this PR have been merged into In textual form:
|
I like that rendering, except for this part
Is there any way to make the function name more prominent here? I feel it drowns a bit in the noise, with the Also the |
Also PAUSING doesnt have the function name any more (not sure why) and looks very different than the other messages? It has no timing and the "INFO" is before the module instzad of after. And what about |
Also my question is still open of how this looks like in Miri, when there are also Miri log messages between the core engine log messages. |
oops, I didn't notice that. I'm gonna remove all that. This wrapping isn't necessary for hierarchical printing |
The extra marker is If you come up with better symbols, I'm very open to other things, but I'd rather get something merged and bikeshed symbols in the tracing-tree bugtracker |
Sure. |
Sorry about that! Totally slipped my mind—I read the notification on GitHub and left it in my tabs. Taking care of that now; I'll update y'all when I publish a new version in about 30 minutes. |
No worries! Thanks for taking care of it now. |
Yes that rendering looks great. :) |
self.frame().instance, | ||
unwinding | ||
); | ||
info!(unwinding); |
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.
Why is info!(unwinding)
run twice? Also just having unwinding=true/false
in the log without much context is not very clear...
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 duplication is gone, and we now inform about the stack popping again
Ooh, maybe we should try out #[instrument]
next 😆
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.
Ooh, maybe we should try out #[instrument] next laughing
No idea what that means.^^
@bors r+ |
📌 Commit 8f9472c has been approved by |
Use `tracing` spans to trace the entire MIR interp stack r? @RalfJung While being very verbose, this allows really good tracking of what's going on. While I considered schemes like the previous indenter that we had (which we could get by using the `tracing-tree` crate), this will break down horribly with things like multithreaded rustc. Instead, we can now use `RUSTC_LOG` to restrict the things being traced. You could specify a filter in a way that only shows the logging of a specific frame. ![screenshot of command line output of the new formatting](https://user-images.githubusercontent.com/332036/89291343-aa40de00-d65a-11ea-9f6c-ea06c1806327.png) If we lower the span's level to `debug`, then in `info` level logging we'd not see the frames, but in `debug` level we would see them. The filtering rules in `tracing` are super powerful, but I'm not sure if we can specify a filter so we do see `debug` level events, but *not* the `frame` spans. The documentation at https://docs.rs/tracing-subscriber/0.2.10/tracing_subscriber/struct.EnvFilter.html makes me think that we can only turn on things, not turn off things at a more precise level. cc @hawkw
Rollup of 11 pull requests Successful merges: - rust-lang#75143 (Use `tracing` spans to trace the entire MIR interp stack) - rust-lang#75699 (Uplift drop-bounds lint from clippy) - rust-lang#76768 (Test and reject out-of-bounds shuffle vectors) - rust-lang#77190 (updated p! macro to accept literals) - rust-lang#77388 (Add some regression tests) - rust-lang#77419 (Create E0777 error code for invalid argument in derive) - rust-lang#77447 (BTreeMap: document DrainFilterInner better) - rust-lang#77468 (Fix test name) - rust-lang#77469 (Improve rustdoc error for failed intra-doc link resolution) - rust-lang#77473 (Make --all-targets in x.py check opt-in) - rust-lang#77508 (Fix capitalization in blog post name) Failed merges: r? `@ghost`
…-obk logging: add env var to control verbose scope entry/exit logging ~~This got removed in rust-lang#75143, and I find this makes long traces a lot harder to read, so I propose we add this back.~~ Example trace: ``` │ │ ├─0ms INFO rustc_const_eval::interpret::step return │ │ ├─0ms INFO rustc_const_eval::interpret::eval_context popping stack frame (returning from function) │ │┌┘rustc_const_eval::interpret::eval_context::frame std::ptr::mut_ptr::<impl *mut u8>::guaranteed_eq │ ├┘rustc_const_eval::interpret::eval_context::frame std::ptr::mut_ptr::<impl *mut u8>::is_null │ ├─1ms INFO rustc_const_eval::interpret::step // executing bb2 │ ├─1ms INFO rustc_const_eval::interpret::step StorageDead(_4) │ ├─1ms INFO rustc_const_eval::interpret::step StorageDead(_2) │ ├─1ms INFO rustc_const_eval::interpret::step return │ ├─1ms INFO rustc_const_eval::interpret::eval_context popping stack frame (returning from function) │┌┘rustc_const_eval::interpret::eval_context::frame std::ptr::mut_ptr::<impl *mut u8>::is_null ├┘rustc_const_eval::interpret::eval_context::frame std::sys_common::thread_local_dtor::register_dtor_fallback::run_dtors ├─178ms INFO rustc_const_eval::interpret::step // executing bb2 ├─178ms INFO rustc_const_eval::interpret::step StorageDead(_5) ``` r? `@oli-obk`
r? @RalfJung
While being very verbose, this allows really good tracking of what's going on. While I considered schemes like the previous indenter that we had (which we could get by using the
tracing-tree
crate), this will break down horribly with things like multithreaded rustc. Instead, we can now useRUSTC_LOG
to restrict the things being traced. You could specify a filter in a way that only shows the logging of a specific frame.If we lower the span's level to
debug
, then ininfo
level logging we'd not see the frames, but indebug
level we would see them. The filtering rules intracing
are super powerful, but I'm not sure if we can specify a filter so we do seedebug
level events, but not theframe
spans. The documentation at https://docs.rs/tracing-subscriber/0.2.10/tracing_subscriber/struct.EnvFilter.html makes me think that we can only turn on things, not turn off things at a more precise level.cc @hawkw