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

Add rest-client instrumentation adapter #172

Merged
merged 2 commits into from
Feb 18, 2020
Merged

Add rest-client instrumentation adapter #172

merged 2 commits into from
Feb 18, 2020

Conversation

grantbdev
Copy link
Contributor

Overview

Add rest-client instrumentation adapter similar to the existing adapter for Faraday.

The rest-client gem uses restclient internally for file/folder naming, so I used that style for the adapter code. The gem's README also titleizes the name as simply "REST Client", so that is used in some spots but if that is too confusing I could try to clarify or consolidate on a single name.

Related

@grantbdev grantbdev marked this pull request as ready for review January 22, 2020 04:51
Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

This is a great start @grantbdev! A number of things have changed over the last week that helps to streamline setup and install instrumentation. A good portion of my suggestions are based on those improvements. As I went through this PR, I realized that there were some existing issues with the Faraday and Sinatra adapters and ultimately made #177 to address them. I reference that PR in a number of comments and it corrects a few issues in our current instrumentation "template".

adapters/restclient/example/Gemfile Show resolved Hide resolved
adapters/restclient/example/restclient.rb Outdated Show resolved Hide resolved
adapters/restclient/example/restclient.rb Outdated Show resolved Hide resolved
adapters/restclient/example/restclient.rb Outdated Show resolved Hide resolved
adapters/restclient/test/test_helper.rb Outdated Show resolved Hide resolved
module RestClient
class Adapter < OpenTelemetry::Instrumentation::Adapter
install do |config|
require_dependencies
Copy link
Member

Choose a reason for hiding this comment

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

I'm taking a mental note of how. many times I see this in adapters. It might make sense to make this an optional part of the DSL at some point.

@grantbdev
Copy link
Contributor Author

@mwear Thank you for the feedback! I've pushed up my changes.

Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

As I go through these adapters with a fine tooth comb, I find a few more holes in our instrumentation template. I noticed that we are not using Rubocop on the instrumentation adapters, which lead me to create #179. We should add it for all instumentation adapters (including this one). You can look at #173, but the basic approach will be to:

@grantbdev
Copy link
Contributor Author

@mwear Feedback addressed.

Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

This looks great @grantbdev. Thanks for working through my feedback as we hone our instrumentation template.

end

OpenTelemetry::SDK.configure do |c|
c.use 'OpenTelemetry::Adapters::Faraday', tracer_middleware: NoOp
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mwear @elskwid Based on our discussion, I've updated the example files to use the proper installation and to have the no-op examples in separate files.


def trace_request # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
span = tracer.start_span(
url,
Copy link
Member

Choose a reason for hiding this comment

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

This will lead to high-cardinality span names. See: #175 (comment).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mwear We could use "HTTP #{METHOD_NAME}". If that sounds good I'll update both PRs.

Only other thing I can think of that would add specificity without introducing a lot more would be to include URL host/domain.

@grantbdev
Copy link
Contributor Author

@mwear Updated this PR with lower-cardinality span names and a few other tweaks I've found from working on more adapters.

Do you think we should add setting of span.status to each adapter?
https://github.com/mutations/opentelemetry-ruby/commit/35204f07cb543ec3e533365f6cb148fb0f4ca866#diff-d5fef5fa085cedfa6cea4c783a6bd8c2R47

Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

Good call on setting span.status. We should be doing that here and on the other http client spans. I had a couple of other comments.

@grantbdev
Copy link
Contributor Author

@mwear Feedback addressed.

@grantbdev
Copy link
Contributor Author

PR updated to use "HTTP #{method_name}" span names as discussed in the SIG meeting.

Copy link
Member

@mwear mwear left a comment

Choose a reason for hiding this comment

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

There's one last change now that the context prop PR has merged. You'll probably want to rebase, make the suggested change, and ensure things work.

@grantbdev
Copy link
Contributor Author

@mwear PR updated and I made sure to use the block that provides the span context for restclient like you suggested for excon.

I'm not sure that we have anything explicitly testing propagation, let me know if you have ideas on how to accomplish that.

@mwear
Copy link
Member

mwear commented Feb 7, 2020

@grantbdev Thanks for bringing up propagation tests. It is something we should test and in general, we should port over applicable tests when converting Datadog instrumentation. Here is an example from dd-trace-rb: https://github.com/DataDog/dd-trace-rb/blob/master/spec/ddtrace/contrib/rest_client/request_patch_spec.rb#L196-L209

By default OpenTelemetry.propagation.http_injectors is empty, making inject effectively a no-op. You could setup a custom injector for your test, or you could just use the trace context injector. Currently, there is a debate as to whether or not trace context should be a default injector. You can use the Datadog test as template and setup an injector like so:

before do
  # these are currently empty, but this will future proof the test
  @orig_injectors = OpenTelemetry.propagation.http_injectors
  OpenTelemetry.propagation.http_injectors = [OpenTelemetry::Trace::Propagation.http_trace_context_injector]
end

after do
  OpenTelemetry.propagation.http_injectors = @orig_injectors
end

@grantbdev
Copy link
Contributor Author

@mwear Tests added, let me know what you think. I wasn't sure if we should use the TraceParent class directly to generate the header value in the test and I didn't know how to get the context for that approach either.

@mwear
Copy link
Member

mwear commented Feb 8, 2020

👀 ing good @grantbdev. Thanks for addressing all my feedback. I am slightly weirded out that the assertions check for headers['Traceparent'] when the injector uses traceparent as the key. Out of curiosity, do you know if that is the libraries doing that normalization?

Anyhow, I am happy with where this is. Would you like me to leave this open for you to take a look @fbogsany, or should I go ahead and merge?

@grantbdev
Copy link
Contributor Author

@mwear I think the capitalization is coming from the libraries. So far, all of them except ethon (which I haven't opened a PR for yet) have capitalized the traceparent header.

@mwear
Copy link
Member

mwear commented Feb 18, 2020

This has been open for a bit and hasn't received any new comments. I'd like to merge it, but will need a rebase first.

@grantbdev
Copy link
Contributor Author

@mwear Rebased

mwear pushed a commit that referenced this pull request Feb 18, 2020
* Add datadog-porting-guide

* Reflection on experiences implementing instrumentation adapters so far
  (faraday, sinatra, rack)

* Update based on recent PR comments

* e.g., #172

* Update with suggestions from PR

* Make a note about runtime performance considerations

* usually show up as requests in submitted PRs
Add `rest-client` instrumentation adapter
based on the adapter for Faraday and `ddtrace` code for `rest-client`.

The `rest-client` gem uses `restclient` internally for file and folder
naming, so I used that style for most of the internal adapter code.
`rest-client` is used for names referring to the gem name itself.

Related to #67
Update `faraday` adapter
to match changes in the `rest-client` adapter.

In the example code, the install call is replaced
to work with the structure changes from #175.

Support for disabling span reporting via a custom override
is no longer provided since there is not a need for it at this time.
This also removes the need to support injection of custom middleware.

In the tracer middleware, the HTTP method attribute value
is set to an uppercase string to be compliant with the specification.
The name of the span is set to "HTTP #{verb}"
to reduce the cardinality of the span names as described in the spec.
The span status is now set when the response is received.
The span propagation is now done directly.

Propagated headers are now tested.
@mwear
Copy link
Member

mwear commented Feb 18, 2020

Thanks @grantbdev!

@mwear mwear merged commit 8745e14 into open-telemetry:master Feb 18, 2020
@grantbdev grantbdev deleted the gb/feature--rest-client-instrumentation--67 branch February 18, 2020 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants