-
Notifications
You must be signed in to change notification settings - Fork 31
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
Fix interleaved non-deferred spans #78
Conversation
@safinaskar, let me know if this fixes your issue 😊 |
110abed
to
09adf54
Compare
Would we consider making the retrace behavior default, as it does not change anything for non-concurrent code, but rather improves the concurrent aspect? The current default behavior makes the tree misleading as events seem to come from spans which they do not. |
Anyhow, this is now ready for review. @oli-obk, would you mind taking a look? |
Yes, my original issue is fixed in 09adf54 . Span events still don't have timestamps. I asked for this in #74 (comment) . (Of course, this is feature request, not a bug.)
This output suggests that a1 is child of t2, and a2 is child of t1, which is wrong. Also, I don't understand why |
Awesome. Could you enable For the "if I enable As for the timestamps, I think it would be beneficial to open another issue with the timestamp. Though I am not a maintainer of this crate, I think it would be beneficial for some kind of "Formatter" for span prefixes, which would also allow you to customize the current duration within a span, E.g; These features would be low maintenance since they do not interact with other functionality but rather just prints something before, in contrast to the span retracing which requires more testing due to its interaction and wider behavior change. I'll be happy to add both if the crate authors deem them useful. |
This is output of program from #74 (comment) with 09adf54 with
As you can see, the output is absolutely wrong |
Thank you. I've managed to look into this a little bit now, and the This does currently not play too well with multi-level retracing, so I'll fix that up. pre-open "open span b, parent of a": ├─ Event
├─ Event
├┐b (span b) // this one will look detached and disconned with the retrace line, and will not match the indent as a more than 1 level of spans may be printed depending on the previous span
└┐ a (new span a) |
e490512
to
aa43680
Compare
@safinaskar, I have now revised the logic for handling span pre-open logic. Let me if it fixes your issue |
aa43680
to
f861bac
Compare
@ten3roberts sorry for the delay in looking at this; reviewing now! |
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.
I think this looks good, thanks!
Thank you, glad to help |
It seems Safin is not coming back soon. Do you think we can merge this as is, as it is in a working state (or at least working much better than prior)? |
@ten3roberts I think so? I'm not sure if I fully understand the implications of this change, but I'll run it tomorrow and merge it then. |
Thanks. This PR contains two bugfixes. The first one is fixing an invalid assumption for non-deferred retraced spans. The retracing only happened for events, and not other span open events. This means that for The other bug that safin pointed out was in combining The previous behavior printed the new spans parent before the entire retraced chain. Consider the following example, where the current span before the event in
It worked when there was not mutliple levels that were printed at once (so that C and D line up), but didn't account for the less indented grandparent A. The fix is either
or 2 (parent of retrace root)
I orignally went with #1, but after considering a bit I think #2 looks better now (printing the parent of the root of the retraced chain, and not the parent of the new span. The parent of the new span will either be printed in the retrace chain, or be the parent of the retrace root for single chains. Let me know which method you prefer, and I'll be happy to change things around :) |
The previous behavior was to print the parent of the new span, leading to a parent being printed twice if the parent was also included in the retrace chain.
For a real example use tracing::Instrument;
#[tracing::instrument]
async fn b1() {}
#[tracing::instrument]
async fn b2() {}
#[tracing::instrument]
async fn a1() {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
tracing::info!("sleep done");
b1().await;
tracing::info!("a1 done");
}
#[tracing::instrument]
async fn a2() {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
tracing::info!("sleep done");
b2().await;
}
#[tracing::instrument]
async fn t1() {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
a1().await;
}
#[tracing::instrument]
async fn t2() {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
a2().await;
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
tracing_subscriber::Registry::default()
.with(
tracing_tree::HierarchicalLayer::new(4)
.with_span_retrace(true)
.with_span_modes(true)
.with_indent_lines(true)
.with_verbose_entry(true),
)
.init();
let _span = tracing::info_span!("main").entered();
tracing::info!("foo");
tokio::spawn(t1().instrument(tracing::info_span!("t1-task")));
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
tokio::spawn(t2().instrument(tracing::info_span!("t2-task")));
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
} Behavior #1 (as it always prints the parent of the new/leaf span, it prints Behavior #2 (no duplicates as it always prints the parent of the chain root (if present)) |
@oli-obk could you have a look at this? I'd appreciate any input on how you think this looks, as I consider it complete 😊 |
Thanks! looks great. |
Fixes: #74
Previously, spans were not retraced if they were printed by a nested span open event, as it was wrongfully assumed a span only printed once an event was generated by it, and not by its entering alone.
This further fixes
verbose_entry
combined withretrace
, as the latter broke the indent line connectivity and only printed the immediate successor of the span, not the parent of the entered tree (as multiple spans can be entered at once during retracing)This is now fixed, which means that
retrace=true, deferred=false
should now work properly for interleaved or multithreaded futures.