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

[rails] Redis instrumentation follows users settings #86

Merged
merged 3 commits into from
Mar 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions lib/ddtrace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,9 @@ def self.tracer
require 'ddtrace/contrib/rails/framework'

module Datadog
# Run the auto instrumentation directly after the initialization of the application and
# after the application initializers in config/initializers are run
# Run the auto instrumentation directly after initializers in
# `config/initializers` are executed
class Railtie < Rails::Railtie
config.before_configuration do
begin
# We include 'redis-rails' here if it's available, doing it later
# (typically in initialize callback) does not work, it does not
# get loaded in the right context.
require 'redis-rails'
Datadog::Tracer.log.debug("'redis-rails' module found, Datadog 'redis-rails' integration is available")
rescue LoadError
Datadog::Tracer.log.debug("'redis-rails' module not found, Datadog 'redis-rails' integration is disabled")
end

Datadog::Monkey.patch_module(:redis)
end

# we do actions
config.after_initialize do |app|
Datadog::Contrib::Rails::Framework.configure(config: app.config)
Datadog::Contrib::Rails::Framework.auto_instrument()
Expand Down
29 changes: 20 additions & 9 deletions lib/ddtrace/contrib/rails/framework.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,32 @@ def self.configure(config)
end

def self.auto_instrument_redis
# configure Redis PIN
return unless (defined? ::Rails.cache) && ::Rails.cache.respond_to?(:data)
pin = Datadog::Pin.get_from(::Rails.cache.data)
return unless pin
return unless ::Rails.configuration.datadog_trace[:auto_instrument_redis]
Datadog::Tracer.log.debug('Enabling auto-instrumentation for Redis client')

# enable Redis instrumentation if activated
pin.tracer = nil unless ::Rails.configuration.datadog_trace[:auto_instrument_redis]
return unless pin.tracer
Datadog::Tracer.log.debug("'redis' module found, Datadog 'redis' integration is available")
# patch the Redis library and reload the CacheStore if it was using Redis
Datadog::Monkey.patch_module(:redis)

# reload the cache store if it's available and it's using Redis
return unless defined?(::ActiveSupport::Cache::RedisStore) &&
defined?(::Rails.cache) &&
::Rails.cache.is_a?(::ActiveSupport::Cache::RedisStore)
Datadog::Tracer.log.debug('Enabling auto-instrumentation for redis-rails connector')

# backward compatibility: Rails 3.x doesn't have `cache=` method
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rails 3.x relies in a RAILS_CACHE global; Rails > 3 deprecated this global in favor of a plain Rails.cache

cache_store = ::Rails.configuration.cache_store
cache_instance = ::ActiveSupport::Cache.lookup_store(cache_store)
if ::Rails::VERSION::MAJOR.to_i == 3
silence_warnings { Object.const_set 'RAILS_CACHE', cache_instance }
elsif ::Rails::VERSION::MAJOR.to_i > 3
::Rails.cache = cache_instance
end
end

# automatically instrument all Rails component
def self.auto_instrument
return unless ::Rails.configuration.datadog_trace[:auto_instrument]
Datadog::Tracer.log.info('Detected Rails >= 3.x. Enabling auto-instrumentation for core components')
Datadog::Tracer.log.debug('Enabling auto-instrumentation for core components')

# instrumenting Rails framework
Datadog::Contrib::Rails::ActionController.instrument()
Expand Down
5 changes: 3 additions & 2 deletions test/contrib/rails/apps/application.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'rails/all'
require 'rails/test_help'
require 'contrib/rails/apps/cache'

require 'ddtrace'

Expand All @@ -9,7 +8,9 @@ class TestApplication < Rails::Application
# common settings between all Rails versions
def initialize(*args)
super(*args)
config.cache_store = get_cache
redis_cache = [:redis_store, { url: ENV['REDIS_URL'] }]
file_cache = [:file_store, '/tmp/ddtrace-rb/cache/']
config.cache_store = ENV['REDIS_URL'] ? redis_cache : file_cache
config.eager_load = false
config.secret_key_base = 'not_so_secret'
end
Expand Down
15 changes: 0 additions & 15 deletions test/contrib/rails/apps/cache.rb

This file was deleted.

5 changes: 3 additions & 2 deletions test/contrib/rails/apps/rails3.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
require 'rails/all'
require 'rails/test_help'
require 'contrib/rails/apps/cache'

require 'ddtrace'

class Rails3 < Rails::Application
config.cache_store = get_cache
redis_cache = [:redis_store, { url: ENV['REDIS_URL'] }]
file_cache = [:file_store, '/tmp/ddtrace-rb/cache/']
config.cache_store = ENV['REDIS_URL'] ? redis_cache : file_cache
config.secret_key_base = 'not_so_secret'
config.active_support.test_order = :random
config.active_support.deprecation = :stderr
Expand Down
7 changes: 5 additions & 2 deletions test/contrib/rails/redis_cache_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@

class RedisCacheTracingTest < ActionController::TestCase
setup do
# switch Rails with a dummy tracer
@original_tracer = Rails.configuration.datadog_trace[:tracer]
@tracer = get_test_tracer()
Rails.configuration.datadog_trace[:tracer] = @tracer
assert_equal(true, Rails.cache.respond_to?(:data), "cache '#{Rails.cache}' has no data")
pin = Datadog::Pin.get_from(Rails.cache.data)

# get the Redis pin accessing private methods (only Rails 3.x)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's reasonable to do that in a test

client = Rails.cache.instance_variable_get(:@data)
pin = Datadog::Pin.get_from(client)
refute_nil(pin, 'unable to get pin from Redis connection')
pin.tracer = @tracer
end
Expand Down