-
Notifications
You must be signed in to change notification settings - Fork 329
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
Add Storage.CrossThreadLocal #961
Conversation
This storage implements the "unoptimized" version of thread local storage which allows for the scope to be closed in another thread, as it re-resolves the thread local context in `close`
@jatcwang looks good to me! btw, in my local machine I got this bench results:
the variability could be generated by some background process, if I don't close chrome my benchmarks are garbage. :( |
Cool. @dpsoft can you retrigger CI. Seems like a flaky test unrelated to my changes? |
I just ran again the tests! |
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.
Great PR, nice job.
I would only change the sys.props
thing, otherwise it's good to go!
@@ -141,8 +141,10 @@ object ContextStorage { | |||
* instrumentation follows them around. | |||
*/ | |||
private val _contextStorage: Storage = { | |||
if(sys.props("kamon.context.debug") == "true") | |||
if (sys.props("kamon.context.debug") == "true") |
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.
Now that the choice is between a couple of actual implementations, this should probably be loaded from the configuration file, not the environment
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.
Folks, I'm thinking that we should make CrossThreadLocal
the default context storage implementation. The reasons why I think that are:
- It will not affect the behavior of any of the manual/automatic instrumentation. We always aimed to close scopes on the same thread where we created them, and in those situations this implementation will produce the same results. In 99% of the cases we need to close the scope in the same thread we created it anyways, and Cats/Monix implementations are an exception to that common case so we will continue to recommended closing scopes on the same thread, unless it is very clear that there is a reason for doing otherwise, as it is for Cats/Monix.
- It makes it easier to get started. If there is something I learned over the years is that users almost never read the fine print 😄.. if users need to add a JVM property but that property is controlled from the outside world (IDE, command line parameters or container orchestrators), there will be several cases of things "not working" in certain environments. I would rather go with an option that makes it work by default for everyone.
- In the specific cases where someone needs that little boost in performance (I'm counting to be very few cases here) they can add the extra JVM options to use the optimized TLS.
What do you think about that?
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.
This all sounds reasonable, and simplifying semantics is always good!
I'm just scared because this is a "breaking" change, and I have no intuition for how often this code is called.
If you're sure that we won't see a big performance drop, let's do it, and just make sure to document clearly and make not of it in the release notes.
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 agree 100% with the default context storage should be CrossThreadLocal
but would leave the optimized one as an option for experimented/power
users.
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 totally agree @ivantopo (Makes my life easier that's for sure ;)). Happy to make the change if @SimunKaracic agree too
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 agree 🤝
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.
This is done.
@SimunKaracic I did not make it a config because in the kamon.context.Storage.Debug docstring it says we don't allow this be discovered from configuration because it can cause initialization issues when Kamon is first initialized via instrumentation trying to access the current Context
which I think still applies. Added kamon.context.storageType
system property though
- Fix Debug stroage to allow closing the scope in another thread without context contamination. - Add system property to choose a different context storage type
Can someone please retrigger the CI? Seems like a flakey test |
Thank you for the contribution! :D |
This storage implements the "unoptimized" version of thread local storage which allows for the scope to be closed in another thread, as it re-resolves the thread local context in
close
Rerunning the benchmark:
TBH, I don't think the "gain" of the optimized threadlocal implementation is worth keeping (the large variability of the fastThreadLocal is especially interesting). But I'm biased as I primarily work with the Typelevel stack so I'd like to minimize the steps required to get it working with Kamon, especially when failing to do so will lead to horrible cross-thread context contamination