scout_apm 3.0.0.pre27 → 4.0.3
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 +5 -5
- data/.github/workflows/test.yml +49 -0
- data/.gitignore +1 -1
- data/.rubocop.yml +5 -5
- data/.travis.yml +19 -14
- data/CHANGELOG.markdown +139 -4
- data/Gemfile +1 -7
- data/README.markdown +13 -4
- data/Rakefile +1 -1
- data/ext/allocations/allocations.c +2 -0
- data/gems/README.md +28 -0
- data/gems/octoshark.gemfile +4 -0
- data/gems/rails3.gemfile +5 -0
- data/gems/rails4.gemfile +4 -0
- data/gems/rails5.gemfile +4 -0
- data/gems/rails6.gemfile +4 -0
- data/lib/scout_apm.rb +38 -9
- data/lib/scout_apm/agent.rb +29 -10
- data/lib/scout_apm/agent/exit_handler.rb +0 -1
- data/lib/scout_apm/agent_context.rb +22 -3
- data/lib/scout_apm/app_server_load.rb +7 -2
- data/lib/scout_apm/attribute_arranger.rb +0 -2
- data/lib/scout_apm/auto_instrument.rb +5 -0
- data/lib/scout_apm/auto_instrument/instruction_sequence.rb +31 -0
- data/lib/scout_apm/auto_instrument/layer.rb +23 -0
- data/lib/scout_apm/auto_instrument/parser.rb +27 -0
- data/lib/scout_apm/auto_instrument/rails.rb +175 -0
- data/lib/scout_apm/background_job_integrations/legacy_sneakers.rb +55 -0
- data/lib/scout_apm/background_job_integrations/que.rb +134 -0
- data/lib/scout_apm/background_job_integrations/resque.rb +6 -2
- data/lib/scout_apm/background_job_integrations/shoryuken.rb +124 -0
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +5 -19
- data/lib/scout_apm/background_job_integrations/sneakers.rb +87 -0
- data/lib/scout_apm/config.rb +45 -8
- data/lib/scout_apm/detailed_trace.rb +217 -0
- data/lib/scout_apm/environment.rb +19 -1
- data/lib/scout_apm/error.rb +27 -0
- data/lib/scout_apm/error_service.rb +32 -0
- data/lib/scout_apm/error_service/error_buffer.rb +39 -0
- data/lib/scout_apm/error_service/error_record.rb +211 -0
- data/lib/scout_apm/error_service/ignored_exceptions.rb +66 -0
- data/lib/scout_apm/error_service/middleware.rb +32 -0
- data/lib/scout_apm/error_service/notifier.rb +33 -0
- data/lib/scout_apm/error_service/payload.rb +47 -0
- data/lib/scout_apm/error_service/periodic_work.rb +17 -0
- data/lib/scout_apm/error_service/railtie.rb +11 -0
- data/lib/scout_apm/error_service/sidekiq.rb +80 -0
- data/lib/scout_apm/extensions/transaction_callback_payload.rb +1 -1
- data/lib/scout_apm/fake_store.rb +3 -0
- data/lib/scout_apm/framework_integrations/rails_2.rb +2 -1
- data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +3 -1
- data/lib/scout_apm/git_revision.rb +6 -3
- data/lib/scout_apm/instant/middleware.rb +2 -1
- data/lib/scout_apm/instrument_manager.rb +9 -7
- data/lib/scout_apm/instruments/action_controller_rails_2.rb +3 -1
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +56 -55
- data/lib/scout_apm/instruments/action_view.rb +122 -26
- data/lib/scout_apm/instruments/active_record.rb +66 -18
- data/lib/scout_apm/instruments/http.rb +48 -0
- data/lib/scout_apm/instruments/memcached.rb +43 -0
- data/lib/scout_apm/instruments/mongoid.rb +9 -4
- data/lib/scout_apm/instruments/net_http.rb +8 -1
- data/lib/scout_apm/instruments/typhoeus.rb +88 -0
- data/lib/scout_apm/job_record.rb +4 -2
- data/lib/scout_apm/layaway_file.rb +4 -0
- data/lib/scout_apm/layer.rb +6 -57
- data/lib/scout_apm/layer_children_set.rb +9 -8
- data/lib/scout_apm/layer_converters/converter_base.rb +15 -30
- data/lib/scout_apm/layer_converters/slow_job_converter.rb +12 -2
- data/lib/scout_apm/layer_converters/slow_request_converter.rb +14 -4
- data/lib/scout_apm/layer_converters/trace_converter.rb +184 -0
- data/lib/scout_apm/limited_layer.rb +0 -7
- data/lib/scout_apm/metric_stats.rb +0 -8
- data/lib/scout_apm/middleware.rb +1 -1
- data/lib/scout_apm/periodic_work.rb +19 -0
- data/lib/scout_apm/remote/message.rb +4 -0
- data/lib/scout_apm/remote/server.rb +13 -1
- data/lib/scout_apm/reporter.rb +8 -3
- data/lib/scout_apm/reporting.rb +2 -1
- data/lib/scout_apm/request_histograms.rb +8 -0
- data/lib/scout_apm/serializers/app_server_load_serializer.rb +4 -0
- data/lib/scout_apm/serializers/directive_serializer.rb +4 -0
- data/lib/scout_apm/serializers/payload_serializer.rb +2 -2
- data/lib/scout_apm/serializers/payload_serializer_to_json.rb +30 -15
- data/lib/scout_apm/slow_job_record.rb +5 -1
- data/lib/scout_apm/slow_policy/age_policy.rb +33 -0
- data/lib/scout_apm/slow_policy/percent_policy.rb +22 -0
- data/lib/scout_apm/slow_policy/percentile_policy.rb +24 -0
- data/lib/scout_apm/slow_policy/policy.rb +21 -0
- data/lib/scout_apm/slow_policy/speed_policy.rb +16 -0
- data/lib/scout_apm/slow_request_policy.rb +18 -77
- data/lib/scout_apm/slow_transaction.rb +3 -1
- data/lib/scout_apm/store.rb +0 -1
- data/lib/scout_apm/tracked_request.rb +39 -30
- data/lib/scout_apm/utils/backtrace_parser.rb +3 -0
- data/lib/scout_apm/utils/marshal_logging.rb +90 -0
- data/lib/scout_apm/utils/sql_sanitizer.rb +10 -1
- data/lib/scout_apm/utils/sql_sanitizer_regex.rb +8 -1
- data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +6 -0
- data/lib/scout_apm/utils/unique_id.rb +27 -0
- data/lib/scout_apm/version.rb +1 -1
- data/scout_apm.gemspec +13 -7
- data/test/test_helper.rb +2 -2
- data/test/unit/agent_context_test.rb +29 -0
- data/test/unit/auto_instrument/assignments-instrumented.rb +31 -0
- data/test/unit/auto_instrument/assignments.rb +31 -0
- data/test/unit/auto_instrument/controller-ast.txt +57 -0
- data/test/unit/auto_instrument/controller-instrumented.rb +49 -0
- data/test/unit/auto_instrument/controller.rb +49 -0
- data/test/unit/auto_instrument/rescue_from-instrumented.rb +13 -0
- data/test/unit/auto_instrument/rescue_from.rb +13 -0
- data/test/unit/auto_instrument_test.rb +54 -0
- data/test/unit/environment_test.rb +2 -2
- data/test/unit/error_service/error_buffer_test.rb +25 -0
- data/test/unit/error_service/ignored_exceptions_test.rb +49 -0
- data/test/unit/instruments/active_record_test.rb +40 -0
- data/test/unit/layer_children_set_test.rb +9 -0
- data/test/unit/request_histograms_test.rb +17 -0
- data/test/unit/serializers/payload_serializer_test.rb +39 -5
- data/test/unit/slow_request_policy_test.rb +41 -13
- data/test/unit/sql_sanitizer_test.rb +78 -0
- metadata +101 -62
- data/ext/stacks/extconf.rb +0 -37
- data/ext/stacks/scout_atomics.h +0 -86
- data/ext/stacks/stacks.c +0 -814
- data/lib/scout_apm/slow_job_policy.rb +0 -111
- data/lib/scout_apm/trace_compactor.rb +0 -312
- data/lib/scout_apm/utils/fake_stacks.rb +0 -88
- data/test/unit/instruments/active_record_instruments_test.rb +0 -5
- data/test/unit/slow_job_policy_test.rb +0 -6
- data/tester.rb +0 -53
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
# Note, this instrument has the same logic in both Tracer and Module Prepend
|
|
2
|
+
# versions. If you update, be sure you update in both spots.
|
|
3
|
+
#
|
|
4
|
+
# The prepend version was added for Rails 6 support - ActiveRecord prepends on
|
|
5
|
+
# top of PartialRenderer#collection_with_template, which can (and does) cause
|
|
6
|
+
# infinite loops with our alias_method approach.
|
|
7
|
+
#
|
|
8
|
+
# Even though Rails 6 forced us to use a prepend version, it is now used for
|
|
9
|
+
# all Rubies that support it.
|
|
1
10
|
module ScoutApm
|
|
2
11
|
module Instruments
|
|
3
|
-
# instrumentation for Rails 3 and Rails 4 is the same.
|
|
4
12
|
class ActionView
|
|
5
13
|
attr_reader :context
|
|
6
14
|
|
|
@@ -17,37 +25,125 @@ module ScoutApm
|
|
|
17
25
|
@installed
|
|
18
26
|
end
|
|
19
27
|
|
|
28
|
+
def prependable?
|
|
29
|
+
context.environment.supports_module_prepend?
|
|
30
|
+
end
|
|
31
|
+
|
|
20
32
|
def install
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
return unless defined?(::ActionView) && defined?(::ActionView::PartialRenderer)
|
|
34
|
+
|
|
35
|
+
if prependable?
|
|
36
|
+
install_using_prepend
|
|
37
|
+
else
|
|
38
|
+
install_using_tracer
|
|
39
|
+
end
|
|
40
|
+
@installed = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def install_using_tracer
|
|
44
|
+
logger.info "Instrumenting ActionView::PartialRenderer"
|
|
45
|
+
::ActionView::PartialRenderer.class_eval do
|
|
46
|
+
include ScoutApm::Tracer
|
|
47
|
+
|
|
48
|
+
instrument_method :render_partial,
|
|
49
|
+
:type => "View",
|
|
50
|
+
:name => '#{@template.virtual_path rescue "Unknown Partial"}/Rendering',
|
|
51
|
+
:scope => true
|
|
52
|
+
|
|
53
|
+
instrument_method :collection_with_template,
|
|
54
|
+
:type => "View",
|
|
55
|
+
:name => '#{@template.virtual_path rescue "Unknown Collection"}/Rendering',
|
|
56
|
+
:scope => true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
logger.info "Instrumenting ActionView::TemplateRenderer"
|
|
60
|
+
::ActionView::TemplateRenderer.class_eval do
|
|
61
|
+
include ScoutApm::Tracer
|
|
62
|
+
instrument_method :render_template,
|
|
63
|
+
:type => "View",
|
|
64
|
+
:name => '#{args[0].virtual_path rescue "Unknown"}/Rendering',
|
|
65
|
+
:scope => true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def install_using_prepend
|
|
70
|
+
logger.info "Instrumenting ActionView::PartialRenderer"
|
|
71
|
+
::ActionView::PartialRenderer.prepend(ActionViewPartialRendererInstruments)
|
|
72
|
+
|
|
73
|
+
logger.info "Instrumenting ActionView::TemplateRenderer"
|
|
74
|
+
::ActionView::TemplateRenderer.prepend(ActionViewTemplateRendererInstruments)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
module ActionViewPartialRendererInstruments
|
|
78
|
+
# In Rails 6, the signature changed to pass the view & template args directly, as opposed to through the instance var
|
|
79
|
+
# New signature is: def render_partial(view, template)
|
|
80
|
+
def render_partial(*args, **kwargs)
|
|
81
|
+
req = ScoutApm::RequestManager.lookup
|
|
82
|
+
|
|
83
|
+
maybe_template = args[1]
|
|
84
|
+
|
|
85
|
+
template_name = @template.virtual_path rescue nil # Works on Rails 3.2 -> end of Rails 5 series
|
|
86
|
+
template_name ||= maybe_template.virtual_path rescue nil # Works on Rails 6 -> 6.0.3
|
|
87
|
+
template_name ||= "Unknown Partial"
|
|
88
|
+
|
|
89
|
+
layer_name = template_name + "/Rendering"
|
|
90
|
+
layer = ScoutApm::Layer.new("View", layer_name)
|
|
91
|
+
layer.subscopable!
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
req.start_layer(layer)
|
|
95
|
+
if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
|
|
96
|
+
super(*args, **kwargs)
|
|
97
|
+
else
|
|
98
|
+
super(*args)
|
|
99
|
+
end
|
|
100
|
+
ensure
|
|
101
|
+
req.stop_layer
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def collection_with_template(*args, **kwargs)
|
|
106
|
+
req = ScoutApm::RequestManager.lookup
|
|
107
|
+
|
|
108
|
+
template_name = @template.virtual_path rescue "Unknown Collection"
|
|
109
|
+
template_name ||= "Unknown Collection"
|
|
110
|
+
layer_name = template_name + "/Rendering"
|
|
111
|
+
|
|
112
|
+
layer = ScoutApm::Layer.new("View", layer_name)
|
|
113
|
+
layer.subscopable!
|
|
114
|
+
|
|
115
|
+
begin
|
|
116
|
+
req.start_layer(layer)
|
|
117
|
+
if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
|
|
118
|
+
super(*args, **kwargs)
|
|
119
|
+
else
|
|
120
|
+
super(*args)
|
|
121
|
+
end
|
|
122
|
+
ensure
|
|
123
|
+
req.stop_layer
|
|
37
124
|
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
module ActionViewTemplateRendererInstruments
|
|
129
|
+
def render_template(*args, **kwargs)
|
|
130
|
+
req = ScoutApm::RequestManager.lookup
|
|
38
131
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
132
|
+
template_name = args[0].virtual_path rescue "Unknown"
|
|
133
|
+
template_name ||= "Unknown"
|
|
134
|
+
layer_name = template_name + "/Rendering"
|
|
135
|
+
|
|
136
|
+
layer = ScoutApm::Layer.new("View", layer_name)
|
|
137
|
+
layer.subscopable!
|
|
138
|
+
|
|
139
|
+
begin
|
|
140
|
+
req.start_layer(layer)
|
|
141
|
+
super(*args, **kwargs)
|
|
142
|
+
ensure
|
|
143
|
+
req.stop_layer
|
|
46
144
|
end
|
|
47
145
|
end
|
|
48
146
|
end
|
|
49
147
|
end
|
|
50
148
|
end
|
|
51
149
|
end
|
|
52
|
-
|
|
53
|
-
|
|
@@ -82,10 +82,8 @@ module ScoutApm
|
|
|
82
82
|
|
|
83
83
|
# Install #log tracing
|
|
84
84
|
if Utils::KlassHelper.defined?("ActiveRecord::ConnectionAdapters::AbstractAdapter")
|
|
85
|
-
::ActiveRecord::ConnectionAdapters::AbstractAdapter.
|
|
86
|
-
|
|
87
|
-
include ::ScoutApm::Tracer
|
|
88
|
-
end
|
|
85
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecordInstruments)
|
|
86
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(Tracer)
|
|
89
87
|
end
|
|
90
88
|
|
|
91
89
|
if Utils::KlassHelper.defined?("ActiveRecord::Base")
|
|
@@ -168,17 +166,63 @@ module ScoutApm
|
|
|
168
166
|
#
|
|
169
167
|
################################################################################
|
|
170
168
|
module ActiveRecordInstruments
|
|
171
|
-
def self.
|
|
169
|
+
def self.prepended(instrumented_class)
|
|
172
170
|
ScoutApm::Agent.instance.context.logger.info "Instrumenting #{instrumented_class.inspect}"
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def log(*args, &block)
|
|
174
|
+
# Extract data from the arguments
|
|
175
|
+
sql, name = args
|
|
176
|
+
metric_name = Utils::ActiveRecordMetricName.new(sql, name)
|
|
177
|
+
desc = SqlList.new(sql)
|
|
178
|
+
|
|
179
|
+
# Get current ScoutApm context
|
|
180
|
+
req = ScoutApm::RequestManager.lookup
|
|
181
|
+
current_layer = req.current_layer
|
|
182
|
+
|
|
183
|
+
# If we call #log, we have a real query to run, and we've already
|
|
184
|
+
# gotten through the cache gatekeeper. Since we want to only trace real
|
|
185
|
+
# queries, and not repeated identical queries that just hit cache, we
|
|
186
|
+
# mark layer as ignorable initially in #find_by_sql, then only when we
|
|
187
|
+
# know it's a real database call do we mark it back as usable.
|
|
188
|
+
#
|
|
189
|
+
# This flag is later used in SlowRequestConverter to skip adding ignorable layers
|
|
190
|
+
current_layer.annotate_layer(:ignorable => false) if current_layer
|
|
191
|
+
|
|
192
|
+
# Either: update the current layer and yield, don't start a new one.
|
|
193
|
+
if current_layer && current_layer.type == "ActiveRecord"
|
|
194
|
+
# TODO: Get rid of call .to_s, need to find this without forcing a previous run of the name logic
|
|
195
|
+
if current_layer.name.to_s == Utils::ActiveRecordMetricName::DEFAULT_METRIC
|
|
196
|
+
current_layer.name = metric_name
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
if current_layer.desc.nil?
|
|
200
|
+
current_layer.desc = SqlList.new
|
|
201
|
+
end
|
|
202
|
+
current_layer.desc.merge(desc)
|
|
203
|
+
|
|
204
|
+
super(*args, &block)
|
|
205
|
+
|
|
206
|
+
# OR: Start a new layer, we didn't pick up instrumentation earlier in the stack.
|
|
207
|
+
else
|
|
208
|
+
layer = ScoutApm::Layer.new("ActiveRecord", metric_name)
|
|
209
|
+
layer.desc = desc
|
|
210
|
+
req.start_layer(layer)
|
|
211
|
+
begin
|
|
212
|
+
super(*args, &block)
|
|
213
|
+
ensure
|
|
214
|
+
req.stop_layer
|
|
177
215
|
end
|
|
178
216
|
end
|
|
179
217
|
end
|
|
218
|
+
end
|
|
180
219
|
|
|
181
|
-
|
|
220
|
+
module ActiveRecordInstruments
|
|
221
|
+
def self.prepended(instrumented_class)
|
|
222
|
+
ScoutApm::Agent.instance.context.logger.info "Instrumenting #{instrumented_class.inspect}"
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def log(*args, &block)
|
|
182
226
|
# Extract data from the arguments
|
|
183
227
|
sql, name = args
|
|
184
228
|
metric_name = Utils::ActiveRecordMetricName.new(sql, name)
|
|
@@ -209,7 +253,7 @@ module ScoutApm
|
|
|
209
253
|
end
|
|
210
254
|
current_layer.desc.merge(desc)
|
|
211
255
|
|
|
212
|
-
|
|
256
|
+
super(*args, &block)
|
|
213
257
|
|
|
214
258
|
# OR: Start a new layer, we didn't pick up instrumentation earlier in the stack.
|
|
215
259
|
else
|
|
@@ -217,7 +261,7 @@ module ScoutApm
|
|
|
217
261
|
layer.desc = desc
|
|
218
262
|
req.start_layer(layer)
|
|
219
263
|
begin
|
|
220
|
-
|
|
264
|
+
super(*args, &block)
|
|
221
265
|
ensure
|
|
222
266
|
req.stop_layer
|
|
223
267
|
end
|
|
@@ -264,14 +308,18 @@ module ScoutApm
|
|
|
264
308
|
end
|
|
265
309
|
end
|
|
266
310
|
|
|
267
|
-
def find_by_sql_with_scout_instruments(*args, &block)
|
|
311
|
+
def find_by_sql_with_scout_instruments(*args, **kwargs, &block)
|
|
268
312
|
req = ScoutApm::RequestManager.lookup
|
|
269
313
|
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName::DEFAULT_METRIC)
|
|
270
314
|
layer.annotate_layer(:ignorable => true)
|
|
271
315
|
req.start_layer(layer)
|
|
272
316
|
req.ignore_children!
|
|
273
317
|
begin
|
|
274
|
-
|
|
318
|
+
if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
|
|
319
|
+
find_by_sql_without_scout_instruments(*args, **kwargs, &block)
|
|
320
|
+
else
|
|
321
|
+
find_by_sql_without_scout_instruments(*args, &block)
|
|
322
|
+
end
|
|
275
323
|
ensure
|
|
276
324
|
req.acknowledge_children!
|
|
277
325
|
req.stop_layer
|
|
@@ -349,7 +397,7 @@ module ScoutApm
|
|
|
349
397
|
end
|
|
350
398
|
|
|
351
399
|
module ActiveRecordUpdateInstruments
|
|
352
|
-
def save(*args, &block)
|
|
400
|
+
def save(*args, **options, &block)
|
|
353
401
|
model = self.class.name
|
|
354
402
|
operation = self.persisted? ? "Update" : "Create"
|
|
355
403
|
|
|
@@ -359,14 +407,14 @@ module ScoutApm
|
|
|
359
407
|
req.start_layer(layer)
|
|
360
408
|
req.ignore_children!
|
|
361
409
|
begin
|
|
362
|
-
super(*args, &block)
|
|
410
|
+
super(*args, **options, &block)
|
|
363
411
|
ensure
|
|
364
412
|
req.acknowledge_children!
|
|
365
413
|
req.stop_layer
|
|
366
414
|
end
|
|
367
415
|
end
|
|
368
416
|
|
|
369
|
-
def save!(*args, &block)
|
|
417
|
+
def save!(*args, **options, &block)
|
|
370
418
|
model = self.class.name
|
|
371
419
|
operation = self.persisted? ? "Update" : "Create"
|
|
372
420
|
|
|
@@ -375,7 +423,7 @@ module ScoutApm
|
|
|
375
423
|
req.start_layer(layer)
|
|
376
424
|
req.ignore_children!
|
|
377
425
|
begin
|
|
378
|
-
super(*args, &block)
|
|
426
|
+
super(*args, **options, &block)
|
|
379
427
|
ensure
|
|
380
428
|
req.acknowledge_children!
|
|
381
429
|
req.stop_layer
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module ScoutApm
|
|
2
|
+
module Instruments
|
|
3
|
+
class HTTP
|
|
4
|
+
attr_reader :context
|
|
5
|
+
|
|
6
|
+
def initialize(context)
|
|
7
|
+
@context = context
|
|
8
|
+
@installed = false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def logger
|
|
12
|
+
context.logger
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def installed?
|
|
16
|
+
@installed
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def install
|
|
20
|
+
if defined?(::HTTP) && defined?(::HTTP::Client)
|
|
21
|
+
@installed = true
|
|
22
|
+
|
|
23
|
+
logger.info "Instrumenting HTTP::Client"
|
|
24
|
+
|
|
25
|
+
::HTTP::Client.class_eval do
|
|
26
|
+
include ScoutApm::Tracer
|
|
27
|
+
|
|
28
|
+
def request_with_scout_instruments(verb, uri, opts = {})
|
|
29
|
+
self.class.instrument("HTTP", verb, :ignore_children => true, :desc => request_scout_description(verb, uri)) do
|
|
30
|
+
request_without_scout_instruments(verb, uri, opts)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def request_scout_description(verb, uri)
|
|
35
|
+
max_length = ScoutApm::Agent.instance.context.config.value('instrument_http_url_length')
|
|
36
|
+
(String(uri).split('?').first)[0..(max_length - 1)]
|
|
37
|
+
rescue
|
|
38
|
+
""
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
alias request_without_scout_instruments request
|
|
42
|
+
alias request request_with_scout_instruments
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module ScoutApm
|
|
2
|
+
module Instruments
|
|
3
|
+
class Memcached
|
|
4
|
+
attr_reader :context
|
|
5
|
+
|
|
6
|
+
def initialize(context)
|
|
7
|
+
@context = context
|
|
8
|
+
@installed = false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def logger
|
|
12
|
+
context.logger
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def installed?
|
|
16
|
+
@installed
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def install
|
|
20
|
+
if defined?(::Dalli) && defined?(::Dalli::Client)
|
|
21
|
+
@installed = true
|
|
22
|
+
|
|
23
|
+
logger.info "Instrumenting Memcached"
|
|
24
|
+
|
|
25
|
+
::Dalli::Client.class_eval do
|
|
26
|
+
include ScoutApm::Tracer
|
|
27
|
+
|
|
28
|
+
def perform_with_scout_instruments(*args, &block)
|
|
29
|
+
command = args.first rescue "Unknown"
|
|
30
|
+
|
|
31
|
+
self.class.instrument("Memcached", command) do
|
|
32
|
+
perform_without_scout_instruments(*args, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
alias_method :perform_without_scout_instruments, :perform
|
|
37
|
+
alias_method :perform, :perform_with_scout_instruments
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -37,8 +37,8 @@ module ScoutApm
|
|
|
37
37
|
### See moped instrument for Moped driven deploys
|
|
38
38
|
|
|
39
39
|
### 5.x Mongoid
|
|
40
|
-
if (mongoid_v5? || mongoid_v6?) && defined?(::Mongoid::Contextual::Mongo)
|
|
41
|
-
logger.info "Instrumenting Mongoid 5.x/6.x"
|
|
40
|
+
if (mongoid_v5? || mongoid_v6? || mongoid_v7?) && defined?(::Mongoid::Contextual::Mongo)
|
|
41
|
+
logger.info "Instrumenting Mongoid 5.x/6.x/7.x"
|
|
42
42
|
# All the public methods from Mongoid::Contextual::Mongo.
|
|
43
43
|
# TODO: Geo and MapReduce support (?). They are in other Contextual::* classes
|
|
44
44
|
methods = [
|
|
@@ -54,8 +54,6 @@ module ScoutApm
|
|
|
54
54
|
if ::Mongoid::Contextual::Mongo.method_defined?(method)
|
|
55
55
|
with_scout_instruments = %Q[
|
|
56
56
|
def #{method}_with_scout_instruments(*args, &block)
|
|
57
|
-
|
|
58
|
-
|
|
59
57
|
req = ScoutApm::RequestManager.lookup
|
|
60
58
|
*db, collection = view.collection.namespace.split(".")
|
|
61
59
|
|
|
@@ -112,6 +110,13 @@ module ScoutApm
|
|
|
112
110
|
end
|
|
113
111
|
end
|
|
114
112
|
|
|
113
|
+
def mongoid_v7?
|
|
114
|
+
if defined?(::Mongoid::VERSION)
|
|
115
|
+
::Mongoid::VERSION =~ /\A7/
|
|
116
|
+
else
|
|
117
|
+
false
|
|
118
|
+
end
|
|
119
|
+
end
|
|
115
120
|
|
|
116
121
|
# Example of what a filter looks like: => {"founded"=>{"$gte"=>"1980-1-1"}, "name"=>{"$in"=>["Tool", "Deftones", "Melvins"]}}
|
|
117
122
|
# Approach: find every leaf-node, clear it. inspect the whole thing when done.
|
|
@@ -25,7 +25,7 @@ module ScoutApm
|
|
|
25
25
|
::Net::HTTP.class_eval do
|
|
26
26
|
include ScoutApm::Tracer
|
|
27
27
|
|
|
28
|
-
def request_with_scout_instruments(*args
|
|
28
|
+
def request_with_scout_instruments(*args, &block)
|
|
29
29
|
self.class.instrument("HTTP", "request", :ignore_children => true, :desc => request_scout_description(args.first)) do
|
|
30
30
|
request_without_scout_instruments(*args, &block)
|
|
31
31
|
end
|
|
@@ -35,8 +35,15 @@ module ScoutApm
|
|
|
35
35
|
path = req.path
|
|
36
36
|
path = path.path if path.respond_to?(:path)
|
|
37
37
|
|
|
38
|
+
# Protect against a nil address value
|
|
39
|
+
if @address.nil?
|
|
40
|
+
return "No Address Found"
|
|
41
|
+
end
|
|
42
|
+
|
|
38
43
|
max_length = ScoutApm::Agent.instance.context.config.value('instrument_http_url_length')
|
|
39
44
|
(@address + path.split('?').first)[0..(max_length - 1)]
|
|
45
|
+
rescue
|
|
46
|
+
""
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
alias request_without_scout_instruments request
|