-
Notifications
You must be signed in to change notification settings - Fork 98
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 context inheritance via prepend
instead of changing Thread
#230
Open
ivoanjo
wants to merge
2
commits into
TwP:master
Choose a base branch
from
DataDog:use-prepend-instead-of-modifying-thread-class
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Add context inheritance via prepend
instead of changing Thread
#230
ivoanjo
wants to merge
2
commits into
TwP:master
from
DataDog:use-prepend-instead-of-modifying-thread-class
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Directly modifying the `Thread` class leads to `stack level too deep (SystemStackError)` if other gems have prepended modules to `Thread`, see for instance: * <rollbar/rollbar-gem#1018> * <MiniProfiler/rack-mini-profiler#444> * <https://github.com/DataDog/dd-trace-rb/blob/master/docs/GettingStarted.md#stack-level-too-deep> This behavior can be triggered with the following example app (NOTE: the issue is triggered only on Linux, as due to unrelated reasons the ddtrace gem only adds the module to `Thread` on that OS): ```ruby require 'bundler/inline' gemfile do source 'http://rubygems.org' gem 'logging', '= 2.3.0', require: false gem 'ddtrace', '= 0.50.0', require: false gem 'google-protobuf' end require 'ddtrace' Datadog.configure do |c| c.profiling.enabled = true end require 'logging' Thread.new { }.join ``` By changing context inheritance to use a `prepend`, it becomes compatible with all libraries that use this technique as well.
`ruby2_keywords` enables keyword arguments to work on Ruby 3.0 `Thread`s that have been prepended with `InheritContext`.
Update: Experiment didn't work, either this patch or |
ivoanjo
added a commit
to DataDog/dd-trace-rb
that referenced
this pull request
Jun 17, 2021
This is a repeat of #1362 -- the logging gem also monkey patches `Thread` initialization using `alias_method`, which is incompatible with our instrumentation that uses `preload`. For details, see TwP/logging#230 where we submitted a fix to the upstream gem. Right now the only way to avoid this issue and still enable proflier is to either remove the logging gem or to disable the feature using the `LOGGING_INHERIT_CONTEXT` environment variable. If/when the gem creators accept our proposed change and release it, we'll need to revise this to take that into consideration, as we do for rollbar. NOTE: I'm not entirely happy with the complexity that is accumulating for the tests, but I've decided to not refactor it yet. If we need to add more gems, we should definitely refactor the tests. My hope is that soon we can get rid of our `Thread` monkey patches, and thus get rid of all of this instead.
ivoanjo
added a commit
to DataDog/dd-trace-rb
that referenced
this pull request
Jun 17, 2021
Instead, customers will get the following log message: ``` INFO -- ddtrace: [ddtrace] (/app/lib/ddtrace/profiling/tasks/setup.rb :44:in `activate_cpu_extensions') CPU time profiling skipped because native CPU time is not supported: The `logging` gem is installed and its thread inherit context feature is enabled. Please add LOGGING_INHERIT_CONTEXT=false to your application's environment variables to disable the conflicting `logging` gem feature. See TwP/logging#230 for details. Profiles containing Wall time will still be reported. ``` This is a repeat of #1362 -- the logging gem also monkey patches `Thread` initialization using `alias_method`, which is incompatible with our instrumentation that uses `preload`. For details, see TwP/logging#230 where we submitted a fix to the upstream gem. Right now the only way to avoid this issue and still enable proflier is to either remove the logging gem or to disable the feature using the `LOGGING_INHERIT_CONTEXT` environment variable. If/when the gem creators accept our proposed change and release it, we'll need to revise this to take that into consideration, as we do for rollbar. NOTE: I'm not entirely happy with the complexity that is accumulating for the tests, but I've decided to not refactor it yet. If we need to add more gems, we should definitely refactor the tests. My hope is that soon we can get rid of our `Thread` monkey patches, and thus get rid of all of this instead.
ivoanjo
added a commit
to DataDog/dd-trace-rb
that referenced
this pull request
Jun 17, 2021
Instead, customers will get the following log message: ``` INFO -- ddtrace: [ddtrace] (/app/lib/ddtrace/profiling/tasks/setup.rb :44:in `activate_cpu_extensions') CPU time profiling skipped because native CPU time is not supported: The `logging` gem is installed and its thread inherit context feature is enabled. Please add LOGGING_INHERIT_CONTEXT=false to your application's environment variables to disable the conflicting `logging` gem feature. See TwP/logging#230 for details. Profiles containing Wall time will still be reported. ``` This is a repeat of #1362 -- the logging gem also monkey patches `Thread` initialization using `alias_method`, which is incompatible with our instrumentation that uses `preload`. For details, see TwP/logging#230 where we submitted a fix to the upstream gem. Right now the only way to avoid this issue and still enable proflier is to either remove the logging gem or to disable the feature using the `LOGGING_INHERIT_CONTEXT` environment variable. If/when the gem creators accept our proposed change and release it, we'll need to revise this to take that into consideration, as we do for rollbar. NOTE: I'm not entirely happy with the complexity that is accumulating for the tests, but I've decided to not refactor it yet. If we need to add more gems, we should definitely refactor the tests. My hope is that soon we can get rid of our `Thread` monkey patches, and thus get rid of all of this instead.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
👋 Hello there!
I work at @DataDog on our open-source Ruby APM library,
ddtrace
.One of our users has ran into an issue where
logging
'sThread
inherit context behavior was conflicting with dd-trace's own extensions toThread
, leading to astack level too deep (SystemStackError)
due to both of our extensions conflicting.We've seen this happen from time to time, e.g. rollbar/rollbar-gem#1018 or MiniProfiler/rack-mini-profiler#444. (See also rails/rails#19434 and rails/rails#19413 where rails moved to
prepend
as well)Changing
logging
to useprepend
makes it compatible with all libraries that have moved to useprepend
.Furthermore, while I was in the neighbourhood, I've added the tweaks necessary to not break Ruby 3.0 keyword arguments when used with threads, as well as a test to cover it.
I've tested these changes with Ruby 2.4, 2.7 and 3.0.
Hopefully this change is acceptable? Let me know if I can provide any more info or help, as we're really interested in solving this 😀
Note: As documented in the logging source code, setting the
LOGGING_INHERIT_CONTEXT
environment variable tofalse
also avoids this issue, although at the cost of loosing that helpful feature.