Skip to content

Commit

Permalink
Refactored: Faraday to use Datadog::Contrib::Integration. (#570)
Browse files Browse the repository at this point in the history
  • Loading branch information
delner authored Oct 1, 2018
1 parent ffb31fc commit f9fed67
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 70 deletions.
2 changes: 1 addition & 1 deletion lib/ddtrace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def configure(target = configuration, opts = {})
require 'ddtrace/contrib/delayed_job/integration'
require 'ddtrace/contrib/elasticsearch/integration'
require 'ddtrace/contrib/excon/integration'
require 'ddtrace/contrib/faraday/patcher'
require 'ddtrace/contrib/faraday/integration'
require 'ddtrace/contrib/grape/integration'
require 'ddtrace/contrib/graphql/patcher'
require 'ddtrace/contrib/http/integration'
Expand Down
22 changes: 22 additions & 0 deletions lib/ddtrace/contrib/faraday/configuration/settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require 'ddtrace/contrib/configuration/settings'
require 'ddtrace/ext/http'
require 'ddtrace/contrib/faraday/ext'

module Datadog
module Contrib
module Faraday
module Configuration
# Custom settings for the Faraday integration
class Settings < Contrib::Configuration::Settings
DEFAULT_ERROR_HANDLER = lambda do |env|
Datadog::Ext::HTTP::ERROR_RANGE.cover?(env[:status])
end

option :distributed_tracing, default: false
option :error_handler, default: DEFAULT_ERROR_HANDLER
option :service_name, default: Ext::SERVICE_NAME
end
end
end
end
end
13 changes: 13 additions & 0 deletions lib/ddtrace/contrib/faraday/ext.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Datadog
module Contrib
module Faraday
# Faraday integration constants
module Ext
APP = 'faraday'.freeze
SERVICE_NAME = 'faraday'.freeze

SPAN_REQUEST = 'faraday.request'.freeze
end
end
end
end
36 changes: 36 additions & 0 deletions lib/ddtrace/contrib/faraday/integration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'ddtrace/contrib/integration'
require 'ddtrace/contrib/faraday/configuration/settings'
require 'ddtrace/contrib/faraday/patcher'

module Datadog
module Contrib
module Faraday
# Description of Faraday integration
class Integration
include Contrib::Integration

register_as :faraday, auto_patch: true

def self.version
Gem.loaded_specs['faraday'] && Gem.loaded_specs['faraday'].version
end

def self.present?
super && defined?(::Faraday)
end

def self.compatible?
super && version < Gem::Version.new('1.0.0')
end

def default_configuration
Configuration::Settings.new
end

def patcher
Patcher
end
end
end
end
end
19 changes: 10 additions & 9 deletions lib/ddtrace/contrib/faraday/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@
require 'ddtrace/ext/http'
require 'ddtrace/ext/net'
require 'ddtrace/propagation/http_propagator'
require 'ddtrace/contrib/faraday/ext'

module Datadog
module Contrib
module Faraday
# Middleware implements a faraday-middleware for ddtrace instrumentation
class Middleware < ::Faraday::Middleware
include Ext::DistributedTracing
include Datadog::Ext::DistributedTracing

def initialize(app, options = {})
super(app)
@options = Datadog.configuration[:faraday].merge(options)
@options = Datadog.configuration[:faraday].to_h.merge(options)
@tracer = Pin.get_from(::Faraday).tracer
setup_service!
end

def call(env)
tracer.trace(NAME) do |span|
tracer.trace(Ext::SPAN_REQUEST) do |span|
annotate!(span, env)
propagate!(span, env) if options[:distributed_tracing] && tracer.enabled
app.call(env).on_complete { |resp| handle_response(span, resp) }
Expand All @@ -32,19 +33,19 @@ def call(env)
def annotate!(span, env)
span.resource = env[:method].to_s.upcase
span.service = service_name(env)
span.span_type = Ext::HTTP::TYPE
span.set_tag(Ext::HTTP::URL, env[:url].path)
span.set_tag(Ext::HTTP::METHOD, env[:method].to_s.upcase)
span.set_tag(Ext::NET::TARGET_HOST, env[:url].host)
span.set_tag(Ext::NET::TARGET_PORT, env[:url].port)
span.span_type = Datadog::Ext::HTTP::TYPE
span.set_tag(Datadog::Ext::HTTP::URL, env[:url].path)
span.set_tag(Datadog::Ext::HTTP::METHOD, env[:method].to_s.upcase)
span.set_tag(Datadog::Ext::NET::TARGET_HOST, env[:url].host)
span.set_tag(Datadog::Ext::NET::TARGET_PORT, env[:url].port)
end

def handle_response(span, env)
if options.fetch(:error_handler).call(env)
span.set_error(["Error #{env[:status]}", env[:body]])
end

span.set_tag(Ext::HTTP::STATUS_CODE, env[:status])
span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, env[:status])
end

def propagate!(span, env)
Expand Down
93 changes: 39 additions & 54 deletions lib/ddtrace/contrib/faraday/patcher.rb
Original file line number Diff line number Diff line change
@@ -1,71 +1,56 @@
require 'ddtrace/contrib/patcher'
require 'ddtrace/ext/app_types'
require 'ddtrace/contrib/faraday/ext'

module Datadog
module Contrib
module Faraday
COMPATIBLE_UNTIL = Gem::Version.new('1.0.0')
SERVICE = 'faraday'.freeze
NAME = 'faraday.request'.freeze

# Responsible for hooking the instrumentation into faraday
# Patcher enables patching of 'faraday' module.
module Patcher
include Base
include Contrib::Patcher

register_as :faraday, auto_patch: true
module_function

DEFAULT_ERROR_HANDLER = lambda do |env|
Ext::HTTP::ERROR_RANGE.cover?(env[:status])
def patched?
done?(:faraday)
end

option :service_name, default: SERVICE
option :distributed_tracing, default: false
option :error_handler, default: DEFAULT_ERROR_HANDLER
option :tracer, default: Datadog.tracer

@patched = false

class << self
def patch
return @patched if patched? || !compatible?

require 'ddtrace/ext/app_types'
require 'ddtrace/contrib/faraday/middleware'

add_pin
add_middleware

@patched = true
rescue => e
Tracer.log.error("Unable to apply Faraday integration: #{e}")
@patched
end

def patched?
@patched
end
def patch
do_once(:faraday) do
begin
require 'ddtrace/contrib/faraday/middleware'

def register_service(name)
get_option(:tracer).set_service_info(name, 'faraday', Ext::AppTypes::WEB)
add_pin
add_middleware
rescue StandardError => e
Datadog::Tracer.log.error("Unable to apply Faraday integration: #{e}")
end
end
end

private

def compatible?
return unless defined?(::Faraday::VERSION)
def add_pin
Pin.new(
get_option(:service_name),
app: Ext::APP,
app_type: Datadog::Ext::AppTypes::WEB,
tracer: get_option(:tracer)
).onto(::Faraday)
end

Gem::Version.new(::Faraday::VERSION) < COMPATIBLE_UNTIL
end
def add_middleware
::Faraday::Middleware.register_middleware(ddtrace: Middleware)
end

def add_pin
Pin.new(
get_option(:service_name),
app: 'faraday',
app_type: Ext::AppTypes::WEB,
tracer: get_option(:tracer)
).onto(::Faraday)
end
def register_service(name)
get_option(:tracer).set_service_info(
name,
Ext::APP,
Datadog::Ext::AppTypes::WEB
)
end

def add_middleware
::Faraday::Middleware.register_middleware(ddtrace: Middleware)
end
def get_option(option)
Datadog.configuration[:faraday].get_option(option)
end
end
end
Expand Down
12 changes: 6 additions & 6 deletions spec/ddtrace/contrib/faraday/middleware_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
let(:configuration_options) { { tracer: tracer } }

let(:request_span) do
tracer.writer.spans(:keep).find { |span| span.name == Datadog::Contrib::Faraday::NAME }
tracer.writer.spans(:keep).find { |span| span.name == Datadog::Contrib::Faraday::Ext::SPAN_REQUEST }
end

before(:each) do
Expand Down Expand Up @@ -51,8 +51,8 @@

it do
expect(request_span).to_not be nil
expect(request_span.service).to eq(Datadog::Contrib::Faraday::SERVICE)
expect(request_span.name).to eq(Datadog::Contrib::Faraday::NAME)
expect(request_span.service).to eq(Datadog::Contrib::Faraday::Ext::SERVICE_NAME)
expect(request_span.name).to eq(Datadog::Contrib::Faraday::Ext::SPAN_REQUEST)
expect(request_span.resource).to eq('GET')
expect(request_span.get_tag(Datadog::Ext::HTTP::METHOD)).to eq('GET')
expect(request_span.get_tag(Datadog::Ext::HTTP::STATUS_CODE)).to eq('200')
Expand All @@ -68,8 +68,8 @@
subject!(:response) { client.post('/failure') }

it do
expect(request_span.service).to eq(Datadog::Contrib::Faraday::SERVICE)
expect(request_span.name).to eq(Datadog::Contrib::Faraday::NAME)
expect(request_span.service).to eq(Datadog::Contrib::Faraday::Ext::SERVICE_NAME)
expect(request_span.name).to eq(Datadog::Contrib::Faraday::Ext::SPAN_REQUEST)
expect(request_span.resource).to eq('POST')
expect(request_span.get_tag(Datadog::Ext::HTTP::METHOD)).to eq('POST')
expect(request_span.get_tag(Datadog::Ext::HTTP::URL)).to eq('/failure')
Expand Down Expand Up @@ -103,7 +103,7 @@
let(:middleware_options) { { split_by_domain: true } }

it do
expect(request_span.name).to eq(Datadog::Contrib::Faraday::NAME)
expect(request_span.name).to eq(Datadog::Contrib::Faraday::Ext::SPAN_REQUEST)
expect(request_span.service).to eq('example.com')
expect(request_span.resource).to eq('GET')
end
Expand Down

0 comments on commit f9fed67

Please sign in to comment.