ddtrace 0.11.4 → 0.12.0.beta1
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/Appraisals +5 -4
- data/README.md +48 -62
- data/Rakefile +11 -15
- data/docs/GettingStarted.md +55 -2
- data/gemfiles/contrib.gemfile +3 -2
- data/gemfiles/rails4_mysql2.gemfile +1 -1
- data/gemfiles/rails5_mysql2.gemfile +1 -1
- data/lib/ddtrace.rb +1 -0
- data/lib/ddtrace/contrib/active_record/patcher.rb +74 -22
- data/lib/ddtrace/contrib/graphql/patcher.rb +57 -0
- data/lib/ddtrace/contrib/rack/middlewares.rb +8 -18
- data/lib/ddtrace/contrib/rails/action_controller.rb +11 -9
- data/lib/ddtrace/contrib/rails/action_view.rb +1 -5
- data/lib/ddtrace/contrib/rails/active_record.rb +38 -17
- data/lib/ddtrace/contrib/rails/active_support.rb +2 -6
- data/lib/ddtrace/contrib/rails/core_extensions.rb +218 -245
- data/lib/ddtrace/contrib/rails/middlewares.rb +2 -7
- data/lib/ddtrace/contrib/rails/patcher.rb +5 -0
- data/lib/ddtrace/contrib/rails/railtie.rb +1 -4
- data/lib/ddtrace/contrib/rails/utils.rb +12 -57
- data/lib/ddtrace/patcher.rb +10 -32
- data/lib/ddtrace/transport.rb +20 -33
- data/lib/ddtrace/version.rb +4 -3
- data/lib/ddtrace/writer.rb +5 -11
- metadata +5 -5
- data/CHANGELOG.md +0 -260
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'ddtrace/ext/app_types'
|
2
|
+
require 'ddtrace/ext/http'
|
3
|
+
|
4
|
+
module Datadog
|
5
|
+
module Contrib
|
6
|
+
module GraphQL
|
7
|
+
# Provides instrumentation for `graphql` through the GraphQL tracing framework
|
8
|
+
module Patcher
|
9
|
+
include Base
|
10
|
+
register_as :graphql
|
11
|
+
|
12
|
+
option :tracer, default: Datadog.tracer
|
13
|
+
option :service_name, default: 'ruby-graphql', depends_on: [:tracer] do |value|
|
14
|
+
get_option(:tracer).set_service_info(value, 'ruby-graphql', Ext::AppTypes::WEB)
|
15
|
+
value
|
16
|
+
end
|
17
|
+
option :schemas
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def patch
|
21
|
+
return patched? if patched? || !compatible? || get_option(:schemas).nil?
|
22
|
+
|
23
|
+
get_option(:schemas).each { |s| patch_schema!(s) }
|
24
|
+
|
25
|
+
@patched = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def patch_schema!(schema)
|
29
|
+
tracer = get_option(:tracer)
|
30
|
+
service_name = get_option(:service_name)
|
31
|
+
|
32
|
+
schema.define do
|
33
|
+
use(
|
34
|
+
::GraphQL::Tracing::DataDogTracing,
|
35
|
+
tracer: tracer,
|
36
|
+
service: service_name
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def patched?
|
42
|
+
return @patched if defined?(@patched)
|
43
|
+
@patched = false
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def compatible?
|
49
|
+
defined?(::GraphQL) \
|
50
|
+
&& defined?(::GraphQL::Tracing::DataDogTracing) \
|
51
|
+
&& Gem.loaded_specs['graphql'].version >= Gem::Version.new('1.7.9')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -37,10 +37,6 @@ module Datadog
|
|
37
37
|
request_span = tracer.trace('rack.request', trace_options)
|
38
38
|
env[:datadog_rack_request_span] = request_span
|
39
39
|
|
40
|
-
# Copy the original env, before the rest of the stack executes.
|
41
|
-
# Values may change; we want values before that happens.
|
42
|
-
original_env = env.dup
|
43
|
-
|
44
40
|
# call the rest of the stack
|
45
41
|
status, headers, response = @app.call(env)
|
46
42
|
[status, headers, response]
|
@@ -64,7 +60,7 @@ module Datadog
|
|
64
60
|
# the result for this request; `resource` and `tags` are expected to
|
65
61
|
# be set in another level but if they're missing, reasonable defaults
|
66
62
|
# are used.
|
67
|
-
set_request_tags!(request_span, env, status, headers, response
|
63
|
+
set_request_tags!(request_span, env, status, headers, response)
|
68
64
|
|
69
65
|
# ensure the request_span is finished and the context reset;
|
70
66
|
# this assumes that the Rack middleware creates a root span
|
@@ -84,19 +80,13 @@ module Datadog
|
|
84
80
|
end
|
85
81
|
end
|
86
82
|
|
87
|
-
def set_request_tags!(request_span, env, status, headers, response
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
|
94
|
-
# relative path + query string, and doesn't mutate.
|
95
|
-
#
|
96
|
-
# REQUEST_URI is only available depending on what web server is running though.
|
97
|
-
# So when its not available, we want the original, unmutated PATH_INFO, which
|
98
|
-
# is just the relative path without query strings.
|
99
|
-
url = env['REQUEST_URI'] || original_env['PATH_INFO']
|
83
|
+
def set_request_tags!(request_span, env, status, headers, response)
|
84
|
+
# the source of truth in Rack is the PATH_INFO key that holds the
|
85
|
+
# URL for the current request; some framework may override that
|
86
|
+
# value, especially during exception handling and because of that
|
87
|
+
# we prefer using the `REQUEST_URI` if this is available.
|
88
|
+
# NOTE: `REQUEST_URI` is Rails specific and may not apply for other frameworks
|
89
|
+
url = env['REQUEST_URI'] || env['PATH_INFO']
|
100
90
|
request_id = get_request_id(headers, env)
|
101
91
|
|
102
92
|
request_span.resource ||= resource_name_for(env, status)
|
@@ -6,13 +6,9 @@ module Datadog
|
|
6
6
|
module Rails
|
7
7
|
# Code used to create and handle 'rails.action_controller' spans.
|
8
8
|
module ActionController
|
9
|
-
include Datadog::Patcher
|
10
|
-
|
11
9
|
def self.instrument
|
12
10
|
# patch Rails core components
|
13
|
-
|
14
|
-
Datadog::RailsActionPatcher.patch_action_controller
|
15
|
-
end
|
11
|
+
Datadog::RailsActionPatcher.patch_action_controller
|
16
12
|
end
|
17
13
|
|
18
14
|
def self.start_processing(payload)
|
@@ -50,14 +46,20 @@ module Datadog
|
|
50
46
|
span.set_tag('rails.route.action', payload.fetch(:action))
|
51
47
|
span.set_tag('rails.route.controller', payload.fetch(:controller))
|
52
48
|
|
53
|
-
|
54
|
-
if exception.nil?
|
49
|
+
if payload[:exception].nil?
|
55
50
|
# [christian] in some cases :status is not defined,
|
56
51
|
# rather than firing an error, simply acknowledge we don't know it.
|
57
52
|
status = payload.fetch(:status, '?').to_s
|
58
53
|
span.status = 1 if status.starts_with?('5')
|
59
|
-
|
60
|
-
|
54
|
+
else
|
55
|
+
error = payload[:exception]
|
56
|
+
if defined?(::ActionDispatch::ExceptionWrapper)
|
57
|
+
status = ::ActionDispatch::ExceptionWrapper.status_code_for_exception(error[0])
|
58
|
+
status = status ? status.to_s : '?'
|
59
|
+
else
|
60
|
+
status = '500'
|
61
|
+
end
|
62
|
+
span.set_error(error) if status.starts_with?('5')
|
61
63
|
end
|
62
64
|
ensure
|
63
65
|
span.finish()
|
@@ -5,13 +5,9 @@ module Datadog
|
|
5
5
|
module Rails
|
6
6
|
# Code used to create and handle 'rails.render_template' and 'rails.render_partial' spans.
|
7
7
|
module ActionView
|
8
|
-
include Datadog::Patcher
|
9
|
-
|
10
8
|
def self.instrument
|
11
9
|
# patch Rails core components
|
12
|
-
|
13
|
-
Datadog::RailsRendererPatcher.patch_renderer
|
14
|
-
end
|
10
|
+
Datadog::RailsRendererPatcher.patch_renderer
|
15
11
|
end
|
16
12
|
|
17
13
|
def self.start_render_template(payload)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'ddtrace/ext/sql'
|
2
|
-
|
3
2
|
require 'ddtrace/contrib/rails/utils'
|
4
3
|
|
5
4
|
module Datadog
|
@@ -7,16 +6,19 @@ module Datadog
|
|
7
6
|
module Rails
|
8
7
|
# Code used to create and handle 'mysql.query', 'postgres.query', ... spans.
|
9
8
|
module ActiveRecord
|
10
|
-
include Datadog::Patcher
|
11
|
-
|
12
9
|
def self.instrument
|
13
10
|
# ActiveRecord is instrumented only if it's available
|
14
11
|
return unless defined?(::ActiveRecord)
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
# subscribe when the active record query has been processed
|
14
|
+
::ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
|
15
|
+
sql(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
if Datadog::Contrib::Rails::Patcher.active_record_instantiation_tracing_supported?
|
19
|
+
# subscribe when the active record instantiates objects
|
20
|
+
::ActiveSupport::Notifications.subscribe('instantiation.active_record') do |*args|
|
21
|
+
instantiation(*args)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -24,14 +26,16 @@ module Datadog
|
|
24
26
|
def self.sql(_name, start, finish, _id, payload)
|
25
27
|
tracer = Datadog.configuration[:rails][:tracer]
|
26
28
|
database_service = Datadog.configuration[:rails][:database_service]
|
27
|
-
|
28
|
-
|
29
|
+
adapter_name = Datadog::Contrib::Rails::Utils.adapter_name
|
30
|
+
database_name = Datadog::Contrib::Rails::Utils.database_name
|
31
|
+
adapter_host = Datadog::Contrib::Rails::Utils.adapter_host
|
32
|
+
adapter_port = Datadog::Contrib::Rails::Utils.adapter_port
|
29
33
|
|
30
34
|
span = tracer.trace(
|
31
|
-
"#{
|
35
|
+
"#{adapter_name}.query",
|
32
36
|
resource: payload.fetch(:sql),
|
33
37
|
service: database_service,
|
34
|
-
span_type:
|
38
|
+
span_type: Datadog::Ext::SQL::TYPE
|
35
39
|
)
|
36
40
|
|
37
41
|
# Find out if the SQL query has been cached in this request. This meta is really
|
@@ -42,16 +46,33 @@ module Datadog
|
|
42
46
|
# the span should have the query ONLY in the Resource attribute,
|
43
47
|
# so that the ``sql.query`` tag will be set in the agent with an
|
44
48
|
# obfuscated version
|
45
|
-
span.
|
46
|
-
span.set_tag('rails.db.
|
47
|
-
span.set_tag('rails.db.name', connection_config[:database_name])
|
49
|
+
span.set_tag('rails.db.vendor', adapter_name)
|
50
|
+
span.set_tag('rails.db.name', database_name)
|
48
51
|
span.set_tag('rails.db.cached', cached) if cached
|
49
|
-
span.set_tag('out.host',
|
50
|
-
span.set_tag('out.port',
|
52
|
+
span.set_tag('out.host', adapter_host)
|
53
|
+
span.set_tag('out.port', adapter_port)
|
54
|
+
span.start_time = start
|
55
|
+
span.finish(finish)
|
56
|
+
rescue StandardError => e
|
57
|
+
Datadog::Tracer.log.debug(e.message)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.instantiation(_name, start, finish, _id, payload)
|
61
|
+
tracer = Datadog.configuration[:rails][:tracer]
|
62
|
+
|
63
|
+
span = tracer.trace(
|
64
|
+
'active_record.instantiation',
|
65
|
+
resource: payload.fetch(:class_name),
|
66
|
+
span_type: 'custom'
|
67
|
+
)
|
68
|
+
|
69
|
+
span.service = span.parent ? span.parent.service : Datadog.configuration[:rails][:service_name]
|
70
|
+
span.set_tag('active_record.instantiation.class_name', payload.fetch(:class_name))
|
71
|
+
span.set_tag('active_record.instantiation.record_count', payload.fetch(:record_count))
|
51
72
|
span.start_time = start
|
52
73
|
span.finish(finish)
|
53
74
|
rescue StandardError => e
|
54
|
-
Datadog::Tracer.log.
|
75
|
+
Datadog::Tracer.log.debug(e.message)
|
55
76
|
end
|
56
77
|
end
|
57
78
|
end
|
@@ -6,13 +6,9 @@ module Datadog
|
|
6
6
|
module Rails
|
7
7
|
# Code used to create and handle 'rails.cache' spans.
|
8
8
|
module ActiveSupport
|
9
|
-
include Datadog::Patcher
|
10
|
-
|
11
9
|
def self.instrument
|
12
|
-
|
13
|
-
|
14
|
-
Datadog::RailsCachePatcher.patch_cache_store
|
15
|
-
end
|
10
|
+
# patch Rails core components
|
11
|
+
Datadog::RailsCachePatcher.patch_cache_store
|
16
12
|
end
|
17
13
|
|
18
14
|
def self.start_trace_cache(payload)
|
@@ -4,211 +4,193 @@ module Datadog
|
|
4
4
|
# rubocop:disable Metrics/MethodLength
|
5
5
|
# rubocop:disable Metrics/ModuleLength
|
6
6
|
module RailsRendererPatcher
|
7
|
-
include Datadog::Patcher
|
8
|
-
|
9
7
|
module_function
|
10
8
|
|
11
9
|
def patch_renderer
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Datadog::Tracer.log.debug('Expected Template/Partial classes not found; template rendering disabled')
|
22
|
-
end
|
10
|
+
if defined?(::ActionView::TemplateRenderer) && defined?(::ActionView::PartialRenderer)
|
11
|
+
patch_template_renderer(::ActionView::TemplateRenderer)
|
12
|
+
patch_partial_renderer(::ActionView::PartialRenderer)
|
13
|
+
elsif defined?(::ActionView::Rendering) && defined?(::ActionView::Partials::PartialRenderer)
|
14
|
+
# NOTE: Rails < 3.1 compatibility: different classes are used
|
15
|
+
patch_template_renderer(::ActionView::Rendering)
|
16
|
+
patch_partial_renderer(::ActionView::Partials::PartialRenderer)
|
17
|
+
else
|
18
|
+
Datadog::Tracer.log.debug('Expected Template/Partial classes not found; template rendering disabled')
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
22
|
def patch_template_renderer(klass)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
Datadog::Contrib::Rails::ActionView.start_render_template(tracing_context: @tracing_context)
|
36
|
-
end
|
37
|
-
|
38
|
-
render_without_datadog(*args, &block)
|
39
|
-
rescue Exception => e
|
40
|
-
# attach the exception to the tracing context if any
|
41
|
-
@tracing_context[:exception] = e
|
42
|
-
raise e
|
43
|
-
ensure
|
44
|
-
# ensure that the template `Span` is finished even during exceptions
|
45
|
-
Datadog::Contrib::Rails::ActionView.finish_render_template(tracing_context: @tracing_context)
|
23
|
+
klass.class_eval do
|
24
|
+
def render_with_datadog(*args, &block)
|
25
|
+
# create a tracing context and start the rendering span
|
26
|
+
# NOTE: Rails < 3.1 compatibility: preserve the tracing
|
27
|
+
# context when a partial is rendered
|
28
|
+
@tracing_context ||= {}
|
29
|
+
if @tracing_context.empty?
|
30
|
+
Datadog::Contrib::Rails::ActionView.start_render_template(tracing_context: @tracing_context)
|
46
31
|
end
|
47
32
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
33
|
+
render_without_datadog(*args)
|
34
|
+
rescue Exception => e
|
35
|
+
# attach the exception to the tracing context if any
|
36
|
+
@tracing_context[:exception] = e
|
37
|
+
raise e
|
38
|
+
ensure
|
39
|
+
# ensure that the template `Span` is finished even during exceptions
|
40
|
+
Datadog::Contrib::Rails::ActionView.finish_render_template(tracing_context: @tracing_context)
|
41
|
+
end
|
42
|
+
|
43
|
+
def render_template_with_datadog(*args)
|
44
|
+
begin
|
45
|
+
# arguments based on render_template signature (stable since Rails 3.2)
|
46
|
+
template = args[0]
|
47
|
+
layout_name = args[1]
|
48
|
+
|
49
|
+
# update the tracing context with computed values before the rendering
|
50
|
+
template_name = template.try('identifier')
|
51
|
+
template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(template_name)
|
52
|
+
layout = if layout_name.is_a?(String)
|
53
|
+
# NOTE: Rails < 3.1 compatibility: the second argument is the layout name
|
54
|
+
layout_name
|
55
|
+
else
|
56
|
+
layout_name.try(:[], 'virtual_path')
|
57
|
+
end
|
58
|
+
@tracing_context[:template_name] = template_name
|
59
|
+
@tracing_context[:layout] = layout
|
60
|
+
rescue StandardError => e
|
61
|
+
Datadog::Tracer.log.debug(e.message)
|
71
62
|
end
|
72
63
|
|
73
|
-
#
|
74
|
-
|
75
|
-
|
64
|
+
# execute the original function anyway
|
65
|
+
render_template_without_datadog(*args)
|
66
|
+
end
|
76
67
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
68
|
+
# method aliasing to patch the class
|
69
|
+
alias_method :render_without_datadog, :render
|
70
|
+
alias_method :render, :render_with_datadog
|
71
|
+
|
72
|
+
if klass.private_method_defined?(:render_template) || klass.method_defined?(:render_template)
|
73
|
+
alias_method :render_template_without_datadog, :render_template
|
74
|
+
alias_method :render_template, :render_template_with_datadog
|
75
|
+
else
|
76
|
+
# NOTE: Rails < 3.1 compatibility: the method name is different
|
77
|
+
alias_method :render_template_without_datadog, :_render_template
|
78
|
+
alias_method :_render_template, :render_template_with_datadog
|
85
79
|
end
|
86
80
|
end
|
87
81
|
end
|
88
82
|
|
89
83
|
def patch_partial_renderer(klass)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
84
|
+
klass.class_eval do
|
85
|
+
def render_with_datadog(*args, &block)
|
86
|
+
# Create a tracing context and start the rendering span
|
87
|
+
tracing_context = {}
|
88
|
+
Datadog::Contrib::Rails::ActionView.start_render_partial(tracing_context: tracing_context)
|
89
|
+
tracing_contexts[current_span_id] = tracing_context
|
90
|
+
|
91
|
+
render_without_datadog(*args)
|
92
|
+
rescue Exception => e
|
93
|
+
# attach the exception to the tracing context if any
|
94
|
+
tracing_contexts[current_span_id][:exception] = e
|
95
|
+
raise e
|
96
|
+
ensure
|
97
|
+
# Ensure that the template `Span` is finished even during exceptions
|
98
|
+
# Remove the existing tracing context (to avoid leaks)
|
99
|
+
tracing_contexts.delete(current_span_id)
|
100
|
+
|
101
|
+
# Then finish the span associated with the context
|
102
|
+
Datadog::Contrib::Rails::ActionView.finish_render_partial(tracing_context: tracing_context)
|
103
|
+
end
|
111
104
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
# execute the original function anyway
|
122
|
-
render_partial_without_datadog(*args)
|
105
|
+
def render_partial_with_datadog(*args)
|
106
|
+
begin
|
107
|
+
# update the tracing context with computed values before the rendering
|
108
|
+
template_name = Datadog::Contrib::Rails::Utils.normalize_template_name(@template.try('identifier'))
|
109
|
+
tracing_contexts[current_span_id][:template_name] = template_name
|
110
|
+
rescue StandardError => e
|
111
|
+
Datadog::Tracer.log.debug(e.message)
|
123
112
|
end
|
124
113
|
|
125
|
-
#
|
126
|
-
|
127
|
-
|
128
|
-
def tracing_contexts
|
129
|
-
@tracing_contexts ||= {}
|
130
|
-
end
|
114
|
+
# execute the original function anyway
|
115
|
+
render_partial_without_datadog(*args)
|
116
|
+
end
|
131
117
|
|
132
|
-
|
133
|
-
|
134
|
-
|
118
|
+
# Table of tracing contexts, one per partial/span, keyed by span_id
|
119
|
+
# because there will be multiple concurrent contexts, depending on how
|
120
|
+
# many partials are nested within one another.
|
121
|
+
def tracing_contexts
|
122
|
+
@tracing_contexts ||= {}
|
123
|
+
end
|
135
124
|
|
136
|
-
|
137
|
-
|
138
|
-
alias_method :render, :render_with_datadog
|
139
|
-
alias_method :render_partial_without_datadog, :render_partial
|
140
|
-
alias_method :render_partial, :render_partial_with_datadog
|
125
|
+
def current_span_id
|
126
|
+
Datadog.configuration[:rails][:tracer].call_context.current_span.span_id
|
141
127
|
end
|
128
|
+
|
129
|
+
# method aliasing to patch the class
|
130
|
+
alias_method :render_without_datadog, :render
|
131
|
+
alias_method :render, :render_with_datadog
|
132
|
+
alias_method :render_partial_without_datadog, :render_partial
|
133
|
+
alias_method :render_partial, :render_partial_with_datadog
|
142
134
|
end
|
143
135
|
end
|
144
136
|
end
|
145
137
|
|
146
138
|
# RailsActionPatcher contains functions to patch Rails action controller instrumentation
|
147
139
|
module RailsActionPatcher
|
148
|
-
include Datadog::Patcher
|
149
|
-
|
150
140
|
module_function
|
151
141
|
|
152
142
|
def patch_action_controller
|
153
|
-
|
154
|
-
patch_process_action
|
155
|
-
end
|
143
|
+
patch_process_action
|
156
144
|
end
|
157
145
|
|
158
146
|
def patch_process_action
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
raise e
|
186
|
-
end
|
187
|
-
ensure
|
188
|
-
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
|
147
|
+
::ActionController::Instrumentation.class_eval do
|
148
|
+
def process_action_with_datadog(*args)
|
149
|
+
# mutable payload with a tracing context that is used in two different
|
150
|
+
# signals; it propagates the request span so that it can be finished
|
151
|
+
# no matter what
|
152
|
+
payload = {
|
153
|
+
controller: self.class,
|
154
|
+
action: action_name,
|
155
|
+
headers: {
|
156
|
+
# The exception this controller was given in the request,
|
157
|
+
# which is typical if the controller is configured to handle exceptions.
|
158
|
+
request_exception: request.headers['action_dispatch.exception']
|
159
|
+
},
|
160
|
+
tracing_context: {}
|
161
|
+
}
|
162
|
+
|
163
|
+
begin
|
164
|
+
# process and catch request exceptions
|
165
|
+
Datadog::Contrib::Rails::ActionController.start_processing(payload)
|
166
|
+
result = process_action_without_datadog(*args)
|
167
|
+
payload[:status] = response.status
|
168
|
+
result
|
169
|
+
rescue Exception => e
|
170
|
+
payload[:exception] = [e.class.name, e.message]
|
171
|
+
payload[:exception_object] = e
|
172
|
+
raise e
|
189
173
|
end
|
190
|
-
|
191
|
-
|
192
|
-
alias_method :process_action, :process_action_with_datadog
|
174
|
+
ensure
|
175
|
+
Datadog::Contrib::Rails::ActionController.finish_processing(payload)
|
193
176
|
end
|
177
|
+
|
178
|
+
alias_method :process_action_without_datadog, :process_action
|
179
|
+
alias_method :process_action, :process_action_with_datadog
|
194
180
|
end
|
195
181
|
end
|
196
182
|
end
|
197
183
|
|
198
184
|
# RailsCachePatcher contains function to patch Rails caching libraries.
|
199
185
|
module RailsCachePatcher
|
200
|
-
include Datadog::Patcher
|
201
|
-
|
202
186
|
module_function
|
203
187
|
|
204
188
|
def patch_cache_store
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
reload_cache_store
|
211
|
-
end
|
189
|
+
patch_cache_store_read
|
190
|
+
patch_cache_store_fetch
|
191
|
+
patch_cache_store_write
|
192
|
+
patch_cache_store_delete
|
193
|
+
reload_cache_store
|
212
194
|
end
|
213
195
|
|
214
196
|
def cache_store_class(k)
|
@@ -228,116 +210,107 @@ module Datadog
|
|
228
210
|
end
|
229
211
|
|
230
212
|
def patch_cache_store_read
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
raise e
|
249
|
-
end
|
250
|
-
ensure
|
251
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
213
|
+
cache_store_class(:read).class_eval do
|
214
|
+
alias_method :read_without_datadog, :read
|
215
|
+
def read(*args, &block)
|
216
|
+
payload = {
|
217
|
+
action: 'GET',
|
218
|
+
key: args[0],
|
219
|
+
tracing_context: {}
|
220
|
+
}
|
221
|
+
|
222
|
+
begin
|
223
|
+
# process and catch cache exceptions
|
224
|
+
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
225
|
+
read_without_datadog(*args, &block)
|
226
|
+
rescue Exception => e
|
227
|
+
payload[:exception] = [e.class.name, e.message]
|
228
|
+
payload[:exception_object] = e
|
229
|
+
raise e
|
252
230
|
end
|
231
|
+
ensure
|
232
|
+
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
253
233
|
end
|
254
234
|
end
|
255
235
|
end
|
256
236
|
|
257
237
|
def patch_cache_store_fetch
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
raise e
|
276
|
-
end
|
277
|
-
ensure
|
278
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
238
|
+
cache_store_class(:fetch).class_eval do
|
239
|
+
alias_method :fetch_without_datadog, :fetch
|
240
|
+
def fetch(*args, &block)
|
241
|
+
payload = {
|
242
|
+
action: 'GET',
|
243
|
+
key: args[0],
|
244
|
+
tracing_context: {}
|
245
|
+
}
|
246
|
+
|
247
|
+
begin
|
248
|
+
# process and catch cache exceptions
|
249
|
+
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
250
|
+
fetch_without_datadog(*args, &block)
|
251
|
+
rescue Exception => e
|
252
|
+
payload[:exception] = [e.class.name, e.message]
|
253
|
+
payload[:exception_object] = e
|
254
|
+
raise e
|
279
255
|
end
|
256
|
+
ensure
|
257
|
+
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
280
258
|
end
|
281
259
|
end
|
282
260
|
end
|
283
261
|
|
284
262
|
def patch_cache_store_write
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
raise e
|
303
|
-
end
|
304
|
-
ensure
|
305
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
263
|
+
cache_store_class(:write).class_eval do
|
264
|
+
alias_method :write_without_datadog, :write
|
265
|
+
def write(*args, &block)
|
266
|
+
payload = {
|
267
|
+
action: 'SET',
|
268
|
+
key: args[0],
|
269
|
+
tracing_context: {}
|
270
|
+
}
|
271
|
+
|
272
|
+
begin
|
273
|
+
# process and catch cache exceptions
|
274
|
+
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
275
|
+
write_without_datadog(*args, &block)
|
276
|
+
rescue Exception => e
|
277
|
+
payload[:exception] = [e.class.name, e.message]
|
278
|
+
payload[:exception_object] = e
|
279
|
+
raise e
|
306
280
|
end
|
281
|
+
ensure
|
282
|
+
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
307
283
|
end
|
308
284
|
end
|
309
285
|
end
|
310
286
|
|
311
287
|
def patch_cache_store_delete
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
raise e
|
330
|
-
end
|
331
|
-
ensure
|
332
|
-
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
288
|
+
cache_store_class(:delete).class_eval do
|
289
|
+
alias_method :delete_without_datadog, :delete
|
290
|
+
def delete(*args, &block)
|
291
|
+
payload = {
|
292
|
+
action: 'DELETE',
|
293
|
+
key: args[0],
|
294
|
+
tracing_context: {}
|
295
|
+
}
|
296
|
+
|
297
|
+
begin
|
298
|
+
# process and catch cache exceptions
|
299
|
+
Datadog::Contrib::Rails::ActiveSupport.start_trace_cache(payload)
|
300
|
+
delete_without_datadog(*args, &block)
|
301
|
+
rescue Exception => e
|
302
|
+
payload[:exception] = [e.class.name, e.message]
|
303
|
+
payload[:exception_object] = e
|
304
|
+
raise e
|
333
305
|
end
|
306
|
+
ensure
|
307
|
+
Datadog::Contrib::Rails::ActiveSupport.finish_trace_cache(payload)
|
334
308
|
end
|
335
309
|
end
|
336
310
|
end
|
337
311
|
|
338
312
|
def self.reload_cache_store
|
339
|
-
|
340
|
-
return unless redis && redis.patched?
|
313
|
+
return unless Datadog.registry[:redis].patched?
|
341
314
|
|
342
315
|
return unless defined?(::ActiveSupport::Cache::RedisStore) &&
|
343
316
|
defined?(::Rails.cache) &&
|