Skip to content

Commit

Permalink
Merge pull request #235 from palazzem/rails-wrapper
Browse files Browse the repository at this point in the history
[rails] use direct instrumentation instead of Rails instrumentation
  • Loading branch information
Emanuele Palazzetti authored Nov 2, 2017
2 parents 4cebeb1 + ab51dd0 commit 5edd255
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 88 deletions.
14 changes: 2 additions & 12 deletions lib/ddtrace/contrib/rails/action_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,9 @@ module ActionController
def self.instrument
# patch Rails core components
Datadog::RailsActionPatcher.patch_action_controller

# subscribe when the request processing starts
::ActiveSupport::Notifications.subscribe('!datadog.start_processing.action_controller') do |*args|
start_processing(*args)
end

# subscribe when the request processing has been completed
::ActiveSupport::Notifications.subscribe('!datadog.finish_processing.action_controller') do |*args|
finish_processing(*args)
end
end

def self.start_processing(_name, _start, _finish, _id, payload)
def self.start_processing(payload)
# trace the execution
tracer = ::Rails.configuration.datadog_trace.fetch(:tracer)
service = ::Rails.configuration.datadog_trace.fetch(:default_controller_service)
Expand All @@ -35,7 +25,7 @@ def self.start_processing(_name, _start, _finish, _id, payload)
Datadog::Tracer.log.error(e.message)
end

def self.finish_processing(_name, start, finish, _id, payload)
def self.finish_processing(payload)
# retrieve the tracing context and the latest active span
tracing_context = payload.fetch(:tracing_context)
span = tracing_context[:dd_request_span]
Expand Down
30 changes: 5 additions & 25 deletions lib/ddtrace/contrib/rails/action_view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,10 @@ module Rails
module ActionView
def self.instrument
# patch Rails core components
Datadog::RailsRendererPatcher.patch_renderer()

# subscribe when the template rendering starts
::ActiveSupport::Notifications.subscribe('!datadog.start_render_template.action_view') do |*args|
start_render_template(*args)
end

# subscribe when the template rendering has been processed
::ActiveSupport::Notifications.subscribe('!datadog.finish_render_template.action_view') do |*args|
finish_render_template(*args)
end

# subscribe when the partial rendering starts
::ActiveSupport::Notifications.subscribe('!datadog.start_render_partial.action_view') do |*args|
start_render_partial(*args)
end

# subscribe when the partial rendering has been processed
::ActiveSupport::Notifications.subscribe('!datadog.finish_render_partial.action_view') do |*args|
finish_render_partial(*args)
end
Datadog::RailsRendererPatcher.patch_renderer
end

def self.start_render_template(_name, _start, _finish, _id, payload)
def self.start_render_template(payload)
# retrieve the tracing context
tracing_context = payload.fetch(:tracing_context)

Expand All @@ -42,7 +22,7 @@ def self.start_render_template(_name, _start, _finish, _id, payload)
Datadog::Tracer.log.debug(e.message)
end

def self.finish_render_template(_name, _start, _finish, _id, payload)
def self.finish_render_template(payload)
# retrieve the tracing context and the latest active span
tracing_context = payload.fetch(:tracing_context)
span = tracing_context[:dd_rails_template_span]
Expand All @@ -64,7 +44,7 @@ def self.finish_render_template(_name, _start, _finish, _id, payload)
Datadog::Tracer.log.debug(e.message)
end

def self.start_render_partial(_name, _start, _finish, _id, payload)
def self.start_render_partial(payload)
# retrieve the tracing context
tracing_context = payload.fetch(:tracing_context)

Expand All @@ -75,7 +55,7 @@ def self.start_render_partial(_name, _start, _finish, _id, payload)
Datadog::Tracer.log.debug(e.message)
end

def self.finish_render_partial(_name, start, finish, _id, payload)
def self.finish_render_partial(payload)
# retrieve the tracing context and the latest active span
tracing_context = payload.fetch(:tracing_context)
span = tracing_context[:dd_rails_partial_span]
Expand Down
16 changes: 3 additions & 13 deletions lib/ddtrace/contrib/rails/active_support.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,10 @@ module Rails
module ActiveSupport
def self.instrument
# patch Rails core components
Datadog::RailsCachePatcher.patch_cache_store()

# subscribe when a cache read starts being processed
::ActiveSupport::Notifications.subscribe('!datadog.start_cache_tracing.active_support') do |*args|
start_trace_cache(*args)
end

# subscribe when a cache read has been processed
::ActiveSupport::Notifications.subscribe('!datadog.finish_cache_tracing.active_support') do |*args|
finish_trace_cache(*args)
end
Datadog::RailsCachePatcher.patch_cache_store
end

def self.start_trace_cache(_name, _start, _finish, _id, payload)
def self.start_trace_cache(payload)
tracer = ::Rails.configuration.datadog_trace.fetch(:tracer)
tracing_context = payload.fetch(:tracing_context)

Expand All @@ -45,7 +35,7 @@ def self.start_trace_cache(_name, _start, _finish, _id, payload)
Datadog::Tracer.log.debug(e.message)
end

def self.finish_trace_cache(_name, _start, _finish, _id, payload)
def self.finish_trace_cache(payload)
# retrieve the tracing context and continue the trace
tracing_context = payload.fetch(:tracing_context)
span = tracing_context[:dd_cache_span]
Expand Down
90 changes: 52 additions & 38 deletions lib/ddtrace/contrib/rails/core_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Datadog
# RailsRendererPatcher contains function to patch Rails rendering libraries.
# rubocop:disable Lint/RescueException
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/BlockLength
# rubocop:disable Metrics/ModuleLength
module RailsRendererPatcher
module_function

Expand All @@ -27,22 +27,17 @@ def render_with_datadog(*args, &block)
# context when a partial is rendered
@tracing_context ||= {}
if @tracing_context.empty?
::ActiveSupport::Notifications.instrument(
'!datadog.start_render_template.action_view',
tracing_context: @tracing_context
)
Datadog::Contrib::Rails::ActionView.start_render_template(tracing_context: @tracing_context)
end

render_without_datadog(*args)
rescue Exception => e
# attach the exception to the tracing context if any
@tracing_context[:exception] = e
raise e
ensure
# ensure that the template `Span` is finished even during exceptions
::ActiveSupport::Notifications.instrument(
'!datadog.finish_render_template.action_view',
tracing_context: @tracing_context
)
Datadog::Contrib::Rails::ActionView.finish_render_template(tracing_context: @tracing_context)
end

def render_template_with_datadog(*args)
Expand Down Expand Up @@ -90,21 +85,15 @@ def patch_partial_renderer(klass)
def render_with_datadog(*args, &block)
# create a tracing context and start the rendering span
@tracing_context = {}
::ActiveSupport::Notifications.instrument(
'!datadog.start_render_partial.action_view',
tracing_context: @tracing_context
)
Datadog::Contrib::Rails::ActionView.start_render_partial(tracing_context: @tracing_context)
render_without_datadog(*args)
rescue Exception => e
# attach the exception to the tracing context if any
@tracing_context[:exception] = e
raise e
ensure
# ensure that the template `Span` is finished even during exceptions
::ActiveSupport::Notifications.instrument(
'!datadog.finish_render_partial.action_view',
tracing_context: @tracing_context
)
Datadog::Contrib::Rails::ActionView.finish_render_partial(tracing_context: @tracing_context)
end

def render_partial_with_datadog(*args)
Expand Down Expand Up @@ -143,24 +132,25 @@ def process_action_with_datadog(*args)
# mutable payload with a tracing context that is used in two different
# signals; it propagates the request span so that it can be finished
# no matter what
raw_payload = {
payload = {
controller: self.class.name,
action: action_name,
tracing_context: {}
}

# emits two different signals that start and finish the trace; this approach
# mimics the original behavior that is available since Rails 3.0:
# - https://github.com/rails/rails/blob/3-0-stable/actionpack/lib/action_controller/metal/instrumentation.rb#L17-L35
# - https://github.com/rails/rails/blob/5-1-stable/actionpack/lib/action_controller/metal/instrumentation.rb#L17-L39
ActiveSupport::Notifications.instrument('!datadog.start_processing.action_controller', raw_payload)

# process the request and finish the trace
ActiveSupport::Notifications.instrument('!datadog.finish_processing.action_controller', raw_payload) do |payload|
begin
# process and catch request exceptions
Datadog::Contrib::Rails::ActionController.start_processing(payload)
result = process_action_without_datadog(*args)
payload[:status] = response.status
result
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
end
ensure
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
end

alias_method :process_action_without_datadog, :process_action
Expand Down Expand Up @@ -206,11 +196,17 @@ def read(*args, &block)
tracing_context: {}
}

ActiveSupport::Notifications.instrument('!datadog.start_cache_tracing.active_support', raw_payload)

ActiveSupport::Notifications.instrument('!datadog.finish_cache_tracing.active_support', raw_payload) do
begin
# process and catch cache exceptions
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(raw_payload)
read_without_datadog(*args, &block)
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
end
ensure
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(raw_payload)
end
end
end
Expand All @@ -225,11 +221,17 @@ def fetch(*args, &block)
tracing_context: {}
}

ActiveSupport::Notifications.instrument('!datadog.start_cache_tracing.active_support', raw_payload)

ActiveSupport::Notifications.instrument('!datadog.finish_cache_tracing.active_support', raw_payload) do
begin
# process and catch cache exceptions
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(raw_payload)
fetch_without_datadog(*args, &block)
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
end
ensure
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(raw_payload)
end
end
end
Expand All @@ -244,11 +246,17 @@ def write(*args, &block)
tracing_context: {}
}

ActiveSupport::Notifications.instrument('!datadog.start_cache_tracing.active_support', raw_payload)

ActiveSupport::Notifications.instrument('!datadog.finish_cache_tracing.active_support', raw_payload) do
begin
# process and catch cache exceptions
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(raw_payload)
write_without_datadog(*args, &block)
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
end
ensure
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(raw_payload)
end
end
end
Expand All @@ -263,11 +271,17 @@ def delete(*args, &block)
tracing_context: {}
}

ActiveSupport::Notifications.instrument('!datadog.start_cache_tracing.active_support', raw_payload)

ActiveSupport::Notifications.instrument('!datadog.finish_cache_tracing.active_support', raw_payload) do
begin
# process and catch cache exceptions
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(raw_payload)
delete_without_datadog(*args, &block)
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
raise e
end
ensure
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(raw_payload)
end
end
end
Expand Down

0 comments on commit 5edd255

Please sign in to comment.