-
Notifications
You must be signed in to change notification settings - Fork 369
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
Multiplexing fix #1227
Multiplexing fix #1227
Conversation
Something is still broken here, a lot of the analytics and sampling specs are failing |
@@ -67,14 +67,19 @@ | |||
context 'and the host matches a specific configuration' do | |||
before do | |||
Datadog.configure do |c| | |||
c.use :ethon, describe: /example\.com/ do |ethon| | |||
c.use :ethon, describes: /example\.com/ do |ethon| |
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.
Nice catch!
I've updated this PR description to match current work |
if pattern.is_a?(Proc) | ||
pattern === name | ||
elsif pattern.is_a?(Regexp) |
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 recommend using #===
for all the supported types, like we do in our SimpleMatcher. In this case, I don't think we should type check, but instead document that patterns must respond to #===
.
You might need to #to_s
the name
, but I'm not sure on 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.
So i've updated this whole pattern to the, far simpler
def resolve(name)
# Try to find a matching pattern
matching_pattern = patterns.find do |pattern|
if pattern.respond_to?(:===)
(pattern === name) || (pattern === name.to_s) || (pattern == name)
end
end
# Return match or default
matching_pattern
end
For the cases in (pattern === name) || (pattern === name.to_s) || (pattern == name)
:
- The first case is needed for when the
pattern
is a Proc or Regexp and thename
is a string (or whatever the Proc or Regexp expect as input). As far as I can tell theProc
===
implementation is an alias for.call
and Regexp===
implementation is equivalent toregex =~ str >= 0
- The second case is needed for when the
pattern
is a Regexp but thename
is something that coerces to a string, likeURL('<url>')
, which is part of our pattern resolver spec. - The final case is needed when the
pattern
is a regexp or proc and thenname
is also a Regexp or Proc, which is howresolver.resolve
gets used within the Configurableadd_configuration
method
Lmk what you think
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.
Can't case 1 and 2 be handled only by 2?
Also, I don't see how in 3 we'd receive a proc or regex as the name parameter. I tried to follow the method you linked, but it seems like we are receiving a regular key there. Also, was this case supported before? I don't see a raw ==
in the original code.
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.
1 and 2 are in opposition unfortunately if we aren't going to differentiate between a Proc and Regexp
Option 1 covers the case where we don't want to coerce the name
for procs, this is covered in spec here for Procs
Option 2 covers the case where we do want to coerce the name
for regexp, this is covered in spec here for Regexp
That being said I can update this to check explicitly for a Proc
to decide between using option 1 or 2. Also can remove the explicit respond_to?(:===)
.
The need for option 3 is because we use resolver.resolve with key
inputs that are both
-
the actal host, url string or string coercablle that we want to match against a pattern, like here
-
but also the
:describes
block (potentially a proc or regex) itself, seen here.
There's a lot of room for improvement in the way we're using resolvers but for now to fit the extisting usage the pattern resolver has to be pretty permissive with what it can resolve against
lib/ddtrace/contrib/configuration/resolvers/pattern_resolver.rb
Outdated
Show resolved
Hide resolved
Co-authored-by: Marco Costa <marco.costa@datadoghq.com>
Updated:
This PR is a first step at addressing #1204 .
As far as I can tell our multiplexing code that relied on
describes
blocks for http clients was never really functional. It appears that, due to the way our PatternResolver attempts toresolve
a key, we woulld always "fallback" to:default
configuration if thatdescribes
pattern has not yet been added, which leads to methods likeconfiguration_for?(key)
to always return true. And sinceconfiguration_for?(key)
always returns true when using a PatternResolver, we never add thedescribes
pattern to the configurations, instead always just overwriting the default, seen here:config = configuration_for?(key) ? configuration(key) : add_configuration(key)
I'm a bit hesitant to modify too much here, as it's unclear to me whether the root issue here is thatThe root issue here is thatA: our
PatternResolver
is returning an unexpected:default
as a fallback incorrectly.B: Or, ourconfiguration_for?(key)
method is incorrectly usingresolver.resolve
to determine whether configuration explicitly exists.So in the meantime I've put in a patch, i'd like to see how this runs against the whole test suite as well. Open to feedback as well, just wanted to start the conversation here.B: Additionally, the test suite for integations that relied on
PatternResolver
were testing with adescribe
block, not adescribes
block. an incorrectly spelled key effectively functions as overwriting the defaults.C: And, lastly, even with the above issues fixed, the
PatternResolver
resolve
method was not properly accounting for Regex patterns, which is the only pattern we document as being accepted bydescribes
So, needless to say there were a few things at work here. Here's what i've done in this PR to clean this up going forward.
PatternResolver
resolve
method now explicitly returns nil in the event the pattern has not yet been added. While a resolver'sresolve
method could hypothetically have a fallback value, given the way it's being used in practice within our configuration code, having it return a fallback value is problematic.the
resolve
method also now has logic to correctly resolve against Regexp patterns.Tests are updated to test against the appropriate
describes
block, and i've added "non-matching" describes blocks to prevent a regression from what is happening in Unable to configure several http services with different service names #1204 where the lastdescribes
block to be configured "wins".The Excon integration had some unusual behavior for how it was determining precedence for it's default configuration code vs it's
middleware
configuration code vs it'sdescribes
configuration code. I've fixed this to support bothdescribes
taking precedence overdefault
andmiddleware
taking precedence overdefault
.I think technically this constitutes a breaking change since it's possible some users have been relying on
describes
code that otherwise wouldn't have "matched" to set config details. So, for example, even if the user putdescribes: localHoost, {service_name: xyz}
instead ofdescribes: localhost, {service_name: xyz}
, theservice_name
would still be set toxyz
while this would now be fixed, we should make sure to not this in release notes.Lmk what you think