Skip to content

Commit

Permalink
Add Net:HTTP instrumentation adapter (#187)
Browse files Browse the repository at this point in the history
Add `Net::HTTP` instrumentation adapter
based on other HTTP client adapters and the related `ddtrace` code.
  • Loading branch information
grantbdev authored Feb 28, 2020
1 parent ba8b7b6 commit b9df39e
Show file tree
Hide file tree
Showing 18 changed files with 438 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ commands:
bundle install --jobs=3 --retry=3
bundle exec appraisal install
bundle exec appraisal rake test
- run:
name: Bundle + CI (Adapters - Net::HTTP)
command: |
cd adapters/net_http
gem uninstall -aIx bundler
gem install --no-document bundler -v '~> 2.0.2'
bundle install --jobs=3 --retry=3
bundle exec rake test
- run:
name: Bundle + CI (Adapters - Redis)
command: |
Expand Down
6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ GEM_INFO = {
OpenTelemetry::Adapters::Faraday::VERSION
}
},
"opentelemetry-adapters-net_http" => {
version_getter: ->() {
require './lib/opentelemetry/adapters/net/http/version.rb'
OpenTelemetry::Adapters::Net::HTTP::VERSION
}
},
"opentelemetry-adapters-redis" => {
version_getter: ->() {
require './lib/opentelemetry/adapters/redis/version.rb'
Expand Down
27 changes: 27 additions & 0 deletions adapters/net_http/.rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
AllCops:
TargetRubyVersion: '2.4.0'

Bundler/OrderedGems:
Exclude:
- gemfiles/**/*
Lint/UnusedMethodArgument:
Enabled: false
Metrics/AbcSize:
Max: 18
Metrics/LineLength:
Enabled: false
Metrics/MethodLength:
Max: 20
Metrics/ParameterLists:
Enabled: false
Naming/FileName:
Exclude:
- "lib/opentelemetry-adapters-net-http.rb"
Style/FrozenStringLiteralComment:
Exclude:
- gemfiles/**/*
Style/ModuleFunction:
Enabled: false
Style/StringLiterals:
Exclude:
- gemfiles/**/*
15 changes: 15 additions & 0 deletions adapters/net_http/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

source 'https://rubygems.org'

gemspec

gem 'opentelemetry-api', path: '../../api'

group :test do
gem 'opentelemetry-sdk', path: '../../sdk'
end
28 changes: 28 additions & 0 deletions adapters/net_http/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require 'bundler/gem_tasks'
require 'rake/testtask'
require 'yard'
require 'rubocop/rake_task'

RuboCop::RakeTask.new

Rake::TestTask.new :test do |t|
t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList['test/**/*_test.rb']
end

YARD::Rake::YardocTask.new do |t|
t.stats_options = ['--list-undoc']
end

if RUBY_ENGINE == 'truffleruby'
task default: %i[test]
else
task default: %i[test rubocop yard]
end
7 changes: 7 additions & 0 deletions adapters/net_http/example/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gem 'opentelemetry-adapters-net-http', path: '../../../adapters/net_http'
gem 'opentelemetry-api', path: '../../../api'
gem 'opentelemetry-sdk', path: '../../../sdk'
13 changes: 13 additions & 0 deletions adapters/net_http/example/net_http.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require 'rubygems'
require 'bundler/setup'
require 'net/http'

Bundler.require

OpenTelemetry::SDK.configure do |c|
c.use 'OpenTelemetry::Adapters::Net::HTTP'
end

Net::HTTP.get(URI('http://example.com'))
7 changes: 7 additions & 0 deletions adapters/net_http/lib/opentelemetry-adapters-net-http.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require_relative './opentelemetry/adapters'
16 changes: 16 additions & 0 deletions adapters/net_http/lib/opentelemetry/adapters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
# "Instrumentation adapters" are specified by
# https://github.com/open-telemetry/opentelemetry-specification/blob/57714f7547fe4dcb342ad0ad10a80d86118431c7/specification/overview.md#instrumentation-adapters
#
# Adapters should be able to handle the case when the library is not installed on a user's system.
module Adapters
end
end

require_relative './adapters/net/http'
20 changes: 20 additions & 0 deletions adapters/net_http/lib/opentelemetry/adapters/net/http.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

require 'opentelemetry'

module OpenTelemetry
module Adapters
module Net
# Contains the OpenTelemetry adapter for the Net::HTTP gem
module HTTP
end
end
end
end

require_relative './http/adapter'
require_relative './http/version'
36 changes: 36 additions & 0 deletions adapters/net_http/lib/opentelemetry/adapters/net/http/adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module Adapters
module Net
module HTTP
# The Adapter class contains logic to detect and install the Net::HTTP
# instrumentation adapter
class Adapter < OpenTelemetry::Instrumentation::Adapter
install do |_config|
require_dependencies
patch
end

present do
defined?(::Net::HTTP)
end

private

def require_dependencies
require_relative 'patches/instrumentation'
end

def patch
::Net::HTTP.prepend(Patches::Instrumentation)
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module Adapters
module Net
module HTTP
module Patches
# Module to prepend to Net::HTTP for instrumentation
module Instrumentation
HTTP_METHODS_TO_SPAN_NAMES = Hash.new { |h, k| h[k] = "HTTP #{k}" }
USE_SSL_TO_SCHEME = { false => 'http', true => 'https' }.freeze

def request(req, body = nil, &block)
# Do not trace recursive call for starting the connection
return super(req, body, &block) unless started?

tracer.in_span(
HTTP_METHODS_TO_SPAN_NAMES[req.method],
attributes: {
'component' => 'http',
'http.method' => req.method,
'http.scheme' => USE_SSL_TO_SCHEME[use_ssl?],
'http.target' => req.path,
'peer.hostname' => @address,
'peer.port' => @port
},
kind: :client
) do |span|
OpenTelemetry.propagation.inject(req)

super(req, body, &block).tap do |response|
annotate_span_with_response!(span, response)
end
end
end

private

def annotate_span_with_response!(span, response)
return unless response&.code

status_code = response.code.to_i

span.set_attribute('http.status_code', status_code)
span.status = OpenTelemetry::Trace::Status.http_to_status(
status_code
)
end

def tracer
Net::HTTP::Adapter.instance.tracer
end
end
end
end
end
end
end
15 changes: 15 additions & 0 deletions adapters/net_http/lib/opentelemetry/adapters/net/http/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

module OpenTelemetry
module Adapters
module Net
module HTTP
VERSION = '0.0.0'
end
end
end
end
39 changes: 39 additions & 0 deletions adapters/net_http/opentelemetry-adapters-net-http.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

# Copyright 2020 OpenTelemetry Authors
#
# SPDX-License-Identifier: Apache-2.0

lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'opentelemetry/adapters/net/http/version'

Gem::Specification.new do |spec|
spec.name = 'opentelemetry-adapters-net-http'
spec.version = OpenTelemetry::Adapters::Net::HTTP::VERSION
spec.authors = ['OpenTelemetry Authors']
spec.email = ['[email protected]']

spec.summary = 'Net::HTTP instrumentation adapter for the OpenTelemetry framework'
spec.description = 'Net::HTTP instrumentation adapter for the OpenTelemetry framework'
spec.homepage = 'https://github.com/open-telemetry/opentelemetry-ruby'
spec.license = 'Apache-2.0'

spec.files = ::Dir.glob('lib/**/*.rb') +
::Dir.glob('*.md') +
['LICENSE']
spec.require_paths = ['lib']
spec.required_ruby_version = '>= 2.4.0'

spec.add_dependency 'opentelemetry-api', '~> 0.0'

spec.add_development_dependency 'bundler', '>= 1.17'
spec.add_development_dependency 'minitest', '~> 5.0'
spec.add_development_dependency 'opentelemetry-sdk', '~> 0.0'
spec.add_development_dependency 'rake', '~> 13.0.1'
spec.add_development_dependency 'rubocop', '~> 0.73.0'
spec.add_development_dependency 'simplecov', '~> 0.17.1'
spec.add_development_dependency 'webmock', '~> 3.7.6'
spec.add_development_dependency 'yard', '~> 0.9'
spec.add_development_dependency 'yard-doctest', '~> 0.1.6'
end
4 changes: 4 additions & 0 deletions adapters/net_http/test/.rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
inherit_from: ../.rubocop.yml

Metrics/BlockLength:
Enabled: false
Loading

0 comments on commit b9df39e

Please sign in to comment.