Skip to content
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

Auto instrument Faraday default connection #1057

Merged
merged 1 commit into from
Jul 10, 2020

Conversation

marcotc
Copy link
Member

@marcotc marcotc commented May 28, 2020

Our auto instrumentation did not configure itself to work with Faraday's default connection.
The default connection is used when using the short Faraday syntax: Faraday.get("http://domain.com/path").

Other use cases that create a Faraday::Connection (Faraday.new, for example) are already auto instrumented.

@marcotc marcotc added the integrations Involves tracing integrations label May 28, 2020
@marcotc marcotc requested a review from a team May 28, 2020 21:42
@marcotc marcotc self-assigned this May 28, 2020
@@ -16,7 +16,7 @@ class Middleware < ::Faraday::Middleware

def initialize(app, options = {})
super(app)
@options = datadog_configuration.options_hash.merge(options)
@options = options
Copy link
Member Author

@marcotc marcotc May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because patching the default connection happens only once and very early in the application lifecycle (at Datadog::Contrib::Faraday::Patcher::patch), we can't convert a Settings object into a hash here, as the settings delegation won't work from this point on. This causes issues, like using a stale version of the Tracer, for example.

Instead we only resolve it at request time, which happens in the build_request_options! method.

@marcotc marcotc force-pushed the fix/faraday-for-default-connection branch from 3e18b8c to cd55e24 Compare May 28, 2020 21:51
@sdrioux
Copy link

sdrioux commented Jun 1, 2020

Hi Marco - any chance this fixes this issue?

#978

@marcotc
Copy link
Member Author

marcotc commented Jun 1, 2020

Hey @sdrioux, are you using ::Faraday.get in your application (in contrast to conn = Faraday.new; conn.get)? If so, then yes, it does fix it.

@marcotc marcotc requested a review from ericmustin July 8, 2020 21:22
Copy link
Contributor

@ericmustin ericmustin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm.

There's one edge case that's not really blocking this PR, but would be good to understand, as I'm not terribly familiar with Faraday. It looks like there's some places where default_connection gets reset, such as when a default_adapter is configured or default_connection_options are configured: https://github.com/lostisland/faraday/blob/5547e9131aa2629cec13a6b3b00ac9daeab9d430/lib/faraday.rb#L102

https://github.com/lostisland/faraday/blob/5547e9131aa2629cec13a6b3b00ac9daeab9d430/lib/faraday.rb#L152

Would this cause our instrumentation to get dropped?

@marcotc
Copy link
Member Author

marcotc commented Jul 10, 2020

That a very good point @ericmustin! When explicitly replacing the default connection, one has to provide a connection instance and thus I think it's reasonable to expect users to configure ddtrace on that connection, just like they would for any new Faraday connection.
I can see the argument for handling that case internally ourselves, but I think we have enough instrumentation options today for Faraday to cover this case.

@marcotc marcotc merged commit 6d0db8f into master Jul 10, 2020
@marcotc marcotc deleted the fix/faraday-for-default-connection branch July 10, 2020 18:11
@marcotc marcotc added this to the 0.38.0 milestone Jul 10, 2020
@tjwp
Copy link
Contributor

tjwp commented Jul 22, 2020

With the v0.38.0 release we're seeing this warning with the default connection:

WARNING: Unexpected middleware set after the adapter. This won't be supported from Faraday 1.0.

The call ::Faraday.default_connection.use(:ddtrace) is appending the trace middleware after the adapter with Faraday v1.0. It would be better to prepend it to the handlers.

@marcotc
Copy link
Member Author

marcotc commented Jul 22, 2020

👋 @tjwp, we've seen this warning before with Faraday < 1, I'm thinking a similar issue happened here. I'll take a look into it. Thank you for reporting!

@fledman
Copy link
Contributor

fledman commented Jul 22, 2020

@marcotc
I believe this should fix the problem:

diff --git a/lib/ddtrace/contrib/faraday/patcher.rb b/lib/ddtrace/contrib/faraday/patcher.rb
index c36e295d..9a01f2ab 100644
--- a/lib/ddtrace/contrib/faraday/patcher.rb
+++ b/lib/ddtrace/contrib/faraday/patcher.rb
@@ -40,14 +40,16 @@ module Datadog
         end
 
         def add_default_middleware!
+          # 1st instrument the default connection (e.g. +Faraday.get+)
+          # 2nd instrument any newly created connections
           if target_version >= Gem::Version.new('1.0.0')
+            ::Faraday.default_connection.use(:ddtrace)
             ::Faraday::Connection.send(:prepend, Connection)
           else
+            idx = ::Faraday.default_connection.builder.handlers.size - 1
+            ::Faraday.default_connection.builder.insert(idx, Middleware)
             ::Faraday::RackBuilder.send(:prepend, RackBuilder)
           end
-
-          # Instrument the Faraday default connection (e.g. +Faraday.get+)
-          ::Faraday.default_connection.use(:ddtrace)
         end
 
         def get_option(option)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrations Involves tracing integrations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants