-
Notifications
You must be signed in to change notification settings - Fork 380
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
Roda Integration #2368
Roda Integration #2368
Conversation
… status codes and without the tracer.
…ests to spec for roda.
…rom the instrumentation.
…d tracing for the instrumentation.
… instrumentation and move files to correct new contrib paths.
… access to the status code
end | ||
|
||
def call | ||
instrument(Ext::SPAN_REQUEST) { super } |
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 move the error handling logic to the caller
def call
instrument(Ext::SPAN_REQUEST) do |span|
super
rescue => e
# ... Handle error
end
end
So you could be confident yielding in the block without nested begin/rescue.
response = yield span
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.
It looks like in the Roda code, dispatch can land on one of these methods (seen in this conditional)
Would I need to duplicate the rescue block and handle the error in both since either one of these can handle the dispatch?
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.
As an update to this, I wasn't able to move the error handling logic anywhere else because it interfered with the errors produced by the underlying app.
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.
Looks pretty good! 👍
I update this branch. The errors now look like regular PR test errors. |
**What does this PR do?**: This PR was extracted from the Roda integration PR (#2368) and includes **only** the addition of `roda` to the appraisals + the result of running `bundle exec rake appraisal:install`. **Motivation**: I decided to break this from #2368 as fiddling with appraisals has caused a lot of back-and-forth and lost time on a PR that is otherwise in good shape. Let's merge this as fast as possible, and then that PR can focus only on adding Roda. **Additional Notes**: (N/A) **How to test the change?**: Roda testing will come as part of #2368. This PR is mostly a no-op, and CI should still be green.
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.
Looking clean, well organized as I'd expect a good integration to be!
Some minor tweaks on edge cases involving errors/versions worth examining. Please see comments for more details.
Where relevant or useful, I would suggest also adding code comment documentation as it might help an unfamiliar developer wrap their head around instrumentation behavior.
ensure | ||
begin | ||
response = yield | ||
rescue |
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.
Generally recommend classifying what kind of error is caught: StandardError
if you don't want to trap kill signals, Exception
if you want all signals (have be to very careful when catching Exception
). StandardError
is likely correct here.
To clarify, the purpose here is to add additional tags in case of an error? I think it might be better to provide an on_error
argument to the #trace
call, as it will handle the exception and what not for you. this way you can eliminate the begin/rescue
in the ensure
. Bonus is that it will handle Exception
for you.
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 paired with Wan on this one as well, and the on_error
would not fit well for this case because we need the local closure variable request_method
in the error handler.
If we extract the error handling to on_error: method(:handle_error)
, then def handle_error
does not have access to request_method
.
Alternatively, we could declare it inlince on_error: ->{...}
but the method is pretty large.
I think we can keep it as in this file, as the alternatives are less legible.
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 paired with Wan on this one as well, and the on_error
would not fit well for this case because we need the local closure variable request_method
in the error handler.
If we extract the error handling to on_error: method(:handle_error)
, then def handle_error
does not have access to request_method
.
Alternatively, we could declare it inlince on_error: ->{...}
but the method is pretty large.
I think we can keep it as in this file, as the alternatives are less legible.
# The status code is unknown to Roda and decided by the upstream web runner. | ||
# In this case, spans default to status code 500 rather than a blank status code. | ||
default_error_status = '500' | ||
span.resource = "#{request_method} #{default_error_status}" |
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.
Possibly strange edge case here where request.request_method.to_s.upcase
raised an error, hit the ensure
block, request raised an error, caught by this rescue
block, then request_method
will likely be undefined, possibly raising another error.
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'm not sure how this error can be thrown because all routes should be defined with a type from the start. Do you have a suggestion for handling this scenario?
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 paired with Wan and it's not possible for request.request_method.to_s.upcase
to fail, as it comes straight from Rack and it's part of the Rack contract. This is the same behaviour of our other Rack-ralated integrations (Sinatra, Rails, Hanami, Grace)
include Contrib::Integration | ||
|
||
MINIMUM_VERSION = Gem::Version.new('2.0.0') | ||
MAXIMUM_VERSION = Gem::Version.new('4.0.0') |
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.
Good to know this maximum. Do we know we don't support Roda 4.0.0? If so, why don't we?
Also "maximum" version as a name is slightly misleading in that its exclusive (we don't actually support 4.0.0.)
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.
At the time of this comment: Roda 4.x isn't out. The latest version is 3.65.0.
Given the changes that occurred between 1.x and 2.x, I'm just being cautious by setting a maximum of 4.x for now. That way, in our public docs, we can be clear that this logic is intended for 2.x and 3.x.
Whenever 4.x comes out, it'll require visiting to make sure it still functions as expected.
docs/GettingStarted.md
Outdated
@@ -511,6 +512,7 @@ For a list of available integrations, and their configuration options, please re | |||
| Redis | `redis` | `>= 3.2` | `>= 3.2` | *[Link](#redis)* | *[Link](https://github.com/redis/redis-rb)* | | |||
| Resque | `resque` | `>= 1.0` | `>= 1.0` | *[Link](#resque)* | *[Link](https://github.com/resque/resque)* | | |||
| Rest Client | `rest-client` | `>= 1.8` | `>= 1.8` | *[Link](#rest-client)* | *[Link](https://github.com/rest-client/rest-client)* | | |||
| Roda | `roda` | `>= 2.1` | `>= 2.1` | *[Link](#roda)* | *[Link](https://github.com/jeremyevans/roda)* | |
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 there's an upper limit on versions we support, we should add that here as well.
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 catch! I was being cautious by hardcoding a limit of 4.x, so I should update this Getting Started doc 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.
In the latest commit, this now gives a range ending <4 (since it works with 3.x):
| Roda | `roda` | `>= 2.1, <4` | `>= 2.1, <4` | *[Link](#roda)* | *[Link](https://github.com/jeremyevans/roda)*
add latest changes
…distributed tracing option in favor of allowing Rack to do it instead, and load in Rack by default when integration is loaded.
add latest changes into branch
update with latest changes
add latest changes
# Patcher enables patching of 'roda' | ||
module Patcher | ||
include Contrib::Patcher | ||
::Roda.use Datadog::Tracing::Contrib::Rack::TraceMiddleware if defined? ::Roda |
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.
We should remove this top-level call and instead, due to lack of a good way to automatically instrument Roda+Rack, we should add this manual step to the readme.
add latest changes
…plications wll need to call on it. Tests and GettingStarted have been updated for that change.
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.
Thank you so much, @wantsui! 🙇
What does this PR do?
Continues on the great work started by @randy-girard in #718 by working on a Roda Integration that works with dd-trace-rb 1.x .
Code to trigger automatic instrumentation
Available Configuration Options
Example trace:
Motivation
Add support for Roda
Additional Notes
Addressed Notes:
It is highly recommended to load in Rack through
use Datadog::Tracing::Contrib::Rack::TraceMiddleware
because Rack handles the context propagation for distributed tracing.How to test the change?
See Checks ran.