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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.markdown +147 -2
  4. data/Guardfile +43 -0
  5. data/Rakefile +2 -2
  6. data/ext/allocations/allocations.c +6 -0
  7. data/ext/allocations/extconf.rb +1 -0
  8. data/ext/rusage/README.md +26 -0
  9. data/ext/rusage/extconf.rb +5 -0
  10. data/ext/rusage/rusage.c +52 -0
  11. data/lib/scout_apm.rb +28 -15
  12. data/lib/scout_apm/agent.rb +89 -37
  13. data/lib/scout_apm/agent/logging.rb +6 -1
  14. data/lib/scout_apm/agent/reporting.rb +9 -6
  15. data/lib/scout_apm/app_server_load.rb +21 -10
  16. data/lib/scout_apm/attribute_arranger.rb +6 -3
  17. data/lib/scout_apm/background_job_integrations/delayed_job.rb +71 -1
  18. data/lib/scout_apm/background_job_integrations/resque.rb +85 -0
  19. data/lib/scout_apm/background_job_integrations/sidekiq.rb +22 -20
  20. data/lib/scout_apm/background_recorder.rb +43 -0
  21. data/lib/scout_apm/background_worker.rb +19 -15
  22. data/lib/scout_apm/config.rb +138 -28
  23. data/lib/scout_apm/db_query_metric_set.rb +80 -0
  24. data/lib/scout_apm/db_query_metric_stats.rb +102 -0
  25. data/lib/scout_apm/debug.rb +37 -0
  26. data/lib/scout_apm/environment.rb +22 -15
  27. data/lib/scout_apm/git_revision.rb +51 -0
  28. data/lib/scout_apm/histogram.rb +11 -2
  29. data/lib/scout_apm/instant/assets/xmlhttp_instrumentation.html +2 -2
  30. data/lib/scout_apm/instant/middleware.rb +196 -54
  31. data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +89 -68
  32. data/lib/scout_apm/instruments/action_view.rb +49 -0
  33. data/lib/scout_apm/instruments/active_record.rb +127 -3
  34. data/lib/scout_apm/instruments/grape.rb +4 -3
  35. data/lib/scout_apm/instruments/middleware_detailed.rb +4 -6
  36. data/lib/scout_apm/instruments/mongoid.rb +24 -3
  37. data/lib/scout_apm/instruments/net_http.rb +7 -2
  38. data/lib/scout_apm/instruments/percentile_sampler.rb +36 -19
  39. data/lib/scout_apm/instruments/process/process_cpu.rb +3 -2
  40. data/lib/scout_apm/instruments/process/process_memory.rb +3 -3
  41. data/lib/scout_apm/instruments/resque.rb +40 -0
  42. data/lib/scout_apm/layaway.rb +67 -28
  43. data/lib/scout_apm/layer.rb +19 -59
  44. data/lib/scout_apm/layer_children_set.rb +77 -0
  45. data/lib/scout_apm/layer_converters/allocation_metric_converter.rb +5 -6
  46. data/lib/scout_apm/layer_converters/converter_base.rb +201 -14
  47. data/lib/scout_apm/layer_converters/database_converter.rb +55 -0
  48. data/lib/scout_apm/layer_converters/depth_first_walker.rb +22 -10
  49. data/lib/scout_apm/layer_converters/error_converter.rb +5 -7
  50. data/lib/scout_apm/layer_converters/find_layer_by_type.rb +34 -0
  51. data/lib/scout_apm/layer_converters/histograms.rb +14 -0
  52. data/lib/scout_apm/layer_converters/job_converter.rb +36 -50
  53. data/lib/scout_apm/layer_converters/metric_converter.rb +17 -19
  54. data/lib/scout_apm/layer_converters/request_queue_time_converter.rb +10 -12
  55. data/lib/scout_apm/layer_converters/slow_job_converter.rb +41 -115
  56. data/lib/scout_apm/layer_converters/slow_request_converter.rb +33 -117
  57. data/lib/scout_apm/limited_layer.rb +126 -0
  58. data/lib/scout_apm/metric_meta.rb +0 -5
  59. data/lib/scout_apm/metric_set.rb +9 -1
  60. data/lib/scout_apm/metric_stats.rb +7 -8
  61. data/lib/scout_apm/rack.rb +26 -0
  62. data/lib/scout_apm/remote/message.rb +23 -0
  63. data/lib/scout_apm/remote/recorder.rb +57 -0
  64. data/lib/scout_apm/remote/router.rb +49 -0
  65. data/lib/scout_apm/remote/server.rb +58 -0
  66. data/lib/scout_apm/reporter.rb +51 -15
  67. data/lib/scout_apm/request_histograms.rb +4 -0
  68. data/lib/scout_apm/request_manager.rb +2 -1
  69. data/lib/scout_apm/scored_item_set.rb +7 -0
  70. data/lib/scout_apm/serializers/db_query_serializer_to_json.rb +15 -0
  71. data/lib/scout_apm/serializers/histograms_serializer_to_json.rb +21 -0
  72. data/lib/scout_apm/serializers/payload_serializer.rb +10 -3
  73. data/lib/scout_apm/serializers/payload_serializer_to_json.rb +6 -6
  74. data/lib/scout_apm/serializers/slow_jobs_serializer_to_json.rb +2 -1
  75. data/lib/scout_apm/server_integrations/puma.rb +5 -2
  76. data/lib/scout_apm/slow_job_policy.rb +1 -10
  77. data/lib/scout_apm/slow_job_record.rb +6 -1
  78. data/lib/scout_apm/slow_request_policy.rb +1 -10
  79. data/lib/scout_apm/slow_transaction.rb +20 -2
  80. data/lib/scout_apm/store.rb +66 -12
  81. data/lib/scout_apm/synchronous_recorder.rb +26 -0
  82. data/lib/scout_apm/tracked_request.rb +136 -71
  83. data/lib/scout_apm/utils/active_record_metric_name.rb +8 -4
  84. data/lib/scout_apm/utils/backtrace_parser.rb +3 -3
  85. data/lib/scout_apm/utils/gzip_helper.rb +24 -0
  86. data/lib/scout_apm/utils/numbers.rb +14 -0
  87. data/lib/scout_apm/utils/scm.rb +14 -0
  88. data/lib/scout_apm/version.rb +1 -1
  89. data/scout_apm.gemspec +5 -4
  90. data/test/test_helper.rb +18 -0
  91. data/test/unit/config_test.rb +59 -8
  92. data/test/unit/db_query_metric_set_test.rb +56 -0
  93. data/test/unit/db_query_metric_stats_test.rb +113 -0
  94. data/test/unit/git_revision_test.rb +15 -0
  95. data/test/unit/histogram_test.rb +14 -0
  96. data/test/unit/instruments/net_http_test.rb +21 -0
  97. data/test/unit/instruments/percentile_sampler_test.rb +137 -0
  98. data/test/unit/layaway_test.rb +20 -0
  99. data/test/unit/layer_children_set_test.rb +88 -0
  100. data/test/unit/layer_converters/depth_first_walker_test.rb +66 -0
  101. data/test/unit/layer_converters/metric_converter_test.rb +22 -0
  102. data/test/unit/layer_converters/stubs.rb +33 -0
  103. data/test/unit/limited_layer_test.rb +53 -0
  104. data/test/unit/remote/test_message.rb +13 -0
  105. data/test/unit/remote/test_router.rb +33 -0
  106. data/test/unit/remote/test_server.rb +15 -0
  107. data/test/unit/serializers/payload_serializer_test.rb +3 -12
  108. data/test/unit/store_test.rb +66 -0
  109. data/test/unit/test_tracked_request.rb +87 -0
  110. data/test/unit/utils/active_record_metric_name_test.rb +8 -0
  111. data/test/unit/utils/backtrace_parser_test.rb +5 -0
  112. data/test/unit/utils/numbers_test.rb +15 -0
  113. data/test/unit/utils/scm.rb +17 -0
  114. metadata +125 -30
  115. data/ext/stacks/extconf.rb +0 -37
  116. data/ext/stacks/scout_atomics.h +0 -86
  117. data/ext/stacks/stacks.c +0 -811
  118. data/lib/scout_apm/capacity.rb +0 -57
  119. data/lib/scout_apm/deploy_integrations/capistrano_2.cap +0 -12
  120. data/lib/scout_apm/deploy_integrations/capistrano_2.rb +0 -83
  121. data/lib/scout_apm/deploy_integrations/capistrano_3.cap +0 -12
  122. data/lib/scout_apm/deploy_integrations/capistrano_3.rb +0 -88
  123. data/lib/scout_apm/instruments/delayed_job.rb +0 -57
  124. data/lib/scout_apm/serializers/deploy_serializer.rb +0 -16
  125. data/lib/scout_apm/trace_compactor.rb +0 -312
  126. data/lib/scout_apm/utils/fake_stacks.rb +0 -87
  127. 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) && defined?(::ActionController::Base)
24
- ScoutApm::Agent.instance.logger.info "Instrumenting ActionController::Base"
25
- ::ActionController::Base.class_eval do
26
- # include ScoutApm::Tracer
27
- include ScoutApm::Instruments::ActionControllerRails3Rails4Instruments
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
- instrument_method :render_partial,
38
- :type => "View",
39
- :name => '#{@template.virtual_path rescue "Unknown Partial"}/Rendering',
40
- :scope => true
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
- ScoutApm::Agent.instance.logger.info "Instrumenting ActionView::TemplateRenderer"
49
- ::ActionView::TemplateRenderer.class_eval do
50
- include ScoutApm::Tracer
51
- instrument_method :render_template,
52
- :type => "View",
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
- layer = ScoutApm::Layer.new("Controller", "#{controller_path}/#{action_name}")
79
-
80
- if ScoutApm::Agent.instance.config.value('profile')
81
- # Capture ScoutProf if we can
82
- req.enable_profiled_thread!
83
- layer.set_root_class(self.class)
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
- # Start the layer, then execute the user's code
88
- req.start_layer(layer)
89
- begin
90
- super
91
- rescue
92
- req.error!
93
- raise
94
- ensure
95
- req.stop_layer
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 # process_action
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
- end # ActionControllerRails3Rails4Instruments
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
- else
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(sql, name, &block)
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(sql, name, &block)
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 per request
5
- # in practice). Instead, middleware as a whole are instrumented via the
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
- # There will likely be a configuration flag to turn this on in favor of the
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
- filter = ScoutApm::Instruments::Mongoid.anonymize_filter(view.filter)
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.