-
-
Notifications
You must be signed in to change notification settings - Fork 153
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(sentry-tracing): switch sentry spans on enter and exit #686
Conversation
7a4b72c
to
a138e3c
Compare
a138e3c
to
3636ca1
Compare
7a4b72c
to
6f19f1d
Compare
For those cases, one should usually fork the Sentry Hub in order to have them fully isolated. While you are right that enter/exit is a better fit, and when someone is manually hooking up spans, this distinction can lead to some confusion. |
Hi @saiintbrisson, are you able to solve this problem with hub isolation? I would honestly be a bit hesitant to change how we enter and exit Sentry spans, since others might be relying on the current behavior. But, we can look into it if you are unable to find a way to work around this problem. |
I ended up just using my fork at my company. Hub isolation is pretty verbose as I would have to bind it to every future as it currently stand. I already isolate it for my root future (I have a Axum middleware binding a hub to the handler call). The problem arises on child futures, like Probably manually binding a hub to every call inside my join would work, but I don't want to make my coworkers handle this kind of detail during development. We have a couple of hundreds of mentions of If this happens to be a wont-fix, I'll probably just create my own tracing layer with this impl, but I do think |
Yes that is a bit unfortunate, but ultimately the correct thing to do. Apart from proper span hierarchy, this also relates to Sentrys Scope and other concepts, which could go out of sync if multiple concurrent futures are messing with them. |
I don't think I understand how Scopes are to be used. I currently create a new Hub, create a transaction and set it to the created Hub, that I than use to bind it to the handler call (one scope per request). The way you described it, it seems like every future should have its own Scope? In any case, I expected Let me know if you folks come to any conclusion about this PR. For now, I'll create my own layer impl and move the Thanks for your time and keep up the good work, we've been enjoying Sentry a lot around here :). |
All in all, thank you for the great feedback, this is very valuable.
I might have added a bit to the confusion here. The Rust SDK still has a couple of concepts that have since been removed from the wider "Sentry unified API". For example, there are no Anyhow, in essence you want every future to have its own Scope (which in the Rust SDK is still named
The As I mentioned, the Rust SDK is quite a bit behind in terms of features. By now, the Sentry JS SDK has fully embraced opentelemetry, the SDK and instrumentation side that is. I could maybe imagine Sentry doing something similar in the sense of not duplicating all this span tracking, etc, but fully embracing |
I think this is useful even outside of Futures. My application doesn't do any async but whenever we create a new thread we also create a new tracing span for that thread. The span is created before the new thread (to inherit the current span as the parent) but then only enter it inside the new thread. If I am understanding this issue correctly, currently any events between the creation of the span and the entering of the span will have the wrong span information. While I understand this is a change in behavior I think the current behavior is fairly unexpected and not intuitive. |
I just noticed that my PR #700 does the same thing So I might as well close it, but I would like to point few obvious things with the way sentry does things. Moving scope change to enter/exit will solve majority of issues aside from multi threaded environments. But you cannot make tracing span works without changing scope setting to the on enter/exit |
I'm with you. Though this might not fix everything, it surely fixes most of it. I've been using my fork at my employer and haven't really had any issues up to now. |
I looked over code again and how bind_hub works Hub could be stored together with span and on every This should ensure tracing span will retain the same hub across any thread, if I understood its purpose properly TL;DR pub(super) struct SentrySpanData {
pub(super) sentry_span: TransactionOrSpan,
parent_sentry_span: Option<TransactionOrSpan>,
creation_hub: Arc<sentry_core::Hub>,
//Set to Some() on enter, set to None in on_exit
switch_guard: Option<sentry_core::hub_impl::SwitchGuard>
} |
@saiintbrisson Can you maybe rebase your work on current master? I'm thinking to use patched version of sentry and maybe will make PR against yours to add Switch hub guard |
I created prototype of my idea: It will capture Hub on span creation and create switch guard on every enter of the span while dropping guard in exit @Swatinem I believe it should solve all possible concerns with this PR |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #686 +/- ##
==========================================
+ Coverage 72.79% 72.82% +0.02%
==========================================
Files 66 66
Lines 7804 7830 +26
==========================================
+ Hits 5681 5702 +21
- Misses 2123 2128 +5 |
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 had another look at this.
It looks good as is, but feel free to also fix the nits that I added before merging.
@saiintbrisson Can you apply comments on your PR? |
CI checks are also still unhappy :-( |
This is due to Rust team introducing unnecessary lints with each version Do you want to silence it? Nevermind, we need to rebase this branch on master 9b82c90 |
Hi! Yeah, I'll push fixes in a few hours, thanks for the patience 😅 |
8f139e3
to
bff4693
Compare
bff4693
to
e191a1f
Compare
@Swatinem I think this is good to go now. Thanks again for your time and the team for the amazing product. And thanks @DoumanAsh for the support and getting it to the final solution. |
Thank you for your patience and persistence here :-) |
I've been facing a bug with Sentry Trace where concurrent spans end up wrongly nested. At first, I thought this was some strange autogrouping bug and event sent a feedback (sorry Sentry support member 😅).
After digging a little bit, I discovered that the current tracing layer implementation sets the sentry span as active as soon as a tracing span is created, which should not be the case, as spans are only active once entered. Following the same logic, it also reverts to the parent span only when a span is closed, and not when it's exited.
A span can be entered and exited multiple times, for example, when a tracing
Instrumented
future polls and returns Pending. In case of concurrent Instrumented futures, the current impl ends up nesting Futures under the first created one.sentry-tracing
layer (wrong)tracing-opentelemetry
layer (correct)