-
Notifications
You must be signed in to change notification settings - Fork 374
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
DEBUG-3182 Rework DI loading #4239
base: master
Are you sure you want to change the base?
Conversation
Datadog ReportBranch report: ✅ 0 Failed, 22130 Passed, 1475 Skipped, 5m 19.32s Total Time |
# DI code tracker is instantiated globally before the regular set of | ||
# components is created, but the code tracker needs to call out to the | ||
# "current" DI component to perform instrumentation when application | ||
# code is loaded. Because this call may happen prior to Datadog | ||
# components having been initialized, we maintain the "current component" | ||
# which contains a reference to the most recently instantiated | ||
# DI::Component. This way, if a DI component hasn't been instantiated, | ||
# we do not try to reference Datadog.components. | ||
# In other words, this method exists so that we never attempt to call | ||
# Datadog.components from the code tracker. | ||
def current_component | ||
LOCK.synchronize do | ||
@current_components&.last | ||
end | ||
end | ||
|
||
# To avoid potential races with DI::Component being added and removed, | ||
# we maintain a list of the components. Normally the list should contain | ||
# either zero or one component depending on whether DI is enabled in | ||
# Datadog configuration. However, if a new instance of DI::Component | ||
# is created while the previous instance is still running, we are | ||
# guaranteed to not end up with no component when one is running. | ||
def add_current_component(component) | ||
LOCK.synchronize do | ||
@current_components ||= [] | ||
@current_components << component | ||
end | ||
end | ||
|
||
def remove_current_component(component) | ||
LOCK.synchronize do | ||
@current_components&.delete(component) | ||
end | ||
end |
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.
If I understand your use-case well, you can maybe replace this with something along the lines of
components = Datadog.send(:components, allow_initialization: false)
di = components.di if components
This allows you to access the components without triggering initialization. This is something we use in for instance Datadog::Tracing.correlation
to allow the API to be used, but not cause initialization as a side-effect.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4239 +/- ##
==========================================
- Coverage 97.74% 97.74% -0.01%
==========================================
Files 1355 1357 +2
Lines 82365 82384 +19
Branches 4230 4232 +2
==========================================
+ Hits 80510 80527 +17
- Misses 1855 1857 +2 ☔ View full report in Codecov by Sentry. |
What does this PR do?
This PR separates the part of DI that is required for code tracker (which is the code tracker itself and the DI.current_component group of methods, plus exception classes) to be self-contained. Currently in master loading
datadog/di/init
would bring indatadog/di
as well which is too much (for example, that would cause DI to attempt to load ActiveRecord contrib, which is definitely not the right time for it).Motivation:
Ensuring DI code tracker is loaded early without causing the rest of dd-trace-rb to be loaded early.
Change log entry
Yes: Improved early loading mechanism of dynamic instrumentation (
datadog/di/init
).Additional Notes:
While this PR changes the behavior of
datadog/di/init
, this behavior has not yet been documented anywhere and should not be used by customers.How to test the change?
Integration tests specifically for
datadog/di/init
will be added in a follow-up PR. The existing unit tests verify that basic DI functionality continues to operate correctly.