scout_apm 2.2.0.pre3 → 2.3.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/CHANGELOG.markdown +147 -2
- data/Guardfile +43 -0
- data/Rakefile +2 -2
- data/ext/allocations/allocations.c +6 -0
- data/ext/allocations/extconf.rb +1 -0
- data/ext/rusage/README.md +26 -0
- data/ext/rusage/extconf.rb +5 -0
- data/ext/rusage/rusage.c +52 -0
- data/lib/scout_apm.rb +28 -15
- data/lib/scout_apm/agent.rb +89 -37
- data/lib/scout_apm/agent/logging.rb +6 -1
- data/lib/scout_apm/agent/reporting.rb +9 -6
- data/lib/scout_apm/app_server_load.rb +21 -10
- data/lib/scout_apm/attribute_arranger.rb +6 -3
- data/lib/scout_apm/background_job_integrations/delayed_job.rb +71 -1
- data/lib/scout_apm/background_job_integrations/resque.rb +85 -0
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +22 -20
- data/lib/scout_apm/background_recorder.rb +43 -0
- data/lib/scout_apm/background_worker.rb +19 -15
- data/lib/scout_apm/config.rb +138 -28
- data/lib/scout_apm/db_query_metric_set.rb +80 -0
- data/lib/scout_apm/db_query_metric_stats.rb +102 -0
- data/lib/scout_apm/debug.rb +37 -0
- data/lib/scout_apm/environment.rb +22 -15
- data/lib/scout_apm/git_revision.rb +51 -0
- data/lib/scout_apm/histogram.rb +11 -2
- data/lib/scout_apm/instant/assets/xmlhttp_instrumentation.html +2 -2
- data/lib/scout_apm/instant/middleware.rb +196 -54
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +89 -68
- data/lib/scout_apm/instruments/action_view.rb +49 -0
- data/lib/scout_apm/instruments/active_record.rb +127 -3
- data/lib/scout_apm/instruments/grape.rb +4 -3
- data/lib/scout_apm/instruments/middleware_detailed.rb +4 -6
- data/lib/scout_apm/instruments/mongoid.rb +24 -3
- data/lib/scout_apm/instruments/net_http.rb +7 -2
- data/lib/scout_apm/instruments/percentile_sampler.rb +36 -19
- data/lib/scout_apm/instruments/process/process_cpu.rb +3 -2
- data/lib/scout_apm/instruments/process/process_memory.rb +3 -3
- data/lib/scout_apm/instruments/resque.rb +40 -0
- data/lib/scout_apm/layaway.rb +67 -28
- data/lib/scout_apm/layer.rb +19 -59
- data/lib/scout_apm/layer_children_set.rb +77 -0
- data/lib/scout_apm/layer_converters/allocation_metric_converter.rb +5 -6
- data/lib/scout_apm/layer_converters/converter_base.rb +201 -14
- data/lib/scout_apm/layer_converters/database_converter.rb +55 -0
- data/lib/scout_apm/layer_converters/depth_first_walker.rb +22 -10
- data/lib/scout_apm/layer_converters/error_converter.rb +5 -7
- data/lib/scout_apm/layer_converters/find_layer_by_type.rb +34 -0
- data/lib/scout_apm/layer_converters/histograms.rb +14 -0
- data/lib/scout_apm/layer_converters/job_converter.rb +36 -50
- data/lib/scout_apm/layer_converters/metric_converter.rb +17 -19
- data/lib/scout_apm/layer_converters/request_queue_time_converter.rb +10 -12
- data/lib/scout_apm/layer_converters/slow_job_converter.rb +41 -115
- data/lib/scout_apm/layer_converters/slow_request_converter.rb +33 -117
- data/lib/scout_apm/limited_layer.rb +126 -0
- data/lib/scout_apm/metric_meta.rb +0 -5
- data/lib/scout_apm/metric_set.rb +9 -1
- data/lib/scout_apm/metric_stats.rb +7 -8
- data/lib/scout_apm/rack.rb +26 -0
- data/lib/scout_apm/remote/message.rb +23 -0
- data/lib/scout_apm/remote/recorder.rb +57 -0
- data/lib/scout_apm/remote/router.rb +49 -0
- data/lib/scout_apm/remote/server.rb +58 -0
- data/lib/scout_apm/reporter.rb +51 -15
- data/lib/scout_apm/request_histograms.rb +4 -0
- data/lib/scout_apm/request_manager.rb +2 -1
- data/lib/scout_apm/scored_item_set.rb +7 -0
- data/lib/scout_apm/serializers/db_query_serializer_to_json.rb +15 -0
- data/lib/scout_apm/serializers/histograms_serializer_to_json.rb +21 -0
- data/lib/scout_apm/serializers/payload_serializer.rb +10 -3
- data/lib/scout_apm/serializers/payload_serializer_to_json.rb +6 -6
- data/lib/scout_apm/serializers/slow_jobs_serializer_to_json.rb +2 -1
- data/lib/scout_apm/server_integrations/puma.rb +5 -2
- data/lib/scout_apm/slow_job_policy.rb +1 -10
- data/lib/scout_apm/slow_job_record.rb +6 -1
- data/lib/scout_apm/slow_request_policy.rb +1 -10
- data/lib/scout_apm/slow_transaction.rb +20 -2
- data/lib/scout_apm/store.rb +66 -12
- data/lib/scout_apm/synchronous_recorder.rb +26 -0
- data/lib/scout_apm/tracked_request.rb +136 -71
- data/lib/scout_apm/utils/active_record_metric_name.rb +8 -4
- data/lib/scout_apm/utils/backtrace_parser.rb +3 -3
- data/lib/scout_apm/utils/gzip_helper.rb +24 -0
- data/lib/scout_apm/utils/numbers.rb +14 -0
- data/lib/scout_apm/utils/scm.rb +14 -0
- data/lib/scout_apm/version.rb +1 -1
- data/scout_apm.gemspec +5 -4
- data/test/test_helper.rb +18 -0
- data/test/unit/config_test.rb +59 -8
- data/test/unit/db_query_metric_set_test.rb +56 -0
- data/test/unit/db_query_metric_stats_test.rb +113 -0
- data/test/unit/git_revision_test.rb +15 -0
- data/test/unit/histogram_test.rb +14 -0
- data/test/unit/instruments/net_http_test.rb +21 -0
- data/test/unit/instruments/percentile_sampler_test.rb +137 -0
- data/test/unit/layaway_test.rb +20 -0
- data/test/unit/layer_children_set_test.rb +88 -0
- data/test/unit/layer_converters/depth_first_walker_test.rb +66 -0
- data/test/unit/layer_converters/metric_converter_test.rb +22 -0
- data/test/unit/layer_converters/stubs.rb +33 -0
- data/test/unit/limited_layer_test.rb +53 -0
- data/test/unit/remote/test_message.rb +13 -0
- data/test/unit/remote/test_router.rb +33 -0
- data/test/unit/remote/test_server.rb +15 -0
- data/test/unit/serializers/payload_serializer_test.rb +3 -12
- data/test/unit/store_test.rb +66 -0
- data/test/unit/test_tracked_request.rb +87 -0
- data/test/unit/utils/active_record_metric_name_test.rb +8 -0
- data/test/unit/utils/backtrace_parser_test.rb +5 -0
- data/test/unit/utils/numbers_test.rb +15 -0
- data/test/unit/utils/scm.rb +17 -0
- metadata +125 -30
- data/ext/stacks/extconf.rb +0 -37
- data/ext/stacks/scout_atomics.h +0 -86
- data/ext/stacks/stacks.c +0 -811
- data/lib/scout_apm/capacity.rb +0 -57
- data/lib/scout_apm/deploy_integrations/capistrano_2.cap +0 -12
- data/lib/scout_apm/deploy_integrations/capistrano_2.rb +0 -83
- data/lib/scout_apm/deploy_integrations/capistrano_3.cap +0 -12
- data/lib/scout_apm/deploy_integrations/capistrano_3.rb +0 -88
- data/lib/scout_apm/instruments/delayed_job.rb +0 -57
- data/lib/scout_apm/serializers/deploy_serializer.rb +0 -16
- data/lib/scout_apm/trace_compactor.rb +0 -312
- data/lib/scout_apm/utils/fake_stacks.rb +0 -87
- data/tester.rb +0 -53
@@ -20,84 +20,78 @@ module ScoutApm
|
|
20
20
|
# before and after filter timing. Instrumenting Base includes those
|
21
21
|
# filters, at the expense of missing out on controllers that don't use
|
22
22
|
# the full Rails stack.
|
23
|
-
if defined?(::ActionController)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
if defined?(::ActionController)
|
24
|
+
if defined?(::ActionController::Base)
|
25
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActionController::Base"
|
26
|
+
::ActionController::Base.class_eval do
|
27
|
+
# include ScoutApm::Tracer
|
28
|
+
include ScoutApm::Instruments::ActionControllerBaseInstruments
|
29
|
+
end
|
28
30
|
end
|
29
|
-
ScoutApm::Agent.instance.logger.info "Installing ScoutProf profiling" if ScoutApm::Agent.instance.config.value('profile')
|
30
|
-
end
|
31
|
-
|
32
|
-
if defined?(::ActionView) && defined?(::ActionView::PartialRenderer)
|
33
|
-
ScoutApm::Agent.instance.logger.info "Instrumenting ActionView::PartialRenderer"
|
34
|
-
::ActionView::PartialRenderer.class_eval do
|
35
|
-
include ScoutApm::Tracer
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
instrument_method :collection_with_template,
|
43
|
-
:type => "View",
|
44
|
-
:name => '#{@template.virtual_path rescue "Unknown Collection"}/Rendering',
|
45
|
-
:scope => true
|
32
|
+
if defined?(::ActionController::Metal)
|
33
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActionController::Metal"
|
34
|
+
::ActionController::Metal.class_eval do
|
35
|
+
include ScoutApm::Instruments::ActionControllerMetalInstruments
|
36
|
+
end
|
46
37
|
end
|
47
38
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
:name => '#{args[0].virtual_path rescue "Unknown"}/Rendering',
|
54
|
-
:scope => true
|
39
|
+
if defined?(::ActionController::API)
|
40
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActionController::Api"
|
41
|
+
::ActionController::API.class_eval do
|
42
|
+
include ScoutApm::Instruments::ActionControllerAPIInstruments
|
43
|
+
end
|
55
44
|
end
|
56
45
|
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
module ActionControllerRails3Rails4Instruments
|
61
|
-
def process_action(*args)
|
62
|
-
req = ScoutApm::RequestManager.lookup
|
63
|
-
req.annotate_request(:uri => scout_transaction_uri(request))
|
64
|
-
|
65
|
-
# IP Spoofing Protection can throw an exception, just move on w/o remote ip
|
66
|
-
req.context.add_user(:ip => request.remote_ip) rescue nil
|
67
|
-
|
68
|
-
req.set_headers(request.headers)
|
69
|
-
|
70
|
-
# Check if this this request is to be reported instantly
|
71
|
-
if instant_key = request.cookies['scoutapminstant']
|
72
|
-
Agent.instance.logger.info "Instant trace request with key=#{instant_key} for path=#{path}"
|
73
|
-
req.instant_key = instant_key
|
74
|
-
end
|
75
|
-
|
76
|
-
req.web!
|
77
46
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
layer.traced!
|
85
|
-
end
|
47
|
+
# Returns a new anonymous module each time it is called. So
|
48
|
+
# we can insert this multiple times into the ancestors
|
49
|
+
# stack. Otherwise it only exists the first time you include it
|
50
|
+
# (under Metal, instead of under API) and we miss instrumenting
|
51
|
+
# before_action callbacks
|
52
|
+
end
|
86
53
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
54
|
+
def self.build_instrument_module
|
55
|
+
Module.new do
|
56
|
+
def process_action(*args)
|
57
|
+
req = ScoutApm::RequestManager.lookup
|
58
|
+
current_layer = req.current_layer
|
59
|
+
|
60
|
+
# Check if this this request is to be reported instantly
|
61
|
+
if instant_key = request.cookies['scoutapminstant']
|
62
|
+
Agent.instance.logger.info "Instant trace request with key=#{instant_key} for path=#{path}"
|
63
|
+
req.instant_key = instant_key
|
64
|
+
end
|
65
|
+
|
66
|
+
if current_layer && current_layer.type == "Controller"
|
67
|
+
# Don't start a new layer if ActionController::API or ActionController::Base handled it already.
|
68
|
+
super
|
69
|
+
else
|
70
|
+
req.annotate_request(:uri => ScoutApm::Instruments::ActionControllerRails3Rails4.scout_transaction_uri(request))
|
71
|
+
|
72
|
+
# IP Spoofing Protection can throw an exception, just move on w/o remote ip
|
73
|
+
req.context.add_user(:ip => request.remote_ip) rescue nil
|
74
|
+
req.set_headers(request.headers)
|
75
|
+
|
76
|
+
req.web!
|
77
|
+
|
78
|
+
resolved_name = scout_action_name(*args)
|
79
|
+
req.start_layer( ScoutApm::Layer.new("Controller", "#{controller_path}/#{resolved_name}") )
|
80
|
+
begin
|
81
|
+
super
|
82
|
+
rescue
|
83
|
+
req.error!
|
84
|
+
raise
|
85
|
+
ensure
|
86
|
+
req.stop_layer
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
96
90
|
end
|
97
|
-
end
|
91
|
+
end
|
98
92
|
|
99
93
|
# Given an +ActionDispatch::Request+, formats the uri based on config settings.
|
100
|
-
def scout_transaction_uri(request)
|
94
|
+
def self.scout_transaction_uri(request)
|
101
95
|
case ScoutApm::Agent.instance.config.value("uri_reporting")
|
102
96
|
when 'path'
|
103
97
|
request.path # strips off the query string for more security
|
@@ -105,8 +99,35 @@ module ScoutApm
|
|
105
99
|
request.filtered_path
|
106
100
|
end
|
107
101
|
end
|
102
|
+
end
|
103
|
+
|
104
|
+
module ActionControllerMetalInstruments
|
105
|
+
include ScoutApm::Instruments::ActionControllerRails3Rails4.build_instrument_module
|
106
|
+
|
107
|
+
def scout_action_name(*args)
|
108
|
+
action_name = args[0]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Empty, noop module to provide compatibility w/ previous manual instrumentation
|
113
|
+
module ActionControllerRails3Rails4Instruments
|
114
|
+
end
|
115
|
+
|
116
|
+
module ActionControllerBaseInstruments
|
117
|
+
include ScoutApm::Instruments::ActionControllerRails3Rails4.build_instrument_module
|
118
|
+
|
119
|
+
def scout_action_name(*args)
|
120
|
+
action_name
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
module ActionControllerAPIInstruments
|
125
|
+
include ScoutApm::Instruments::ActionControllerRails3Rails4.build_instrument_module
|
108
126
|
|
109
|
-
|
127
|
+
def scout_action_name(*args)
|
128
|
+
action_name
|
129
|
+
end
|
130
|
+
end
|
110
131
|
end
|
111
132
|
end
|
112
133
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
# instrumentation for Rails 3 and Rails 4 is the same.
|
4
|
+
class ActionView
|
5
|
+
attr_reader :logger
|
6
|
+
|
7
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
8
|
+
@logger = logger
|
9
|
+
@installed = false
|
10
|
+
end
|
11
|
+
|
12
|
+
def installed?
|
13
|
+
@installed
|
14
|
+
end
|
15
|
+
|
16
|
+
def install
|
17
|
+
@installed = true
|
18
|
+
|
19
|
+
if defined?(::ActionView) && defined?(::ActionView::PartialRenderer)
|
20
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActionView::PartialRenderer"
|
21
|
+
::ActionView::PartialRenderer.class_eval do
|
22
|
+
include ScoutApm::Tracer
|
23
|
+
|
24
|
+
instrument_method :render_partial,
|
25
|
+
:type => "View",
|
26
|
+
:name => '#{@template.virtual_path rescue "Unknown Partial"}/Rendering',
|
27
|
+
:scope => true
|
28
|
+
|
29
|
+
instrument_method :collection_with_template,
|
30
|
+
:type => "View",
|
31
|
+
:name => '#{@template.virtual_path rescue "Unknown Collection"}/Rendering',
|
32
|
+
:scope => true
|
33
|
+
end
|
34
|
+
|
35
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActionView::TemplateRenderer"
|
36
|
+
::ActionView::TemplateRenderer.class_eval do
|
37
|
+
include ScoutApm::Tracer
|
38
|
+
instrument_method :render_template,
|
39
|
+
:type => "View",
|
40
|
+
:name => '#{args[0].virtual_path rescue "Unknown"}/Rendering',
|
41
|
+
:scope => true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
@@ -42,6 +42,18 @@ module ScoutApm
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
if Utils::KlassHelper.defined?("ActiveRecord::Base")
|
46
|
+
::ActiveRecord::Base.class_eval do
|
47
|
+
include ::ScoutApm::Instruments::ActiveRecordUpdateInstruments
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if Utils::KlassHelper.defined?("ActiveRecord::Relation")
|
52
|
+
::ActiveRecord::Relation.class_eval do
|
53
|
+
include ::ScoutApm::Instruments::ActiveRecordRelationInstruments
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
45
57
|
if Utils::KlassHelper.defined?("ActiveRecord::Querying")
|
46
58
|
::ActiveRecord::Querying.module_eval do
|
47
59
|
include ::ScoutApm::Tracer
|
@@ -62,8 +74,10 @@ module ScoutApm
|
|
62
74
|
layer = req.current_layer
|
63
75
|
if layer && layer.type == "ActiveRecord"
|
64
76
|
layer.annotate_layer(payload)
|
65
|
-
|
77
|
+
elsif layer
|
66
78
|
ScoutApm::Agent.instance.logger.debug("Expected layer type: ActiveRecord, got #{layer && layer.type}")
|
79
|
+
else
|
80
|
+
# noop, no layer at all. We're probably ignoring this req.
|
67
81
|
end
|
68
82
|
end
|
69
83
|
end
|
@@ -120,7 +134,7 @@ module ScoutApm
|
|
120
134
|
current_layer.desc = desc
|
121
135
|
end
|
122
136
|
|
123
|
-
log_without_scout_instruments(
|
137
|
+
log_without_scout_instruments(*args, &block)
|
124
138
|
|
125
139
|
# OR: Start a new layer, we didn't pick up instrumentation earlier in the stack.
|
126
140
|
else
|
@@ -128,7 +142,7 @@ module ScoutApm
|
|
128
142
|
layer.desc = desc
|
129
143
|
req.start_layer(layer)
|
130
144
|
begin
|
131
|
-
log_without_scout_instruments(
|
145
|
+
log_without_scout_instruments(*args, &block)
|
132
146
|
ensure
|
133
147
|
req.stop_layer
|
134
148
|
end
|
@@ -206,5 +220,115 @@ module ScoutApm
|
|
206
220
|
end
|
207
221
|
end
|
208
222
|
end
|
223
|
+
|
224
|
+
module ActiveRecordUpdateInstruments
|
225
|
+
def self.included(instrumented_class)
|
226
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting ActiveRecord Save: - #{instrumented_class.inspect}"
|
227
|
+
instrumented_class.class_eval do
|
228
|
+
unless instrumented_class.method_defined?(:save_without_scout_instruments)
|
229
|
+
alias_method :save_without_scout_instruments, :save
|
230
|
+
alias_method :save, :save_with_scout_instruments
|
231
|
+
end
|
232
|
+
|
233
|
+
unless instrumented_class.method_defined?(:"savebang_without_scout_instruments")
|
234
|
+
alias_method :"savebang_without_scout_instruments", :"save!"
|
235
|
+
alias_method :"save!", :"savebang_with_scout_instruments"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
def savebang_with_scout_instruments(*args, &block)
|
242
|
+
model = self.class.name
|
243
|
+
operation = self.persisted? ? "Update" : "Create"
|
244
|
+
|
245
|
+
req = ScoutApm::RequestManager.lookup
|
246
|
+
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName.new("", "#{model} #{operation}"))
|
247
|
+
req.start_layer(layer)
|
248
|
+
req.ignore_children!
|
249
|
+
begin
|
250
|
+
savebang_without_scout_instruments(*args, &block)
|
251
|
+
ensure
|
252
|
+
req.acknowledge_children!
|
253
|
+
req.stop_layer
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def save_with_scout_instruments(*args, &block)
|
258
|
+
model = self.class.name
|
259
|
+
operation = self.persisted? ? "Update" : "Create"
|
260
|
+
|
261
|
+
req = ScoutApm::RequestManager.lookup
|
262
|
+
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName.new("", "#{model} #{operation}"))
|
263
|
+
req.start_layer(layer)
|
264
|
+
req.ignore_children!
|
265
|
+
begin
|
266
|
+
save_without_scout_instruments(*args, &block)
|
267
|
+
ensure
|
268
|
+
req.acknowledge_children!
|
269
|
+
req.stop_layer
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
module ActiveRecordRelationInstruments
|
275
|
+
def self.included(instrumented_class)
|
276
|
+
::ActiveRecord::Relation.class_eval do
|
277
|
+
alias_method :update_all_without_scout_instruments, :update_all
|
278
|
+
alias_method :update_all, :update_all_with_scout_instruments
|
279
|
+
|
280
|
+
alias_method :delete_all_without_scout_instruments, :delete_all
|
281
|
+
alias_method :delete_all, :delete_all_with_scout_instruments
|
282
|
+
|
283
|
+
alias_method :destroy_all_without_scout_instruments, :destroy_all
|
284
|
+
alias_method :destroy_all, :destroy_all_with_scout_instruments
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def update_all_with_scout_instruments(*args, &block)
|
289
|
+
model = self.name
|
290
|
+
|
291
|
+
req = ScoutApm::RequestManager.lookup
|
292
|
+
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName.new("", "#{model} Update"))
|
293
|
+
req.start_layer(layer)
|
294
|
+
req.ignore_children!
|
295
|
+
begin
|
296
|
+
update_all_without_scout_instruments(*args, &block)
|
297
|
+
ensure
|
298
|
+
req.acknowledge_children!
|
299
|
+
req.stop_layer
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def delete_all_with_scout_instruments(*args, &block)
|
304
|
+
model = self.name
|
305
|
+
|
306
|
+
req = ScoutApm::RequestManager.lookup
|
307
|
+
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName.new("", "#{model} Delete"))
|
308
|
+
req.start_layer(layer)
|
309
|
+
req.ignore_children!
|
310
|
+
begin
|
311
|
+
delete_all_without_scout_instruments(*args, &block)
|
312
|
+
ensure
|
313
|
+
req.acknowledge_children!
|
314
|
+
req.stop_layer
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def destroy_all_with_scout_instruments(*args, &block)
|
319
|
+
model = self.name
|
320
|
+
|
321
|
+
req = ScoutApm::RequestManager.lookup
|
322
|
+
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName.new("", "#{model} Delete"))
|
323
|
+
req.start_layer(layer)
|
324
|
+
req.ignore_children!
|
325
|
+
begin
|
326
|
+
destroy_all_without_scout_instruments(*args, &block)
|
327
|
+
ensure
|
328
|
+
req.acknowledge_children!
|
329
|
+
req.stop_layer
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
209
333
|
end
|
210
334
|
end
|
@@ -29,9 +29,10 @@ module ScoutApm
|
|
29
29
|
end
|
30
30
|
|
31
31
|
module GrapeEndpointInstruments
|
32
|
-
def run_with_scout_instruments
|
33
|
-
request = ::Grape::Request.new(env)
|
32
|
+
def run_with_scout_instruments(*args)
|
33
|
+
request = ::Grape::Request.new(env || args.first)
|
34
34
|
req = ScoutApm::RequestManager.lookup
|
35
|
+
|
35
36
|
path = ScoutApm::Agent.instance.config.value("uri_reporting") == 'path' ? request.path : request.fullpath
|
36
37
|
req.annotate_request(:uri => path)
|
37
38
|
|
@@ -55,7 +56,7 @@ module ScoutApm
|
|
55
56
|
|
56
57
|
req.start_layer( ScoutApm::Layer.new("Controller", name) )
|
57
58
|
begin
|
58
|
-
run_without_scout_instruments
|
59
|
+
run_without_scout_instruments(*args)
|
59
60
|
rescue
|
60
61
|
req.error!
|
61
62
|
raise
|
@@ -1,13 +1,11 @@
|
|
1
1
|
# Inserts a new middleware between each actual middleware in the application,
|
2
2
|
# so as to trace the time for each one.
|
3
3
|
#
|
4
|
-
# Currently disabled due to the overhead of this approach (~10-15ms
|
5
|
-
# in practice). Instead, middleware as a whole are instrumented
|
6
|
-
# MiddlewareSummary class.
|
4
|
+
# Currently disabled by default due to the overhead of this approach (~10-15ms
|
5
|
+
# per request in practice). Instead, middleware as a whole are instrumented
|
6
|
+
# via the MiddlewareSummary class.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
# summary tracing in a future version of the agent, but this is not yet
|
10
|
-
# implemented.
|
8
|
+
# Turn this on with the configuration setting `detailed_middleware` set to true
|
11
9
|
module ScoutApm
|
12
10
|
module Instruments
|
13
11
|
class MiddlewareDetailed
|
@@ -32,8 +32,8 @@ module ScoutApm
|
|
32
32
|
### See moped instrument for Moped driven deploys
|
33
33
|
|
34
34
|
### 5.x Mongoid
|
35
|
-
if mongoid_v5? && defined?(::Mongoid::Contextual::Mongo)
|
36
|
-
ScoutApm::Agent.instance.logger.info "Instrumenting Mongoid 5.x"
|
35
|
+
if (mongoid_v5? || mongoid_v6?) && defined?(::Mongoid::Contextual::Mongo)
|
36
|
+
ScoutApm::Agent.instance.logger.info "Instrumenting Mongoid 5.x/6.x"
|
37
37
|
# All the public methods from Mongoid::Contextual::Mongo.
|
38
38
|
# TODO: Geo and MapReduce support (?). They are in other Contextual::* classes
|
39
39
|
methods = [
|
@@ -50,11 +50,24 @@ module ScoutApm
|
|
50
50
|
with_scout_instruments = %Q[
|
51
51
|
def #{method}_with_scout_instruments(*args, &block)
|
52
52
|
|
53
|
+
|
53
54
|
req = ScoutApm::RequestManager.lookup
|
54
55
|
*db, collection = view.collection.namespace.split(".")
|
55
56
|
|
56
57
|
name = collection + "/#{method}"
|
57
|
-
|
58
|
+
|
59
|
+
# Between Mongo gem version 2.1 and 2.3, this method name was
|
60
|
+
# changed. Accomodate both. If for some reason neither is
|
61
|
+
# there, try to continue with an empty "filter" hash.
|
62
|
+
raw_filter = if view.respond_to?(:selector)
|
63
|
+
view.selector
|
64
|
+
elsif view.respond_to?(:filter)
|
65
|
+
view.filter
|
66
|
+
else
|
67
|
+
{}
|
68
|
+
end
|
69
|
+
|
70
|
+
filter = ScoutApm::Instruments::Mongoid.anonymize_filter(raw_filter)
|
58
71
|
|
59
72
|
layer = ScoutApm::Layer.new("MongoDB", name)
|
60
73
|
layer.desc = filter.inspect
|
@@ -86,6 +99,14 @@ module ScoutApm
|
|
86
99
|
end
|
87
100
|
end
|
88
101
|
|
102
|
+
def mongoid_v6?
|
103
|
+
if defined?(::Mongoid::VERSION)
|
104
|
+
::Mongoid::VERSION =~ /\A6/
|
105
|
+
else
|
106
|
+
false
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
89
110
|
|
90
111
|
# Example of what a filter looks like: => {"founded"=>{"$gte"=>"1980-1-1"}, "name"=>{"$in"=>["Tool", "Deftones", "Melvins"]}}
|
91
112
|
# Approach: find every leaf-node, clear it. inspect the whole thing when done.
|