ddtrace 0.26.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +153 -77
- data/.circleci/images/primary/{Dockerfile-1.9.3 → Dockerfile-2.5.6} +8 -8
- data/.circleci/images/primary/Dockerfile-2.6.4 +73 -0
- data/.github/CODEOWNERS +1 -0
- data/Appraisals +201 -94
- data/CHANGELOG.md +25 -8
- data/Rakefile +153 -47
- data/ddtrace.gemspec +1 -1
- data/docker-compose.yml +56 -26
- data/docs/GettingStarted.md +117 -14
- data/lib/ddtrace.rb +4 -0
- data/lib/ddtrace/analytics.rb +9 -39
- data/lib/ddtrace/configuration.rb +0 -19
- data/lib/ddtrace/contrib/action_pack/action_controller/instrumentation.rb +144 -0
- data/lib/ddtrace/contrib/action_pack/action_controller/patcher.rb +37 -0
- data/lib/ddtrace/contrib/action_pack/configuration/settings.rb +25 -0
- data/lib/ddtrace/contrib/action_pack/ext.rb +16 -0
- data/lib/ddtrace/contrib/action_pack/integration.rb +36 -0
- data/lib/ddtrace/contrib/action_pack/patcher.rb +29 -0
- data/lib/ddtrace/contrib/action_pack/utils.rb +36 -0
- data/lib/ddtrace/contrib/action_view/configuration/settings.rb +24 -0
- data/lib/ddtrace/contrib/action_view/ext.rb +17 -0
- data/lib/ddtrace/contrib/action_view/instrumentation.rb +192 -0
- data/lib/ddtrace/contrib/action_view/integration.rb +43 -0
- data/lib/ddtrace/contrib/action_view/patcher.rb +47 -0
- data/lib/ddtrace/contrib/action_view/utils.rb +32 -0
- data/lib/ddtrace/contrib/active_support/cache/instrumentation.rb +157 -0
- data/lib/ddtrace/contrib/active_support/cache/patcher.rb +62 -0
- data/lib/ddtrace/contrib/active_support/cache/redis.rb +47 -0
- data/lib/ddtrace/contrib/active_support/configuration/settings.rb +23 -0
- data/lib/ddtrace/contrib/active_support/ext.rb +21 -0
- data/lib/ddtrace/contrib/active_support/integration.rb +38 -0
- data/lib/ddtrace/contrib/active_support/patcher.rb +29 -0
- data/lib/ddtrace/contrib/ethon/configuration/settings.rb +24 -0
- data/lib/ddtrace/contrib/ethon/easy_patch.rb +139 -0
- data/lib/ddtrace/contrib/ethon/ext.rb +15 -0
- data/lib/ddtrace/contrib/ethon/integration.rb +35 -0
- data/lib/ddtrace/contrib/ethon/multi_patch.rb +80 -0
- data/lib/ddtrace/contrib/ethon/patcher.rb +27 -0
- data/lib/ddtrace/contrib/patchable.rb +1 -1
- data/lib/ddtrace/contrib/rails/configuration/settings.rb +43 -6
- data/lib/ddtrace/contrib/rails/ext.rb +0 -15
- data/lib/ddtrace/contrib/rails/framework.rb +37 -6
- data/lib/ddtrace/contrib/rails/middlewares.rb +2 -1
- data/lib/ddtrace/contrib/rails/patcher.rb +0 -8
- data/lib/ddtrace/contrib/rails/utils.rb +0 -46
- data/lib/ddtrace/contrib/redis/patcher.rb +12 -19
- data/lib/ddtrace/correlation.rb +8 -12
- data/lib/ddtrace/forced_tracing.rb +10 -38
- data/lib/ddtrace/sampler.rb +20 -74
- data/lib/ddtrace/span.rb +3 -4
- data/lib/ddtrace/tracer.rb +4 -11
- data/lib/ddtrace/version.rb +2 -2
- metadata +32 -9
- data/lib/ddtrace/contrib/rails/action_controller.rb +0 -100
- data/lib/ddtrace/contrib/rails/action_controller_patch.rb +0 -78
- data/lib/ddtrace/contrib/rails/action_view.rb +0 -19
- data/lib/ddtrace/contrib/rails/active_support.rb +0 -67
- data/lib/ddtrace/contrib/rails/core_extensions.rb +0 -353
@@ -1,100 +0,0 @@
|
|
1
|
-
require 'ddtrace/ext/http'
|
2
|
-
require 'ddtrace/ext/errors'
|
3
|
-
require 'ddtrace/contrib/rack/ext'
|
4
|
-
require 'ddtrace/contrib/rails/ext'
|
5
|
-
|
6
|
-
module Datadog
|
7
|
-
module Contrib
|
8
|
-
module Rails
|
9
|
-
# Code used to create and handle 'rails.action_controller' spans.
|
10
|
-
module ActionController
|
11
|
-
include Datadog::Patcher
|
12
|
-
|
13
|
-
def self.instrument
|
14
|
-
# patch Rails core components
|
15
|
-
do_once(:instrument) do
|
16
|
-
Datadog::RailsActionPatcher.patch_action_controller
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.start_processing(payload)
|
21
|
-
# trace the execution
|
22
|
-
tracer = Datadog.configuration[:rails][:tracer]
|
23
|
-
service = Datadog.configuration[:rails][:controller_service]
|
24
|
-
type = Datadog::Ext::HTTP::TYPE_INBOUND
|
25
|
-
span = tracer.trace(Ext::SPAN_ACTION_CONTROLLER, service: service, span_type: type)
|
26
|
-
|
27
|
-
# attach the current span to the tracing context
|
28
|
-
tracing_context = payload.fetch(:tracing_context)
|
29
|
-
tracing_context[:dd_request_span] = span
|
30
|
-
rescue StandardError => e
|
31
|
-
Datadog::Tracer.log.error(e.message)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.finish_processing(payload)
|
35
|
-
# retrieve the tracing context and the latest active span
|
36
|
-
tracing_context = payload.fetch(:tracing_context)
|
37
|
-
env = payload.fetch(:env)
|
38
|
-
span = tracing_context[:dd_request_span]
|
39
|
-
return unless span && !span.finished?
|
40
|
-
|
41
|
-
begin
|
42
|
-
# Set the resource name, if it's still the default name
|
43
|
-
if span.resource == span.name
|
44
|
-
span.resource = "#{payload.fetch(:controller)}##{payload.fetch(:action)}"
|
45
|
-
end
|
46
|
-
|
47
|
-
# Set the resource name of the Rack request span unless this is an exception controller.
|
48
|
-
unless exception_controller?(payload)
|
49
|
-
rack_request_span = env[Datadog::Contrib::Rack::TraceMiddleware::RACK_REQUEST_SPAN]
|
50
|
-
rack_request_span.resource = span.resource if rack_request_span
|
51
|
-
end
|
52
|
-
|
53
|
-
# Set analytics sample rate
|
54
|
-
Utils.set_analytics_sample_rate(span)
|
55
|
-
|
56
|
-
# Associate with runtime metrics
|
57
|
-
Datadog.runtime_metrics.associate_with_span(span)
|
58
|
-
|
59
|
-
span.set_tag(Ext::TAG_ROUTE_ACTION, payload.fetch(:action))
|
60
|
-
span.set_tag(Ext::TAG_ROUTE_CONTROLLER, payload.fetch(:controller))
|
61
|
-
|
62
|
-
exception = payload[:exception_object]
|
63
|
-
if exception.nil?
|
64
|
-
# [christian] in some cases :status is not defined,
|
65
|
-
# rather than firing an error, simply acknowledge we don't know it.
|
66
|
-
status = payload.fetch(:status, '?').to_s
|
67
|
-
span.status = 1 if status.starts_with?('5')
|
68
|
-
elsif Utils.exception_is_error?(exception)
|
69
|
-
span.set_error(exception)
|
70
|
-
end
|
71
|
-
ensure
|
72
|
-
span.finish()
|
73
|
-
end
|
74
|
-
rescue StandardError => e
|
75
|
-
Datadog::Tracer.log.error(e.message)
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.exception_controller?(payload)
|
79
|
-
exception_controller_class = Datadog.configuration[:rails][:exception_controller]
|
80
|
-
controller = payload.fetch(:controller)
|
81
|
-
headers = payload.fetch(:headers)
|
82
|
-
|
83
|
-
# If no exception controller class has been set,
|
84
|
-
# guess whether this is an exception controller from the headers.
|
85
|
-
if exception_controller_class.nil?
|
86
|
-
!headers[:request_exception].nil?
|
87
|
-
# If an exception controller class has been specified,
|
88
|
-
# check if the controller is a kind of the exception controller class.
|
89
|
-
elsif exception_controller_class.is_a?(Class) || exception_controller_class.is_a?(Module)
|
90
|
-
controller <= exception_controller_class
|
91
|
-
# Otherwise if the exception controller class is some other value (like false)
|
92
|
-
# assume that this controller doesn't handle exceptions.
|
93
|
-
else
|
94
|
-
false
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module Datadog
|
2
|
-
module Contrib
|
3
|
-
module Rails
|
4
|
-
# Instrument ActiveController processing
|
5
|
-
module ActionControllerPatch
|
6
|
-
def self.included(base)
|
7
|
-
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
|
8
|
-
base.send(:prepend, ProcessActionPatch)
|
9
|
-
else
|
10
|
-
base.class_eval do
|
11
|
-
alias_method :process_action_without_datadog, :process_action
|
12
|
-
|
13
|
-
include ProcessActionPatch
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Compatibility module for Ruby versions not supporting #prepend
|
19
|
-
module ProcessActionCompatibilityPatch
|
20
|
-
def process_action(*args)
|
21
|
-
process_action_without_datadog(*args)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# ActionController patch
|
26
|
-
module ProcessActionPatch
|
27
|
-
# compatibility module for Ruby versions not supporting #prepend
|
28
|
-
include ProcessActionCompatibilityPatch unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.0.0')
|
29
|
-
|
30
|
-
def process_action(*args)
|
31
|
-
# mutable payload with a tracing context that is used in two different
|
32
|
-
# signals; it propagates the request span so that it can be finished
|
33
|
-
# no matter what
|
34
|
-
payload = {
|
35
|
-
controller: self.class,
|
36
|
-
action: action_name,
|
37
|
-
env: request.env,
|
38
|
-
headers: {
|
39
|
-
# The exception this controller was given in the request,
|
40
|
-
# which is typical if the controller is configured to handle exceptions.
|
41
|
-
request_exception: request.headers['action_dispatch.exception']
|
42
|
-
},
|
43
|
-
tracing_context: {}
|
44
|
-
}
|
45
|
-
|
46
|
-
begin
|
47
|
-
# process and catch request exceptions
|
48
|
-
Datadog::Contrib::Rails::ActionController.start_processing(payload)
|
49
|
-
result = super(*args)
|
50
|
-
status = datadog_response_status
|
51
|
-
payload[:status] = status unless status.nil?
|
52
|
-
result
|
53
|
-
# rubocop:disable Lint/RescueException
|
54
|
-
rescue Exception => e
|
55
|
-
payload[:exception] = [e.class.name, e.message]
|
56
|
-
payload[:exception_object] = e
|
57
|
-
raise e
|
58
|
-
end
|
59
|
-
# rubocop:enable Lint/RescueException
|
60
|
-
ensure
|
61
|
-
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
|
62
|
-
end
|
63
|
-
|
64
|
-
def datadog_response_status
|
65
|
-
case response
|
66
|
-
when ActionDispatch::Response
|
67
|
-
response.status
|
68
|
-
when Array
|
69
|
-
# Likely a Rack response array: first element is the status.
|
70
|
-
status = response.first
|
71
|
-
status.class <= Integer ? status : nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'ddtrace/contrib/rails/utils'
|
2
|
-
|
3
|
-
module Datadog
|
4
|
-
module Contrib
|
5
|
-
module Rails
|
6
|
-
# Code used to create and handle 'rails.render_template' and 'rails.render_partial' spans.
|
7
|
-
module ActionView
|
8
|
-
include Datadog::Patcher
|
9
|
-
|
10
|
-
def self.instrument
|
11
|
-
# patch Rails core components
|
12
|
-
do_once(:instrument) do
|
13
|
-
Datadog::RailsRendererPatcher.patch_renderer
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
require 'ddtrace/contrib/rails/ext'
|
3
|
-
|
4
|
-
module Datadog
|
5
|
-
module Contrib
|
6
|
-
module Rails
|
7
|
-
# Code used to create and handle 'rails.cache' spans.
|
8
|
-
module ActiveSupport
|
9
|
-
include Datadog::Patcher
|
10
|
-
|
11
|
-
def self.instrument
|
12
|
-
do_once(:instrument) do
|
13
|
-
# patch Rails core components
|
14
|
-
Datadog::RailsCachePatcher.patch_cache_store
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.start_trace_cache(payload)
|
19
|
-
tracer = Datadog.configuration[:rails][:tracer]
|
20
|
-
|
21
|
-
# In most of the cases Rails ``fetch()`` and ``read()`` calls are nested.
|
22
|
-
# This check ensures that two reads are not nested since they don't provide
|
23
|
-
# interesting details.
|
24
|
-
# NOTE: the ``finish_trace_cache()`` is fired but it already has a safe-guard
|
25
|
-
# to avoid any kind of issue.
|
26
|
-
current_span = tracer.active_span
|
27
|
-
return if payload[:action] == Ext::RESOURCE_CACHE_GET &&
|
28
|
-
current_span.try(:name) == Ext::SPAN_CACHE &&
|
29
|
-
current_span.try(:resource) == Ext::RESOURCE_CACHE_GET
|
30
|
-
|
31
|
-
tracing_context = payload.fetch(:tracing_context)
|
32
|
-
|
33
|
-
# create a new ``Span`` and add it to the tracing context
|
34
|
-
service = Datadog.configuration[:rails][:cache_service]
|
35
|
-
type = Ext::SPAN_TYPE_CACHE
|
36
|
-
span = tracer.trace(Ext::SPAN_CACHE, service: service, span_type: type)
|
37
|
-
span.resource = payload.fetch(:action)
|
38
|
-
tracing_context[:dd_cache_span] = span
|
39
|
-
rescue StandardError => e
|
40
|
-
Datadog::Tracer.log.debug(e.message)
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.finish_trace_cache(payload)
|
44
|
-
# retrieve the tracing context and continue the trace
|
45
|
-
tracing_context = payload.fetch(:tracing_context)
|
46
|
-
span = tracing_context[:dd_cache_span]
|
47
|
-
return unless span && !span.finished?
|
48
|
-
|
49
|
-
begin
|
50
|
-
# discard parameters from the cache_store configuration
|
51
|
-
store, = *Array.wrap(::Rails.configuration.cache_store).flatten
|
52
|
-
span.set_tag(Ext::TAG_CACHE_BACKEND, store)
|
53
|
-
normalized_key = ::ActiveSupport::Cache.expand_cache_key(payload.fetch(:key))
|
54
|
-
cache_key = Datadog::Utils.truncate(normalized_key, Ext::QUANTIZE_CACHE_MAX_KEY_SIZE)
|
55
|
-
span.set_tag(Ext::TAG_CACHE_KEY, cache_key)
|
56
|
-
|
57
|
-
span.set_error(payload[:exception]) if payload[:exception]
|
58
|
-
ensure
|
59
|
-
span.finish
|
60
|
-
end
|
61
|
-
rescue StandardError => e
|
62
|
-
Datadog::Tracer.log.debug(e.message)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,353 +0,0 @@
|
|
1
|
-
require 'ddtrace/contrib/rails/ext'
|
2
|
-
|
3
|
-
module Datadog
|
4
|
-
# RailsRendererPatcher contains function to patch Rails rendering libraries.
|
5
|
-
# rubocop:disable Lint/RescueException
|
6
|
-
# rubocop:disable Metrics/MethodLength
|
7
|
-
# rubocop:disable Metrics/ModuleLength
|
8
|
-
module RailsRendererPatcher
|
9
|
-
include Datadog::Patcher
|
10
|
-
|
11
|
-
module_function
|
12
|
-
|
13
|
-
def patch_renderer
|
14
|
-
do_once(:patch_renderer) do
|
15
|
-
if defined?(::ActionView::TemplateRenderer) && defined?(::ActionView::PartialRenderer)
|
16
|
-
patch_template_renderer(::ActionView::TemplateRenderer)
|
17
|
-
patch_partial_renderer(::ActionView::PartialRenderer)
|
18
|
-
elsif defined?(::ActionView::Rendering) && defined?(::ActionView::Partials::PartialRenderer)
|
19
|
-
# NOTE: Rails < 3.1 compatibility: different classes are used
|
20
|
-
patch_template_renderer(::ActionView::Rendering)
|
21
|
-
patch_partial_renderer(::ActionView::Partials::PartialRenderer)
|
22
|
-
else
|
23
|
-
Datadog::Tracer.log.debug('Expected Template/Partial classes not found; template rendering disabled')
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def patch_template_renderer(klass)
|
29
|
-
# rubocop:disable Metrics/BlockLength
|
30
|
-
do_once(:patch_template_renderer) do
|
31
|
-
klass.class_eval do
|
32
|
-
def render_with_datadog(*args, &block)
|
33
|
-
# NOTE: This check exists purely for Rails 3.0 compatibility.
|
34
|
-
# The 'if' part can be removed when support for Rails 3.0 is removed.
|
35
|
-
if active_datadog_span
|
36
|
-
render_without_datadog(*args, &block)
|
37
|
-
else
|
38
|
-
datadog_tracer.trace(
|
39
|
-
Datadog::Contrib::Rails::Ext::SPAN_RENDER_TEMPLATE,
|
40
|
-
span_type: Datadog::Ext::HTTP::TEMPLATE
|
41
|
-
) do |span|
|
42
|
-
with_datadog_span(span) { render_without_datadog(*args, &block) }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def render_template_with_datadog(*args)
|
48
|
-
begin
|
49
|
-
# arguments based on render_template signature (stable since Rails 3.2)
|
50
|
-
template = args[0]
|
51
|
-
layout_name = args[1]
|
52
|
-
|
53
|
-
# update the tracing context with computed values before the rendering
|
54
|
-
template_name = template.try('identifier')
|
55
|
-
template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(template_name)
|
56
|
-
layout = if layout_name.is_a?(String)
|
57
|
-
# NOTE: Rails < 3.1 compatibility: the second argument is the layout name
|
58
|
-
layout_name
|
59
|
-
else
|
60
|
-
layout_name.try(:[], 'virtual_path')
|
61
|
-
end
|
62
|
-
if template_name
|
63
|
-
active_datadog_span.set_tag(
|
64
|
-
Datadog::Contrib::Rails::Ext::TAG_TEMPLATE_NAME,
|
65
|
-
template_name
|
66
|
-
)
|
67
|
-
end
|
68
|
-
|
69
|
-
if layout
|
70
|
-
active_datadog_span.set_tag(
|
71
|
-
Datadog::Contrib::Rails::Ext::TAG_LAYOUT,
|
72
|
-
layout
|
73
|
-
)
|
74
|
-
end
|
75
|
-
rescue StandardError => e
|
76
|
-
Datadog::Tracer.log.debug(e.message)
|
77
|
-
end
|
78
|
-
|
79
|
-
# execute the original function anyway
|
80
|
-
render_template_without_datadog(*args)
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
attr_accessor :active_datadog_span
|
86
|
-
|
87
|
-
def datadog_tracer
|
88
|
-
Datadog.configuration[:rails][:tracer]
|
89
|
-
end
|
90
|
-
|
91
|
-
def with_datadog_span(span)
|
92
|
-
self.active_datadog_span = span
|
93
|
-
yield
|
94
|
-
ensure
|
95
|
-
self.active_datadog_span = nil
|
96
|
-
end
|
97
|
-
|
98
|
-
# method aliasing to patch the class
|
99
|
-
alias_method :render_without_datadog, :render
|
100
|
-
alias_method :render, :render_with_datadog
|
101
|
-
|
102
|
-
if klass.private_method_defined?(:render_template) || klass.method_defined?(:render_template)
|
103
|
-
alias_method :render_template_without_datadog, :render_template
|
104
|
-
alias_method :render_template, :render_template_with_datadog
|
105
|
-
else
|
106
|
-
# NOTE: Rails < 3.1 compatibility: the method name is different
|
107
|
-
alias_method :render_template_without_datadog, :_render_template
|
108
|
-
alias_method :_render_template, :render_template_with_datadog
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def patch_partial_renderer(klass)
|
115
|
-
do_once(:patch_partial_renderer) do
|
116
|
-
klass.class_eval do
|
117
|
-
def render_with_datadog(*args, &block)
|
118
|
-
datadog_tracer.trace(
|
119
|
-
Datadog::Contrib::Rails::Ext::SPAN_RENDER_PARTIAL,
|
120
|
-
span_type: Datadog::Ext::HTTP::TEMPLATE
|
121
|
-
) do |span|
|
122
|
-
with_datadog_span(span) { render_without_datadog(*args) }
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def render_partial_with_datadog(*args)
|
127
|
-
begin
|
128
|
-
template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(@template.try('identifier'))
|
129
|
-
if template_name
|
130
|
-
active_datadog_span.set_tag(
|
131
|
-
Datadog::Contrib::Rails::Ext::TAG_TEMPLATE_NAME,
|
132
|
-
template_name
|
133
|
-
)
|
134
|
-
end
|
135
|
-
rescue StandardError => e
|
136
|
-
Datadog::Tracer.log.debug(e.message)
|
137
|
-
end
|
138
|
-
|
139
|
-
# execute the original function anyway
|
140
|
-
render_partial_without_datadog(*args)
|
141
|
-
end
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
attr_accessor :active_datadog_span
|
146
|
-
|
147
|
-
def datadog_tracer
|
148
|
-
Datadog.configuration[:rails][:tracer]
|
149
|
-
end
|
150
|
-
|
151
|
-
def with_datadog_span(span)
|
152
|
-
self.active_datadog_span = span
|
153
|
-
yield
|
154
|
-
ensure
|
155
|
-
self.active_datadog_span = nil
|
156
|
-
end
|
157
|
-
|
158
|
-
# method aliasing to patch the class
|
159
|
-
alias_method :render_without_datadog, :render
|
160
|
-
alias_method :render, :render_with_datadog
|
161
|
-
alias_method :render_partial_without_datadog, :render_partial
|
162
|
-
alias_method :render_partial, :render_partial_with_datadog
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# RailsActionPatcher contains functions to patch Rails action controller instrumentation
|
169
|
-
module RailsActionPatcher
|
170
|
-
include Datadog::Patcher
|
171
|
-
|
172
|
-
module_function
|
173
|
-
|
174
|
-
def patch_action_controller
|
175
|
-
do_once(:patch_action_controller) do
|
176
|
-
patch_process_action
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def patch_process_action
|
181
|
-
do_once(:patch_process_action) do
|
182
|
-
require 'ddtrace/contrib/rails/action_controller_patch'
|
183
|
-
|
184
|
-
::ActionController::Metal.send(:include, Datadog::Contrib::Rails::ActionControllerPatch)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
# RailsCachePatcher contains function to patch Rails caching libraries.
|
190
|
-
module RailsCachePatcher
|
191
|
-
include Datadog::Patcher
|
192
|
-
|
193
|
-
module_function
|
194
|
-
|
195
|
-
def patch_cache_store
|
196
|
-
do_once(:patch_cache_store) do
|
197
|
-
patch_cache_store_read
|
198
|
-
patch_cache_store_fetch
|
199
|
-
patch_cache_store_write
|
200
|
-
patch_cache_store_delete
|
201
|
-
reload_cache_store
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def cache_store_class(k)
|
206
|
-
# When Redis is used, we can't only patch Cache::Store as it is
|
207
|
-
# Cache::RedisStore, a sub-class of it that is used, in practice.
|
208
|
-
# We need to do a per-method monkey patching as some of them might
|
209
|
-
# be redefined, and some of them not. The latest version of redis-activesupport
|
210
|
-
# redefines write but leaves untouched read and delete:
|
211
|
-
# https://github.com/redis-store/redis-activesupport/blob/master/lib/active_support/cache/redis_store.rb
|
212
|
-
c = if defined?(::ActiveSupport::Cache::RedisStore) &&
|
213
|
-
::ActiveSupport::Cache::RedisStore.instance_methods(false).include?(k)
|
214
|
-
::ActiveSupport::Cache::RedisStore
|
215
|
-
else
|
216
|
-
::ActiveSupport::Cache::Store
|
217
|
-
end
|
218
|
-
c
|
219
|
-
end
|
220
|
-
|
221
|
-
def patch_cache_store_read
|
222
|
-
do_once(:patch_cache_store_read) do
|
223
|
-
cache_store_class(:read).class_eval do
|
224
|
-
alias_method :read_without_datadog, :read
|
225
|
-
|
226
|
-
def read(*args, &block)
|
227
|
-
payload = {
|
228
|
-
action: Datadog::Contrib::Rails::Ext::RESOURCE_CACHE_GET,
|
229
|
-
key: args[0],
|
230
|
-
tracing_context: {}
|
231
|
-
}
|
232
|
-
|
233
|
-
begin
|
234
|
-
# process and catch cache exceptions
|
235
|
-
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
236
|
-
read_without_datadog(*args, &block)
|
237
|
-
rescue Exception => e
|
238
|
-
payload[:exception] = [e.class.name, e.message]
|
239
|
-
payload[:exception_object] = e
|
240
|
-
raise e
|
241
|
-
end
|
242
|
-
ensure
|
243
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def patch_cache_store_fetch
|
250
|
-
do_once(:patch_cache_store_fetch) do
|
251
|
-
cache_store_class(:fetch).class_eval do
|
252
|
-
alias_method :fetch_without_datadog, :fetch
|
253
|
-
|
254
|
-
def fetch(*args, &block)
|
255
|
-
payload = {
|
256
|
-
action: Datadog::Contrib::Rails::Ext::RESOURCE_CACHE_GET,
|
257
|
-
key: args[0],
|
258
|
-
tracing_context: {}
|
259
|
-
}
|
260
|
-
|
261
|
-
begin
|
262
|
-
# process and catch cache exceptions
|
263
|
-
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
264
|
-
fetch_without_datadog(*args, &block)
|
265
|
-
rescue Exception => e
|
266
|
-
payload[:exception] = [e.class.name, e.message]
|
267
|
-
payload[:exception_object] = e
|
268
|
-
raise e
|
269
|
-
end
|
270
|
-
ensure
|
271
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
def patch_cache_store_write
|
278
|
-
do_once(:patch_cache_store_write) do
|
279
|
-
cache_store_class(:write).class_eval do
|
280
|
-
alias_method :write_without_datadog, :write
|
281
|
-
|
282
|
-
def write(*args, &block)
|
283
|
-
payload = {
|
284
|
-
action: Datadog::Contrib::Rails::Ext::RESOURCE_CACHE_SET,
|
285
|
-
key: args[0],
|
286
|
-
tracing_context: {}
|
287
|
-
}
|
288
|
-
|
289
|
-
begin
|
290
|
-
# process and catch cache exceptions
|
291
|
-
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
292
|
-
write_without_datadog(*args, &block)
|
293
|
-
rescue Exception => e
|
294
|
-
payload[:exception] = [e.class.name, e.message]
|
295
|
-
payload[:exception_object] = e
|
296
|
-
raise e
|
297
|
-
end
|
298
|
-
ensure
|
299
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
def patch_cache_store_delete
|
306
|
-
do_once(:patch_cache_store_delete) do
|
307
|
-
cache_store_class(:delete).class_eval do
|
308
|
-
alias_method :delete_without_datadog, :delete
|
309
|
-
|
310
|
-
def delete(*args, &block)
|
311
|
-
payload = {
|
312
|
-
action: Datadog::Contrib::Rails::Ext::RESOURCE_CACHE_DELETE,
|
313
|
-
key: args[0],
|
314
|
-
tracing_context: {}
|
315
|
-
}
|
316
|
-
|
317
|
-
begin
|
318
|
-
# process and catch cache exceptions
|
319
|
-
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
320
|
-
delete_without_datadog(*args, &block)
|
321
|
-
rescue Exception => e
|
322
|
-
payload[:exception] = [e.class.name, e.message]
|
323
|
-
payload[:exception_object] = e
|
324
|
-
raise e
|
325
|
-
end
|
326
|
-
ensure
|
327
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
328
|
-
end
|
329
|
-
end
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
def self.reload_cache_store
|
334
|
-
redis = Datadog.registry[:redis]
|
335
|
-
return unless redis && redis.patcher.patched?
|
336
|
-
|
337
|
-
return unless defined?(::ActiveSupport::Cache::RedisStore) &&
|
338
|
-
defined?(::Rails.cache) &&
|
339
|
-
::Rails.cache.is_a?(::ActiveSupport::Cache::RedisStore)
|
340
|
-
|
341
|
-
Tracer.log.debug('Reloading redis cache store')
|
342
|
-
|
343
|
-
# backward compatibility: Rails 3.x doesn't have `cache=` method
|
344
|
-
cache_store = ::Rails.configuration.cache_store
|
345
|
-
cache_instance = ::ActiveSupport::Cache.lookup_store(cache_store)
|
346
|
-
if ::Rails::VERSION::MAJOR.to_i == 3
|
347
|
-
silence_warnings { Object.const_set 'RAILS_CACHE', cache_instance }
|
348
|
-
elsif ::Rails::VERSION::MAJOR.to_i > 3
|
349
|
-
::Rails.cache = cache_instance
|
350
|
-
end
|
351
|
-
end
|
352
|
-
end
|
353
|
-
end
|