ddtrace 0.26.1 → 0.27.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|