Skip to content

Commit

Permalink
Turn rails into regular contribution
Browse files Browse the repository at this point in the history
  • Loading branch information
p-lambert committed Oct 16, 2017
1 parent 4566d99 commit 082dd2d
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 83 deletions.
40 changes: 0 additions & 40 deletions lib/ddtrace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,3 @@ def configure(&blk)
end

require 'ddtrace/monkey'

# Datadog auto instrumentation for frameworks
if defined?(Rails::VERSION)
if !ENV['DISABLE_DATADOG_RAILS']
if Rails::VERSION::MAJOR.to_i >= 3
require 'ddtrace/contrib/rails/framework'
require 'ddtrace/contrib/rails/middlewares'

module Datadog
# Railtie class initializes
class Railtie < Rails::Railtie
config.app_middleware.use(Datadog::Contrib::Rails::ExceptionMiddleware)

config.after_initialize do |app|
Datadog::Contrib::Rails::Framework.configure(config: app.config)
Datadog::Contrib::Rails::Framework.auto_instrument()
Datadog::Contrib::Rails::Framework.auto_instrument_redis()
Datadog::Contrib::Rails::Framework.auto_instrument_grape()
end

# Configure datadog settings before building the middleware stack.
# This is required because the middleware stack is frozen after
# the initialization and so it's too late to add our tracing
# functionalities.
initializer :datadog_config, before: :build_middleware_stack do |app|
app.config.middleware.insert_before(
0, Datadog::Contrib::Rack::TraceMiddleware
)
end
end
end
else
Datadog::Tracer.log.warn 'Detected a Rails version < 3.x.'\
'This version is not supported yet and the'\
'auto-instrumentation for core components will be disabled.'
end
else
Datadog::Tracer.log.info 'Skipping Rails auto-instrumentation, DISABLE_DATADOG_RAILS is set.'
end
end
63 changes: 22 additions & 41 deletions lib/ddtrace/contrib/rails/framework.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,78 +30,59 @@ module Rails
# - handle configuration entries which are specific to Datadog tracing
# - instrument parts of the framework when needed
module Framework
include Base
register_as :rails

option :enabled, default: true
option :auto_instrument, default: false
option :auto_instrument_redis, default: false
option :auto_instrument_grape, default: false
option :default_service, default: 'rails-app'
option :default_controller_service, default: 'rails-controller'
option :default_cache_service, default: 'rails-cache'
option :default_grape_service, default: 'grape'
option :default_database_service
option :distributed_tracing_enabled, default: false
option :template_base_path, default: 'views/'
option :tracer, default: Datadog.tracer
option :debug, default: false
option :trace_agent_hostname, default: Datadog::Writer::HOSTNAME
option :trace_agent_port, default: Datadog::Writer::PORT
option :env, default: nil
option :tags, default: {}

# configure Datadog settings
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.configure(rails_config)
user_config = config[:config].datadog_trace rescue {}
Datadog.configuration.use(:rails, user_config)
tracer = Datadog.configuration[:rails][:tracer]

tracer.enabled = get_option(:enabled)
tracer.class.debug_logging = get_option(:debug)
tracer.enabled = Datadog.configuration[:rails][:enabled]
tracer.class.debug_logging = Datadog.configuration[:rails][:debug]

tracer.configure(
hostname: get_option(:trace_agent_hostname),
port: get_option(:trace_agent_port)
hostname: Datadog.configuration[:rails][:trace_agent_hostname],
port: Datadog.configuration[:rails][:trace_agent_port]
)

tracer.set_tags(get_option(:tags))
tracer.set_tags('env' => get_option(:env)) if get_option(:env)
tracer.set_tags(Datadog.configuration[:rails][:tags])
tracer.set_tags('env' => Datadog.configuration[:rails][:env]) if Datadog.configuration[:rails][:env]

tracer.set_service_info(
get_option(:default_service),
Datadog.configuration[:rails][:default_service],
'rack',
Datadog::Ext::AppTypes::WEB
)

tracer.set_service_info(
get_option(:default_controller_service),
Datadog.configuration[:rails][:default_controller_service],
'rails',
Datadog::Ext::AppTypes::WEB
)
tracer.set_service_info(
get_option(:default_cache_service),
Datadog.configuration[:rails][:default_cache_service],
'rails',
Datadog::Ext::AppTypes::CACHE
)

# By default, default service would be guessed from the script
# being executed, but here we know better, get it from Rails config.
tracer.default_service = get_option(:default_service)
tracer.default_service = Datadog.configuration[:rails][:default_service]

Datadog.configuration[:rack][:tracer] = tracer
Datadog.configuration[:rack][:default_service] = get_option(:default_service)
Datadog.configuration[:rack][:distributed_tracing_enabled] = get_option(:distributed_tracing_enabled)
Datadog.configuration[:rack][:default_service] = Datadog.configuration[:rails][:default_service]
Datadog.configuration[:rack][:distributed_tracing_enabled] = \
Datadog.configuration[:rails][:distributed_tracing_enabled]

if defined?(::ActiveRecord)
begin
# set default database service details and store it in the configuration
conn_cfg = ::ActiveRecord::Base.connection_config()
adapter_name = Datadog::Contrib::Rails::Utils.normalize_vendor(conn_cfg[:adapter])
set_option(:default_database_service, adapter_name) unless get_option(:default_database_service)
Datadog.configuration[:rails][:default_database_service] ||= adapter_name
tracer.set_service_info(
get_option(:default_database_service),
Datadog.configuration[:rails][:default_database_service],
adapter_name,
Datadog::Ext::AppTypes::DB
)
Expand All @@ -111,11 +92,11 @@ def self.configure(rails_config)
end

# update global configurations
::Rails.configuration.datadog_trace = to_h
::Rails.configuration.datadog_trace = Datadog.registry[:rails].to_h
end

def self.auto_instrument_redis
return unless get_option(:auto_instrument_redis)
return unless Datadog.configuration[:rails][:auto_instrument_redis]
Datadog::Tracer.log.debug('Enabling auto-instrumentation for Redis client')

# patch the Redis library and reload the CacheStore if it was using Redis
Expand All @@ -138,21 +119,21 @@ def self.auto_instrument_redis
end

def self.auto_instrument_grape
return unless get_option(:auto_instrument_grape)
return unless Datadog.configuration[:rails][:auto_instrument_grape]

# patch the Grape library so that endpoints are traced
Datadog::Monkey.patch_module(:grape)

# update the Grape pin object
pin = Datadog::Pin.get_from(::Grape)
return unless pin && pin.enabled?
pin.tracer = get_option(:tracer)
pin.service = get_option(:default_grape_service)
pin.tracer = Datadog.configuration[:rails][:tracer]
pin.service = Datadog.configuration[:rails][:default_grape_service]
end

# automatically instrument all Rails component
def self.auto_instrument
return unless get_option(:auto_instrument)
return unless Datadog.configuration[:rails][:auto_instrument]
Datadog::Tracer.log.debug('Enabling auto-instrumentation for core components')

# instrumenting Rails framework
Expand Down
55 changes: 55 additions & 0 deletions lib/ddtrace/contrib/rails/patcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module Datadog
module Contrib
module Rails
# Patcher
module Patcher
include Base
register_as :rails, auto_patch: true

option :enabled, default: true
option :auto_instrument, default: false
option :auto_instrument_redis, default: false
option :auto_instrument_grape, default: false
option :default_service, default: 'rails-app'
option :default_controller_service, default: 'rails-controller'
option :default_cache_service, default: 'rails-cache'
option :default_grape_service, default: 'grape'
option :default_database_service
option :distributed_tracing_enabled, default: false
option :template_base_path, default: 'views/'
option :tracer, default: Datadog.tracer
option :debug, default: false
option :trace_agent_hostname, default: Datadog::Writer::HOSTNAME
option :trace_agent_port, default: Datadog::Writer::PORT
option :env, default: nil
option :tags, default: {}
option :sidekiq_service

@patched = false

class << self
def patch
return @patched if patched? || !compatible?
require_relative 'framework'
@patched = true
rescue => e
Datadog::Tracer.log.error("Unable to apply Rails integration: #{e}")
@patched
end

def patched?
@patched
end

def compatible?
return if ENV['DISABLE_DATADOG_RAILS']

defined?(::Rails::VERSION) && ::Rails::VERSION::MAJOR.to_i >= 3
end
end
end
end
end
end

require 'ddtrace/contrib/rails/railtie' if Datadog.registry[:rails].compatible?
27 changes: 27 additions & 0 deletions lib/ddtrace/contrib/rails/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'ddtrace/contrib/rails/framework'
require 'ddtrace/contrib/rails/middlewares'
require 'ddtrace/contrib/rack/middlewares'

module Datadog
# Railtie class initializes
class Railtie < Rails::Railtie
config.app_middleware.use(Datadog::Contrib::Rails::ExceptionMiddleware)

config.after_initialize do |app|
Datadog::Contrib::Rails::Framework.configure(config: app.config)
Datadog::Contrib::Rails::Framework.auto_instrument
Datadog::Contrib::Rails::Framework.auto_instrument_redis
Datadog::Contrib::Rails::Framework.auto_instrument_grape
end

# Configure datadog settings before building the middleware stack.
# This is required because the middleware stack is frozen after
# the initialization and so it's too late to add our tracing
# functionalities.
initializer :datadog_config, before: :build_middleware_stack do |app|
app.config.middleware.insert_before(
0, Datadog::Contrib::Rack::TraceMiddleware
)
end
end
end
2 changes: 1 addition & 1 deletion lib/ddtrace/contrib/sidekiq/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Tracer
def initialize(options = {})
# check if Rails configuration is available and use it to override
# Sidekiq defaults
rails_config = ::Rails.configuration.datadog_trace rescue {}
rails_config = Datadog.registry[:rails].to_h
base_config = DEFAULT_CONFIG.merge(rails_config)
user_config = base_config.merge(options)
@tracer = user_config[:tracer]
Expand Down
1 change: 1 addition & 0 deletions lib/ddtrace/monkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# because patchers do not include any 3rd party module nor even our
# patching code, which is required on demand, when patching.
require 'ddtrace/contrib/base'
require 'ddtrace/contrib/rails/patcher'
require 'ddtrace/contrib/active_record/patcher'
require 'ddtrace/contrib/elasticsearch/patcher'
require 'ddtrace/contrib/faraday/patcher'
Expand Down
2 changes: 1 addition & 1 deletion test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def reset_config
end

config = { config: ::Rails.application.config }
Datadog.registry[:rails].configure(config)
Datadog::Contrib::Rails::Framework.configure(config)
end

def test_repeat
Expand Down

0 comments on commit 082dd2d

Please sign in to comment.