-
Notifications
You must be signed in to change notification settings - Fork 714
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
Fixes race condition with toSpan and flush #1306
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright 2013-2020 The OpenZipkin Authors | ||
* Copyright 2013-2021 The OpenZipkin Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except | ||
* in compliance with the License. You may obtain a copy of the License at | ||
|
@@ -192,12 +192,6 @@ public final Span joinSpan(TraceContext context) { | |
} | ||
} | ||
|
||
/** Returns an equivalent context if exists in the pending map */ | ||
TraceContext swapForPendingContext(TraceContext context) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder why this was removed. |
||
PendingSpan pendingSpan = pendingSpans.get(context); | ||
return pendingSpan != null ? pendingSpan.context() : null; | ||
} | ||
|
||
/** | ||
* Explicitly creates a child within an existing trace. The result will be have its parent ID set | ||
* to the input's span ID. If a sampling decision has not yet been made, one will happen here. | ||
|
@@ -377,9 +371,12 @@ public Span toSpan(TraceContext context) { | |
} | ||
|
||
Span toSpan(@Nullable TraceContext parent, TraceContext context) { | ||
// Re-use a pending context if present: This ensures reference consistency on Span.context() | ||
TraceContext pendingContext = swapForPendingContext(context); | ||
if (pendingContext != null) return _toSpan(parent, pendingContext); | ||
// Re-use a pending span if present: This ensures reference consistency on Span.context() | ||
PendingSpan pendingSpan = pendingSpans.get(context); | ||
if (pendingSpan != null) { | ||
if (isNoop(context)) return new NoopSpan(context); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be moved into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could, but it would mean either a redundant check with the call from the overloaded _toSpan, or eliminating the shortcut taken there that avoids unnecessary pendingSpan lookup. |
||
return _toSpan(context, pendingSpan); | ||
} | ||
|
||
// There are a few known scenarios for the context to be absent from the pending map: | ||
// * Created by a separate tracer (localRootId set) | ||
|
@@ -408,6 +405,10 @@ Span _toSpan(@Nullable TraceContext parent, TraceContext context) { | |
|
||
// allocate a mutable span in case multiple threads call this method.. they'll use the same data | ||
PendingSpan pendingSpan = pendingSpans.getOrCreate(parent, context, false); | ||
return _toSpan(context, pendingSpan); | ||
} | ||
|
||
Span _toSpan(TraceContext context, PendingSpan pendingSpan) { | ||
TraceContext pendingContext = pendingSpan.context(); | ||
// A lost race of Tracer.toSpan(context) is the only known situation where "context" won't be | ||
// the same as pendingSpan.context() | ||
|
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.
2022