scout_apm 2.4.10 → 2.4.11.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +4 -0
- data/lib/scout_apm.rb +3 -0
- data/lib/scout_apm/agent_context.rb +4 -0
- data/lib/scout_apm/context.rb +9 -0
- data/lib/scout_apm/extensions/config.rb +87 -0
- data/lib/scout_apm/extensions/transaction_callback_payload.rb +74 -0
- data/lib/scout_apm/layer_converters/allocation_metric_converter.rb +3 -1
- data/lib/scout_apm/layer_converters/database_converter.rb +2 -0
- data/lib/scout_apm/layer_converters/error_converter.rb +4 -2
- data/lib/scout_apm/layer_converters/histograms.rb +1 -0
- data/lib/scout_apm/layer_converters/job_converter.rb +1 -0
- data/lib/scout_apm/layer_converters/metric_converter.rb +1 -0
- data/lib/scout_apm/layer_converters/request_queue_time_converter.rb +4 -2
- data/lib/scout_apm/layer_converters/slow_job_converter.rb +1 -0
- data/lib/scout_apm/layer_converters/slow_request_converter.rb +1 -0
- data/lib/scout_apm/reporting.rb +14 -10
- data/lib/scout_apm/tracked_request.rb +22 -15
- data/lib/scout_apm/version.rb +1 -1
- data/test/unit/extensions/periodic_callbacks_test.rb +58 -0
- data/test/unit/extensions/transaction_callbacks_test.rb +58 -0
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1686beb2285cb415ac0f73e4dfa65524b85a369d
|
4
|
+
data.tar.gz: f56d09891f9b899721c711f43dc48e06160073b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3af376cdc73869c73775ca02aaad1817fa735a7b2c73521fe2015f0584c5085e50f7ec94c40bc402363c691e70d98c6cfbc4d0887ff1b0cb7082efeae1bc2578
|
7
|
+
data.tar.gz: 6ace83f9f30fd8bfeb48875e6a58c508f2cc65f1fafd36e8fc1e6421c6556ddc096a27396dc2546ae623af9765586da976da64b6cec9654c29c71feea0927bd6
|
data/CHANGELOG.markdown
CHANGED
data/lib/scout_apm.rb
CHANGED
@@ -172,6 +172,9 @@ require 'scout_apm/agent/exit_handler'
|
|
172
172
|
require 'scout_apm/tasks/doctor'
|
173
173
|
require 'scout_apm/tasks/support'
|
174
174
|
|
175
|
+
require 'scout_apm/extensions/config'
|
176
|
+
require 'scout_apm/extensions/transaction_callback_payload'
|
177
|
+
|
175
178
|
if defined?(Rails) && defined?(Rails::VERSION) && defined?(Rails::VERSION::MAJOR) && Rails::VERSION::MAJOR >= 3 && defined?(Rails::Railtie)
|
176
179
|
module ScoutApm
|
177
180
|
class Railtie < Rails::Railtie
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ScoutApm
|
2
2
|
class AgentContext
|
3
|
+
|
4
|
+
attr_accessor :extensions
|
5
|
+
|
3
6
|
# Initially start up without attempting to load a configuration file. We
|
4
7
|
# need to be able to lookup configuration options like "application_root"
|
5
8
|
# which would then in turn influence where the yaml configuration file is
|
@@ -9,6 +12,7 @@ module ScoutApm
|
|
9
12
|
def initialize()
|
10
13
|
@logger = LoggerFactory.build_minimal_logger
|
11
14
|
@process_start_time = Time.now
|
15
|
+
@extensions = ScoutApm::Extensions::Config.new(self)
|
12
16
|
end
|
13
17
|
|
14
18
|
def marshal_dump
|
data/lib/scout_apm/context.rb
CHANGED
@@ -23,6 +23,15 @@ module ScoutApm
|
|
23
23
|
@extra.merge({:user => @user})
|
24
24
|
end
|
25
25
|
|
26
|
+
def to_flat_hash
|
27
|
+
h = to_hash
|
28
|
+
user = h.delete(:user)
|
29
|
+
if user
|
30
|
+
user.each { |k,v| h["user_#{k}"] = v}
|
31
|
+
end
|
32
|
+
h
|
33
|
+
end
|
34
|
+
|
26
35
|
def self.current
|
27
36
|
RequestManager.lookup.context
|
28
37
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Extensions
|
3
|
+
# !!! Extensions are a 0.x level API and breakage is expected as the API is refined.
|
4
|
+
# Extensions fan out data collected by the agent to additional services.
|
5
|
+
class Config
|
6
|
+
attr_reader :agent_context
|
7
|
+
attr_accessor :transaction_callbacks
|
8
|
+
attr_accessor :periodic_callbacks
|
9
|
+
|
10
|
+
# Adds a new callback that runs after a transaction completes.
|
11
|
+
# These run inline during the request and thus should add minimal overhead.
|
12
|
+
# For example, a transaction callback should NOT make inline HTTP calls to outside services.
|
13
|
+
# +callback+ must be an object that respond to a +call(payload)+ method.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# ScoutApm::Extensions::Config.add_transaction_callback(Proc.new { |payload| puts "Duration: #{payload.duration_ms}" })
|
17
|
+
#
|
18
|
+
# +payload+ is a +ScoutApm::Extensions::TransactionCallbackPayload+ object.
|
19
|
+
def self.add_transaction_callback(callback)
|
20
|
+
agent_context.extensions.transaction_callbacks << callback
|
21
|
+
end
|
22
|
+
|
23
|
+
# Adds a callback that runs when the per-minute report data is sent to Scout.
|
24
|
+
# These run in a background thread so external HTTP calls are OK.
|
25
|
+
# +callback+ must be an object that responds to a +call(reporting_period, metadata)+ method.
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# ScoutApm::Extensions::Config.add_periodic_callback(Proc.new { |reporting_period, metadata| ... })
|
29
|
+
def self.add_periodic_callback(callback)
|
30
|
+
agent_context.extensions.periodic_callbacks << callback
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(agent_context)
|
34
|
+
@agent_context = agent_context
|
35
|
+
@transaction_callbacks = []
|
36
|
+
@periodic_callbacks = []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Runs each reporting period callback.
|
40
|
+
# Each callback runs inside a begin/rescue block so a broken callback doesn't prevent other
|
41
|
+
# callbacks from executing or reporting data from being sent.
|
42
|
+
def run_periodic_callbacks(reporting_period, metadata)
|
43
|
+
return unless periodic_callbacks.any?
|
44
|
+
|
45
|
+
periodic_callbacks.each do |callback|
|
46
|
+
begin
|
47
|
+
callback.call(reporting_period, metadata)
|
48
|
+
rescue => e
|
49
|
+
logger.warn "Error running reporting callback extension=#{callback}"
|
50
|
+
logger.info e.message
|
51
|
+
logger.debug e.backtrace
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Runs each transaction callback.
|
57
|
+
# Each callback runs inside a begin/rescue block so a broken callback doesn't prevent other
|
58
|
+
# callbacks from executing or the transaction from being recorded.
|
59
|
+
def run_transaction_callbacks(converter_results, context, scope_layer)
|
60
|
+
# It looks like layer_finder.scope = nil when a Sidekiq job is retried
|
61
|
+
return unless scope_layer
|
62
|
+
return unless transaction_callbacks.any?
|
63
|
+
|
64
|
+
payload = ScoutApm::Extensions::TransactionCallbackPayload.new(agent_context,converter_results,context,scope_layer)
|
65
|
+
|
66
|
+
transaction_callbacks.each do |callback|
|
67
|
+
begin
|
68
|
+
callback.call(payload)
|
69
|
+
rescue => e
|
70
|
+
logger.warn "Error running transaction callback extension=#{callback}"
|
71
|
+
logger.info e.message
|
72
|
+
logger.debug e.backtrace
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.agent_context
|
78
|
+
ScoutApm::Agent.instance.context
|
79
|
+
end
|
80
|
+
|
81
|
+
def logger
|
82
|
+
agent_context.logger
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Extensions
|
3
|
+
# A +TransactionCallbackPayload+ is passed to each Transaction callback's +call+ method.
|
4
|
+
# It encapsulates the data about a specific transaction.
|
5
|
+
class TransactionCallbackPayload
|
6
|
+
# A Hash that stores the output of each layer converter by name. See the naming conventions in +TrackedRequest+.
|
7
|
+
attr_accessor :converter_results
|
8
|
+
|
9
|
+
def initialize(agent_context,converter_results,context,scope_layer)
|
10
|
+
@agent_context = agent_context
|
11
|
+
@converter_results = converter_results
|
12
|
+
@context = context
|
13
|
+
@scope_layer = scope_layer
|
14
|
+
end
|
15
|
+
|
16
|
+
# A flat hash of the context associated w/this transaction (ie user ip and another other data added to context).
|
17
|
+
def context
|
18
|
+
@context.to_flat_hash
|
19
|
+
end
|
20
|
+
|
21
|
+
# The total duration of the transaction
|
22
|
+
def duration_ms
|
23
|
+
@scope_layer.total_call_time*1000 # ms
|
24
|
+
end
|
25
|
+
|
26
|
+
# The time in queue of the transaction in ms. If not present, +nil+ is returned as this is unknown.
|
27
|
+
def queue_time_ms
|
28
|
+
# Controller logic
|
29
|
+
if converter_results[:queue_time] && converter_results[:queue].any?
|
30
|
+
converter_results[:queue_time].values.first.total_call_time*1000 # ms
|
31
|
+
# Job logic
|
32
|
+
elsif converter_results[:job]
|
33
|
+
stat = converter_results[:job].metric_set.metrics[ScoutApm::MetricMeta.new("Latency/all", :scope => transaction_name)]
|
34
|
+
stat ? stat.total_call_time*1000 : nil
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def hostname
|
41
|
+
@agent_context.environment.hostname
|
42
|
+
end
|
43
|
+
|
44
|
+
def app_name
|
45
|
+
@agent_context.config.value('name')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns +true+ if the transaction raised an exception.
|
49
|
+
def error?
|
50
|
+
converter_results[:errors] && converter_results[:errors].any?
|
51
|
+
end
|
52
|
+
|
53
|
+
def transation_type
|
54
|
+
@scope_layer.type
|
55
|
+
end
|
56
|
+
|
57
|
+
def transaction_name
|
58
|
+
@scope_layer.legacy_metric_name
|
59
|
+
end
|
60
|
+
|
61
|
+
# Web/Job are more language-agnostic names for controller/job. For example, Python Django does not have controllers.
|
62
|
+
def transaction_type_slug
|
63
|
+
case transation_type
|
64
|
+
when 'Controller'
|
65
|
+
'web'
|
66
|
+
when 'Job'
|
67
|
+
'job'
|
68
|
+
else
|
69
|
+
'transaction'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -8,8 +8,10 @@ module ScoutApm
|
|
8
8
|
meta = MetricMeta.new("ObjectAllocations", {:scope => scope_layer.legacy_metric_name})
|
9
9
|
stat = MetricStats.new
|
10
10
|
stat.update!(root_layer.total_allocations)
|
11
|
+
metrics = { meta => stat }
|
11
12
|
|
12
|
-
@store.track!(
|
13
|
+
@store.track!(metrics)
|
14
|
+
nil # not returning anything in the layer results ... not used
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -32,6 +32,8 @@ module ScoutApm
|
|
32
32
|
# only due to 1 http request)
|
33
33
|
@db_query_metric_set.increment_transaction_count!
|
34
34
|
@store.track_db_query_metrics!(@db_query_metric_set)
|
35
|
+
|
36
|
+
nil # not returning anything in the layer results ... not used
|
35
37
|
end
|
36
38
|
|
37
39
|
def skip_layer?(layer)
|
@@ -10,8 +10,10 @@ module ScoutApm
|
|
10
10
|
meta = MetricMeta.new("Errors/#{scope_layer.legacy_metric_name}", {})
|
11
11
|
stat = MetricStats.new
|
12
12
|
stat.update!(1)
|
13
|
-
|
14
|
-
|
13
|
+
metrics = { meta => stat }
|
14
|
+
|
15
|
+
@store.track!(metrics)
|
16
|
+
metrics # this result must be returned so it can be accessed by transaction callback extensions
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -28,8 +28,10 @@ module ScoutApm
|
|
28
28
|
meta = MetricMeta.new("QueueTime/Request", {:scope => scope_layer.legacy_metric_name})
|
29
29
|
stat = MetricStats.new(true)
|
30
30
|
stat.update!(queue_time)
|
31
|
-
|
32
|
-
|
31
|
+
metrics = { meta => stat }
|
32
|
+
|
33
|
+
@store.track!(metrics)
|
34
|
+
metrics # this result must be returned so it can be accessed by transaction callback extensions
|
33
35
|
end
|
34
36
|
|
35
37
|
private
|
data/lib/scout_apm/reporting.rb
CHANGED
@@ -48,7 +48,9 @@ module ScoutApm
|
|
48
48
|
begin
|
49
49
|
merged = rps.inject { |memo, rp| memo.merge(rp) }
|
50
50
|
logger.debug("Merged #{rps.length} reporting periods, delivering")
|
51
|
-
|
51
|
+
metadata = metadata(merged)
|
52
|
+
deliver_period(merged,metadata)
|
53
|
+
context.extensions.run_periodic_callbacks(merged, metadata)
|
52
54
|
true
|
53
55
|
rescue => e
|
54
56
|
logger.debug("Error merging reporting periods #{e.message}")
|
@@ -63,15 +65,8 @@ module ScoutApm
|
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
66
|
-
def
|
67
|
-
|
68
|
-
slow_transactions = reporting_period.slow_transactions_payload
|
69
|
-
jobs = reporting_period.jobs
|
70
|
-
slow_jobs = reporting_period.slow_jobs_payload
|
71
|
-
histograms = reporting_period.histograms
|
72
|
-
db_query_metrics = reporting_period.db_query_metrics_payload
|
73
|
-
|
74
|
-
metadata = {
|
68
|
+
def metadata(reporting_period)
|
69
|
+
{
|
75
70
|
:app_root => context.environment.root.to_s,
|
76
71
|
:unique_id => ScoutApm::Utils::UniqueId.simple,
|
77
72
|
:agent_version => ScoutApm::VERSION,
|
@@ -79,6 +74,15 @@ module ScoutApm
|
|
79
74
|
:agent_pid => Process.pid,
|
80
75
|
:platform => "ruby",
|
81
76
|
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def deliver_period(reporting_period,metadata)
|
80
|
+
metrics = reporting_period.metrics_payload
|
81
|
+
slow_transactions = reporting_period.slow_transactions_payload
|
82
|
+
jobs = reporting_period.jobs
|
83
|
+
slow_jobs = reporting_period.slow_jobs_payload
|
84
|
+
histograms = reporting_period.histograms
|
85
|
+
db_query_metrics = reporting_period.db_query_metrics_payload
|
82
86
|
|
83
87
|
log_deliver(metrics, slow_transactions, metadata, slow_jobs, histograms)
|
84
88
|
|
@@ -64,7 +64,6 @@ module ScoutApm
|
|
64
64
|
@mem_start = mem_usage
|
65
65
|
@recorder = agent_context.recorder
|
66
66
|
@real_request = false
|
67
|
-
|
68
67
|
ignore_request! if @recorder.nil?
|
69
68
|
end
|
70
69
|
|
@@ -116,6 +115,7 @@ module ScoutApm
|
|
116
115
|
layer.capture_backtrace!
|
117
116
|
end
|
118
117
|
|
118
|
+
|
119
119
|
if finalized?
|
120
120
|
stop_request
|
121
121
|
end
|
@@ -273,27 +273,34 @@ module ScoutApm
|
|
273
273
|
|
274
274
|
apply_name_override
|
275
275
|
|
276
|
-
converters
|
277
|
-
|
278
|
-
LayerConverters::
|
279
|
-
LayerConverters::
|
280
|
-
LayerConverters::
|
281
|
-
LayerConverters::
|
282
|
-
LayerConverters::
|
283
|
-
LayerConverters::
|
276
|
+
# Make a constant, then call converters.dup.each so it isn't inline?
|
277
|
+
converters = {
|
278
|
+
:histograms => LayerConverters::Histograms,
|
279
|
+
:metrics => LayerConverters::MetricConverter,
|
280
|
+
:errors => LayerConverters::ErrorConverter,
|
281
|
+
:allocation_metrics => LayerConverters::AllocationMetricConverter,
|
282
|
+
:queue_time => LayerConverters::RequestQueueTimeConverter,
|
283
|
+
:job => LayerConverters::JobConverter,
|
284
|
+
:db => LayerConverters::DatabaseConverter,
|
284
285
|
|
285
|
-
LayerConverters::SlowJobConverter,
|
286
|
-
LayerConverters::SlowRequestConverter,
|
287
|
-
|
286
|
+
:slow_job => LayerConverters::SlowJobConverter,
|
287
|
+
:slow_req => LayerConverters::SlowRequestConverter,
|
288
|
+
}
|
288
289
|
|
289
290
|
walker = LayerConverters::DepthFirstWalker.new(self.root_layer)
|
290
|
-
|
291
|
+
converter_instances = converters.inject({}) do |memo, (slug, klass)|
|
291
292
|
instance = klass.new(@agent_context, self, layer_finder, @store)
|
292
293
|
instance.register_hooks(walker)
|
293
|
-
instance
|
294
|
+
memo[slug] = instance
|
295
|
+
memo
|
294
296
|
end
|
295
297
|
walker.walk
|
296
|
-
|
298
|
+
converter_results = converter_instances.inject({}) do |memo, (slug,i)|
|
299
|
+
memo[slug] = i.record!
|
300
|
+
memo
|
301
|
+
end
|
302
|
+
|
303
|
+
@agent_context.extensions.run_transaction_callbacks(converter_results,context,layer_finder.scope)
|
297
304
|
|
298
305
|
# If there's an instant_key, it means we need to report this right away
|
299
306
|
if web? && instant?
|
data/lib/scout_apm/version.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PeriodicCallbacksTest < Minitest::Test
|
4
|
+
|
5
|
+
# We don't have a test that ensures we actually report data to the server, so we can't be 100% sure this doesn't break
|
6
|
+
# reporting.
|
7
|
+
def test_broken_callback_does_not_throw_exception
|
8
|
+
ScoutApm::Extensions::Config.add_periodic_callback(BrokenCallback.new)
|
9
|
+
# Runs via agent context as calling +add_periodic_callback+ initializing the context + extension config.
|
10
|
+
ScoutApm::Agent.instance.context.extensions.run_periodic_callbacks(reporting_period,metadata)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_callback_runs
|
14
|
+
Thread.current[:periodic_callback_output] = nil
|
15
|
+
ScoutApm::Extensions::Config.add_periodic_callback(PeriodicCallback.new)
|
16
|
+
ScoutApm::Agent.instance.context.extensions.run_periodic_callbacks(reporting_period,metadata)
|
17
|
+
assert Thread.current[:periodic_callback_output]
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_proc_callback
|
21
|
+
Thread.current[:proc_periodic] = nil
|
22
|
+
ScoutApm::Extensions::Config.add_periodic_callback(Proc.new { |reporting_period, metadata| Thread.current[:proc_periodic] = Time.at(metadata[:agent_time].to_i) })
|
23
|
+
ScoutApm::Agent.instance.context.extensions.run_periodic_callbacks(reporting_period,metadata)
|
24
|
+
assert Thread.current[:proc_periodic]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Doesn't respond to +call+.
|
28
|
+
class BrokenCallback
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets a Thread local so we can verify that the callback ran.
|
32
|
+
class PeriodicCallback
|
33
|
+
def call(reporting_period,metadata)
|
34
|
+
Thread.current[:periodic_callback_output] = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def reporting_period
|
41
|
+
rp = ScoutApm::StoreReportingPeriod.new(ScoutApm::AgentContext.new, Time.at(metadata[:agent_time].to_i))
|
42
|
+
rp.absorb_metrics!(metrics)
|
43
|
+
end
|
44
|
+
|
45
|
+
def metrics
|
46
|
+
meta = ScoutApm::MetricMeta.new("Controller/users/index")
|
47
|
+
stats = ScoutApm::MetricStats.new
|
48
|
+
stats.update!(0.1)
|
49
|
+
{
|
50
|
+
meta => stats
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def metadata
|
55
|
+
{:app_root=>"/srv/rails_app", :unique_id=>"ID", :agent_version=>"2.4.10", :agent_time=>"1523287920", :agent_pid=>21581, :platform=>"ruby"}
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TransactionCallbacksTest < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
# Another test could set the recorder to +FakeRecorder+, which does not call +TrackedRequest#record!+.
|
7
|
+
ScoutApm::Agent.instance.context.recorder = ScoutApm::RecorderFactory.build(ScoutApm::Agent.instance.context)
|
8
|
+
end
|
9
|
+
|
10
|
+
# This is more of an integration test to ensure that we don't break TrackedRequest.
|
11
|
+
def test_broken_callback_does_not_break_tracked_request
|
12
|
+
ScoutApm::Extensions::Config.add_transaction_callback(BrokenCallback.new)
|
13
|
+
|
14
|
+
controller_layer = ScoutApm::Layer.new("Controller", "users/index")
|
15
|
+
# why doesn't this run? check if callbacks are configured
|
16
|
+
tr = ScoutApm::TrackedRequest.new(ScoutApm::Agent.instance.context, ScoutApm::FakeStore.new)
|
17
|
+
tr.start_layer(controller_layer)
|
18
|
+
tr.stop_layer
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_callback_runs
|
22
|
+
Thread.current[:transaction_callback_output] = nil
|
23
|
+
ScoutApm::Extensions::Config.add_transaction_callback(TransactionCallback.new)
|
24
|
+
|
25
|
+
controller_layer = ScoutApm::Layer.new("Controller", "users/index")
|
26
|
+
|
27
|
+
tr = ScoutApm::TrackedRequest.new(ScoutApm::Agent.instance.context, ScoutApm::FakeStore.new)
|
28
|
+
tr.start_layer(controller_layer)
|
29
|
+
tr.stop_layer
|
30
|
+
|
31
|
+
assert Thread.current[:transaction_callback_output]
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_run_proc_callback
|
35
|
+
Thread.current[:proc_transaction_duration] = nil
|
36
|
+
ScoutApm::Extensions::Config.add_transaction_callback(Proc.new { |payload| Thread.current[:proc_transaction_duration] = payload.duration_ms })
|
37
|
+
|
38
|
+
controller_layer = ScoutApm::Layer.new("Controller", "users/index")
|
39
|
+
|
40
|
+
tr = ScoutApm::TrackedRequest.new(ScoutApm::Agent.instance.context, ScoutApm::FakeStore.new)
|
41
|
+
tr.start_layer(controller_layer)
|
42
|
+
tr.stop_layer
|
43
|
+
|
44
|
+
assert Thread.current[:proc_transaction_duration]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Doesn't respond to +call+.
|
48
|
+
class BrokenCallback
|
49
|
+
end
|
50
|
+
|
51
|
+
# Sets a Thread local so we can verify that the callback ran.
|
52
|
+
class TransactionCallback
|
53
|
+
def call(payload)
|
54
|
+
Thread.current[:transaction_callback_output] = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout_apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4.
|
4
|
+
version: 2.4.11.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Derek Haynes
|
@@ -209,6 +209,8 @@ files:
|
|
209
209
|
- lib/scout_apm/db_query_metric_stats.rb
|
210
210
|
- lib/scout_apm/debug.rb
|
211
211
|
- lib/scout_apm/environment.rb
|
212
|
+
- lib/scout_apm/extensions/config.rb
|
213
|
+
- lib/scout_apm/extensions/transaction_callback_payload.rb
|
212
214
|
- lib/scout_apm/fake_store.rb
|
213
215
|
- lib/scout_apm/framework_integrations/rails_2.rb
|
214
216
|
- lib/scout_apm/framework_integrations/rails_3_or_4.rb
|
@@ -332,6 +334,8 @@ files:
|
|
332
334
|
- test/unit/db_query_metric_set_test.rb
|
333
335
|
- test/unit/db_query_metric_stats_test.rb
|
334
336
|
- test/unit/environment_test.rb
|
337
|
+
- test/unit/extensions/periodic_callbacks_test.rb
|
338
|
+
- test/unit/extensions/transaction_callbacks_test.rb
|
335
339
|
- test/unit/fake_store_test.rb
|
336
340
|
- test/unit/git_revision_test.rb
|
337
341
|
- test/unit/histogram_test.rb
|
@@ -379,12 +383,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
379
383
|
version: '0'
|
380
384
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
381
385
|
requirements:
|
382
|
-
- - "
|
386
|
+
- - ">"
|
383
387
|
- !ruby/object:Gem::Version
|
384
|
-
version:
|
388
|
+
version: 1.3.1
|
385
389
|
requirements: []
|
386
390
|
rubyforge_project: scout_apm
|
387
|
-
rubygems_version: 2.4.
|
391
|
+
rubygems_version: 2.4.6
|
388
392
|
signing_key:
|
389
393
|
specification_version: 4
|
390
394
|
summary: Ruby application performance monitoring
|
@@ -398,6 +402,8 @@ test_files:
|
|
398
402
|
- test/unit/db_query_metric_set_test.rb
|
399
403
|
- test/unit/db_query_metric_stats_test.rb
|
400
404
|
- test/unit/environment_test.rb
|
405
|
+
- test/unit/extensions/periodic_callbacks_test.rb
|
406
|
+
- test/unit/extensions/transaction_callbacks_test.rb
|
401
407
|
- test/unit/fake_store_test.rb
|
402
408
|
- test/unit/git_revision_test.rb
|
403
409
|
- test/unit/histogram_test.rb
|
@@ -429,3 +435,4 @@ test_files:
|
|
429
435
|
- test/unit/utils/backtrace_parser_test.rb
|
430
436
|
- test/unit/utils/numbers_test.rb
|
431
437
|
- test/unit/utils/scm.rb
|
438
|
+
has_rdoc:
|