scout_apm 2.6.6 → 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 +4 -4
- data/.github/workflows/test.yml +49 -0
- data/.rubocop.yml +2 -5
- data/.travis.yml +3 -7
- data/CHANGELOG.markdown +45 -0
- data/Gemfile +1 -8
- data/gems/rails6.gemfile +1 -1
- data/lib/scout_apm.rb +22 -1
- data/lib/scout_apm/agent.rb +22 -0
- data/lib/scout_apm/agent_context.rb +14 -2
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +2 -2
- data/lib/scout_apm/config.rb +17 -2
- data/lib/scout_apm/detailed_trace.rb +2 -1
- data/lib/scout_apm/environment.rb +16 -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/instrument_manager.rb +1 -0
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +47 -26
- data/lib/scout_apm/instruments/action_view.rb +21 -8
- data/lib/scout_apm/instruments/active_record.rb +17 -28
- data/lib/scout_apm/instruments/typhoeus.rb +88 -0
- data/lib/scout_apm/layer.rb +1 -1
- data/lib/scout_apm/middleware.rb +1 -1
- data/lib/scout_apm/remote/server.rb +13 -1
- data/lib/scout_apm/reporter.rb +8 -3
- data/lib/scout_apm/serializers/payload_serializer_to_json.rb +28 -10
- 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/utils/sql_sanitizer.rb +1 -0
- data/lib/scout_apm/utils/sql_sanitizer_regex.rb +3 -3
- data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +1 -0
- data/lib/scout_apm/version.rb +1 -1
- data/scout_apm.gemspec +6 -6
- data/test/unit/agent_context_test.rb +29 -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/serializers/payload_serializer_test.rb +36 -0
- data/test/unit/slow_request_policy_test.rb +41 -13
- data/test/unit/sql_sanitizer_test.rb +38 -0
- metadata +26 -61
- data/lib/scout_apm/slow_job_policy.rb +0 -111
- data/test/unit/slow_job_policy_test.rb +0 -6
@@ -0,0 +1,11 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module ErrorService
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
initializer "scoutapm_error_service.middleware" do |app|
|
5
|
+
next if ScoutApm::Agent.instance.config.value("error_service")
|
6
|
+
|
7
|
+
app.config.middleware.insert_after ActionDispatch::DebugExceptions, ScoutApm::ErrorService::Rack
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module ErrorService
|
3
|
+
class Sidekiq
|
4
|
+
def initialize
|
5
|
+
@context = ScoutApm::Agent.instance.context
|
6
|
+
end
|
7
|
+
|
8
|
+
def install
|
9
|
+
return false unless defined?(::Sidekiq)
|
10
|
+
|
11
|
+
if ::Sidekiq::VERSION < "3"
|
12
|
+
install_sidekiq_with_middleware
|
13
|
+
else
|
14
|
+
install_sidekiq_with_error_handler
|
15
|
+
end
|
16
|
+
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def install_sidekiq_with_middleware
|
21
|
+
# old behavior
|
22
|
+
::Sidekiq.configure_server do |config|
|
23
|
+
config.server_middleware do |chain|
|
24
|
+
chain.add ScoutApm::ErrorService::Sidekiq::SidekiqExceptionMiddleware
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def install_sidekiq_with_error_handler
|
30
|
+
::Sidekiq.configure_server do |config|
|
31
|
+
config.error_handlers << proc { |exception, job_info|
|
32
|
+
context = ScoutApm::Agent.instance.context
|
33
|
+
|
34
|
+
# Bail out early, and reraise if the error is not interesting.
|
35
|
+
if context.ignored_exceptions.ignored?(exception)
|
36
|
+
raise
|
37
|
+
end
|
38
|
+
|
39
|
+
job_class =
|
40
|
+
begin
|
41
|
+
job_class = job_info[:job]["class"]
|
42
|
+
job_class = job_info[:job]["args"][0]["job_class"] if job_class == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
43
|
+
job_class
|
44
|
+
rescue
|
45
|
+
"UnknownJob"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Capture the error for further processing and shipping
|
49
|
+
context.error_buffer.capture(exception, job_info.merge(:custom_controller => job_class))
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class SidekiqExceptionMiddleware
|
55
|
+
def call(worker, msg, queue)
|
56
|
+
yield
|
57
|
+
rescue => exception
|
58
|
+
context = ScoutApm::Agent.instance.context
|
59
|
+
|
60
|
+
# Bail out early, and reraise if the error is not interesting.
|
61
|
+
if context.ignored_exceptions.ignored?(exception)
|
62
|
+
raise
|
63
|
+
end
|
64
|
+
|
65
|
+
# Capture the error for further processing and shipping
|
66
|
+
context.error_buffer.capture(
|
67
|
+
exception,
|
68
|
+
{
|
69
|
+
:custom_params => msg,
|
70
|
+
:custom_controller => msg["class"]
|
71
|
+
}
|
72
|
+
)
|
73
|
+
|
74
|
+
# Finally, reraise
|
75
|
+
raise exception
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -26,7 +26,7 @@ module ScoutApm
|
|
26
26
|
# The time in queue of the transaction in ms. If not present, +nil+ is returned as this is unknown.
|
27
27
|
def queue_time_ms
|
28
28
|
# Controller logic
|
29
|
-
if converter_results[:queue_time] && converter_results[:
|
29
|
+
if converter_results[:queue_time] && converter_results[:queue_time].any?
|
30
30
|
converter_results[:queue_time].values.first.total_call_time*1000 # ms
|
31
31
|
# Job logic
|
32
32
|
elsif converter_results[:job]
|
@@ -30,6 +30,7 @@ module ScoutApm
|
|
30
30
|
install_instrument(ScoutApm::Instruments::Moped)
|
31
31
|
install_instrument(ScoutApm::Instruments::Mongoid)
|
32
32
|
install_instrument(ScoutApm::Instruments::NetHttp)
|
33
|
+
install_instrument(ScoutApm::Instruments::Typhoeus)
|
33
34
|
install_instrument(ScoutApm::Instruments::HttpClient)
|
34
35
|
install_instrument(ScoutApm::Instruments::Memcached)
|
35
36
|
install_instrument(ScoutApm::Instruments::Redis)
|
@@ -17,46 +17,73 @@ module ScoutApm
|
|
17
17
|
@installed
|
18
18
|
end
|
19
19
|
|
20
|
+
def installed!
|
21
|
+
@installed = true
|
22
|
+
end
|
23
|
+
|
20
24
|
def install
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
if !defined?(::ActiveSupport)
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
# The block below runs with `self` equal to the ActionController::Base or ::API module, not this class we're in now. By saving an instance of ourselves into the `this` variable, we can continue accessing what we need.
|
30
|
+
this = self
|
27
31
|
|
32
|
+
ActiveSupport.on_load(:action_controller) do
|
33
|
+
if this.installed?
|
34
|
+
this.logger.info("Skipping ActionController - Already Ran")
|
35
|
+
next
|
36
|
+
else
|
37
|
+
this.logger.info("Instrumenting ActionController (on_load)")
|
38
|
+
this.installed!
|
39
|
+
end
|
40
|
+
|
41
|
+
# We previously instrumented ActionController::Metal, which missed
|
42
|
+
# before and after filter timing. Instrumenting Base includes those
|
43
|
+
# filters, at the expense of missing out on controllers that don't use
|
44
|
+
# the full Rails stack.
|
28
45
|
if defined?(::ActionController::Base)
|
29
|
-
logger.info "Instrumenting ActionController::Base"
|
46
|
+
this.logger.info "Instrumenting ActionController::Base"
|
30
47
|
::ActionController::Base.class_eval do
|
31
|
-
# include ScoutApm::Tracer
|
32
48
|
include ScoutApm::Instruments::ActionControllerBaseInstruments
|
33
49
|
end
|
34
50
|
end
|
35
51
|
|
36
52
|
if defined?(::ActionController::Metal)
|
37
|
-
logger.info "Instrumenting ActionController::Metal"
|
53
|
+
this.logger.info "Instrumenting ActionController::Metal"
|
38
54
|
::ActionController::Metal.class_eval do
|
39
55
|
include ScoutApm::Instruments::ActionControllerMetalInstruments
|
40
56
|
end
|
41
57
|
end
|
42
58
|
|
43
59
|
if defined?(::ActionController::API)
|
44
|
-
logger.info "Instrumenting ActionController::Api"
|
60
|
+
this.logger.info "Instrumenting ActionController::Api"
|
45
61
|
::ActionController::API.class_eval do
|
46
62
|
include ScoutApm::Instruments::ActionControllerAPIInstruments
|
47
63
|
end
|
48
64
|
end
|
49
65
|
end
|
50
66
|
|
51
|
-
|
52
|
-
# we can insert this multiple times into the ancestors
|
53
|
-
# stack. Otherwise it only exists the first time you include it
|
54
|
-
# (under Metal, instead of under API) and we miss instrumenting
|
55
|
-
# before_action callbacks
|
67
|
+
ScoutApm::Agent.instance.context.logger.info("Instrumenting ActionController (hook installed)")
|
56
68
|
end
|
57
69
|
|
70
|
+
# Returns a new anonymous module each time it is called. So
|
71
|
+
# we can insert this multiple times into the ancestors
|
72
|
+
# stack. Otherwise it only exists the first time you include it
|
73
|
+
# (under Metal, instead of under API) and we miss instrumenting
|
74
|
+
# before_action callbacks
|
58
75
|
def self.build_instrument_module
|
59
76
|
Module.new do
|
77
|
+
# Determine the URI of this request to capture. Overridable by users in their controller.
|
78
|
+
def scout_transaction_uri(config=ScoutApm::Agent.instance.context.config)
|
79
|
+
case config.value("uri_reporting")
|
80
|
+
when 'path'
|
81
|
+
request.path # strips off the query string for more security
|
82
|
+
else # default handles filtered params
|
83
|
+
request.filtered_path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
60
87
|
def process_action(*args)
|
61
88
|
req = ScoutApm::RequestManager.lookup
|
62
89
|
current_layer = req.current_layer
|
@@ -72,7 +99,11 @@ module ScoutApm
|
|
72
99
|
# Don't start a new layer if ActionController::API or ActionController::Base handled it already.
|
73
100
|
super
|
74
101
|
else
|
75
|
-
|
102
|
+
begin
|
103
|
+
uri = scout_transaction_uri
|
104
|
+
req.annotate_request(:uri => uri)
|
105
|
+
rescue
|
106
|
+
end
|
76
107
|
|
77
108
|
# IP Spoofing Protection can throw an exception, just move on w/o remote ip
|
78
109
|
if agent_context.config.value('collect_remote_ip')
|
@@ -95,16 +126,6 @@ module ScoutApm
|
|
95
126
|
end
|
96
127
|
end
|
97
128
|
|
98
|
-
# Given an +ActionDispatch::Request+, formats the uri based on config settings.
|
99
|
-
# XXX: Don't lookup context like this - find a way to pass it through
|
100
|
-
def self.scout_transaction_uri(request, config=ScoutApm::Agent.instance.context.config)
|
101
|
-
case config.value("uri_reporting")
|
102
|
-
when 'path'
|
103
|
-
request.path # strips off the query string for more security
|
104
|
-
else # default handles filtered params
|
105
|
-
request.filtered_path
|
106
|
-
end
|
107
|
-
end
|
108
129
|
end
|
109
130
|
|
110
131
|
module ActionControllerMetalInstruments
|
@@ -75,25 +75,34 @@ module ScoutApm
|
|
75
75
|
end
|
76
76
|
|
77
77
|
module ActionViewPartialRendererInstruments
|
78
|
-
|
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)
|
79
81
|
req = ScoutApm::RequestManager.lookup
|
80
82
|
|
81
|
-
|
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
|
82
87
|
template_name ||= "Unknown Partial"
|
83
|
-
layer_name = template_name + "/Rendering"
|
84
88
|
|
89
|
+
layer_name = template_name + "/Rendering"
|
85
90
|
layer = ScoutApm::Layer.new("View", layer_name)
|
86
91
|
layer.subscopable!
|
87
92
|
|
88
93
|
begin
|
89
94
|
req.start_layer(layer)
|
90
|
-
|
95
|
+
if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
|
96
|
+
super(*args, **kwargs)
|
97
|
+
else
|
98
|
+
super(*args)
|
99
|
+
end
|
91
100
|
ensure
|
92
101
|
req.stop_layer
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
96
|
-
def collection_with_template(*args)
|
105
|
+
def collection_with_template(*args, **kwargs)
|
97
106
|
req = ScoutApm::RequestManager.lookup
|
98
107
|
|
99
108
|
template_name = @template.virtual_path rescue "Unknown Collection"
|
@@ -105,7 +114,11 @@ module ScoutApm
|
|
105
114
|
|
106
115
|
begin
|
107
116
|
req.start_layer(layer)
|
108
|
-
|
117
|
+
if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
|
118
|
+
super(*args, **kwargs)
|
119
|
+
else
|
120
|
+
super(*args)
|
121
|
+
end
|
109
122
|
ensure
|
110
123
|
req.stop_layer
|
111
124
|
end
|
@@ -113,7 +126,7 @@ module ScoutApm
|
|
113
126
|
end
|
114
127
|
|
115
128
|
module ActionViewTemplateRendererInstruments
|
116
|
-
def render_template(*args)
|
129
|
+
def render_template(*args, **kwargs)
|
117
130
|
req = ScoutApm::RequestManager.lookup
|
118
131
|
|
119
132
|
template_name = args[0].virtual_path rescue "Unknown"
|
@@ -125,7 +138,7 @@ module ScoutApm
|
|
125
138
|
|
126
139
|
begin
|
127
140
|
req.start_layer(layer)
|
128
|
-
super(*args)
|
141
|
+
super(*args, **kwargs)
|
129
142
|
ensure
|
130
143
|
req.stop_layer
|
131
144
|
end
|
@@ -82,15 +82,8 @@ module ScoutApm
|
|
82
82
|
|
83
83
|
# Install #log tracing
|
84
84
|
if Utils::KlassHelper.defined?("ActiveRecord::ConnectionAdapters::AbstractAdapter")
|
85
|
-
|
86
|
-
|
87
|
-
::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(Tracer)
|
88
|
-
else
|
89
|
-
::ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
|
90
|
-
include ::ScoutApm::Instruments::ActiveRecordAliasMethodInstruments
|
91
|
-
include ::ScoutApm::Tracer
|
92
|
-
end
|
93
|
-
end
|
85
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecordInstruments)
|
86
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.include(Tracer)
|
94
87
|
end
|
95
88
|
|
96
89
|
if Utils::KlassHelper.defined?("ActiveRecord::Base")
|
@@ -172,20 +165,12 @@ module ScoutApm
|
|
172
165
|
# to the real SQL, and an AR generated "name" for the Query
|
173
166
|
#
|
174
167
|
################################################################################
|
175
|
-
|
176
|
-
|
177
|
-
module ActiveRecordAliasMethodInstruments
|
178
|
-
def self.included(instrumented_class)
|
168
|
+
module ActiveRecordInstruments
|
169
|
+
def self.prepended(instrumented_class)
|
179
170
|
ScoutApm::Agent.instance.context.logger.info "Instrumenting #{instrumented_class.inspect}"
|
180
|
-
instrumented_class.class_eval do
|
181
|
-
unless instrumented_class.method_defined?(:log_without_scout_instruments)
|
182
|
-
alias_method :log_without_scout_instruments, :log
|
183
|
-
alias_method :log, :log_with_scout_instruments
|
184
|
-
end
|
185
|
-
end
|
186
171
|
end
|
187
172
|
|
188
|
-
def
|
173
|
+
def log(*args, &block)
|
189
174
|
# Extract data from the arguments
|
190
175
|
sql, name = args
|
191
176
|
metric_name = Utils::ActiveRecordMetricName.new(sql, name)
|
@@ -216,7 +201,7 @@ module ScoutApm
|
|
216
201
|
end
|
217
202
|
current_layer.desc.merge(desc)
|
218
203
|
|
219
|
-
|
204
|
+
super(*args, &block)
|
220
205
|
|
221
206
|
# OR: Start a new layer, we didn't pick up instrumentation earlier in the stack.
|
222
207
|
else
|
@@ -224,7 +209,7 @@ module ScoutApm
|
|
224
209
|
layer.desc = desc
|
225
210
|
req.start_layer(layer)
|
226
211
|
begin
|
227
|
-
|
212
|
+
super(*args, &block)
|
228
213
|
ensure
|
229
214
|
req.stop_layer
|
230
215
|
end
|
@@ -323,14 +308,18 @@ module ScoutApm
|
|
323
308
|
end
|
324
309
|
end
|
325
310
|
|
326
|
-
def find_by_sql_with_scout_instruments(*args, &block)
|
311
|
+
def find_by_sql_with_scout_instruments(*args, **kwargs, &block)
|
327
312
|
req = ScoutApm::RequestManager.lookup
|
328
313
|
layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName::DEFAULT_METRIC)
|
329
314
|
layer.annotate_layer(:ignorable => true)
|
330
315
|
req.start_layer(layer)
|
331
316
|
req.ignore_children!
|
332
317
|
begin
|
333
|
-
|
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
|
334
323
|
ensure
|
335
324
|
req.acknowledge_children!
|
336
325
|
req.stop_layer
|
@@ -408,7 +397,7 @@ module ScoutApm
|
|
408
397
|
end
|
409
398
|
|
410
399
|
module ActiveRecordUpdateInstruments
|
411
|
-
def save(*args, &block)
|
400
|
+
def save(*args, **options, &block)
|
412
401
|
model = self.class.name
|
413
402
|
operation = self.persisted? ? "Update" : "Create"
|
414
403
|
|
@@ -418,14 +407,14 @@ module ScoutApm
|
|
418
407
|
req.start_layer(layer)
|
419
408
|
req.ignore_children!
|
420
409
|
begin
|
421
|
-
super(*args, &block)
|
410
|
+
super(*args, **options, &block)
|
422
411
|
ensure
|
423
412
|
req.acknowledge_children!
|
424
413
|
req.stop_layer
|
425
414
|
end
|
426
415
|
end
|
427
416
|
|
428
|
-
def save!(*args, &block)
|
417
|
+
def save!(*args, **options, &block)
|
429
418
|
model = self.class.name
|
430
419
|
operation = self.persisted? ? "Update" : "Create"
|
431
420
|
|
@@ -434,7 +423,7 @@ module ScoutApm
|
|
434
423
|
req.start_layer(layer)
|
435
424
|
req.ignore_children!
|
436
425
|
begin
|
437
|
-
super(*args, &block)
|
426
|
+
super(*args, **options, &block)
|
438
427
|
ensure
|
439
428
|
req.acknowledge_children!
|
440
429
|
req.stop_layer
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
class Typhoeus
|
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?(::Typhoeus)
|
21
|
+
@installed = true
|
22
|
+
|
23
|
+
logger.info "Instrumenting Typhoeus"
|
24
|
+
|
25
|
+
::Typhoeus::Request.send(:prepend, TyphoeusInstrumentation)
|
26
|
+
::Typhoeus::Hydra.send(:prepend, TyphoeusHydraInstrumentation)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module TyphoeusHydraInstrumentation
|
31
|
+
def run(*args, &block)
|
32
|
+
req = ScoutApm::RequestManager.lookup
|
33
|
+
req.start_layer(ScoutApm::Layer.new("HTTP", "Hydra"))
|
34
|
+
current_layer = req.current_layer
|
35
|
+
current_layer.desc = scout_desc if current_layer
|
36
|
+
|
37
|
+
begin
|
38
|
+
super(*args, &block)
|
39
|
+
ensure
|
40
|
+
req.stop_layer
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def scout_desc
|
45
|
+
"#{self.queued_requests.count} requests"
|
46
|
+
rescue
|
47
|
+
""
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module TyphoeusInstrumentation
|
52
|
+
def run(*args, &block)
|
53
|
+
req = ScoutApm::RequestManager.lookup
|
54
|
+
req.start_layer(ScoutApm::Layer.new("HTTP", scout_request_verb))
|
55
|
+
current_layer = req.current_layer
|
56
|
+
current_layer.desc = scout_desc(scout_request_verb, scout_request_url) if current_layer
|
57
|
+
|
58
|
+
begin
|
59
|
+
super(*args, &block)
|
60
|
+
ensure
|
61
|
+
req.stop_layer
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def scout_desc(verb, uri)
|
66
|
+
max_length = ScoutApm::Agent.instance.context.config.value('instrument_http_url_length')
|
67
|
+
(String(uri).split('?').first)[0..(max_length - 1)]
|
68
|
+
rescue
|
69
|
+
""
|
70
|
+
end
|
71
|
+
|
72
|
+
def scout_request_url
|
73
|
+
self.url
|
74
|
+
rescue
|
75
|
+
""
|
76
|
+
end
|
77
|
+
|
78
|
+
def scout_request_verb
|
79
|
+
self.options[:method].to_s
|
80
|
+
rescue
|
81
|
+
""
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|