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
@@ -22,12 +22,17 @@ module ScoutApm
|
|
22
22
|
include ScoutApm::Tracer
|
23
23
|
|
24
24
|
def request_with_scout_instruments(*args,&block)
|
25
|
-
|
26
|
-
self.class.instrument("HTTP", "request", :desc => url) do
|
25
|
+
self.class.instrument("HTTP", "request", :desc => request_scout_description(args.first)) do
|
27
26
|
request_without_scout_instruments(*args, &block)
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
30
|
+
def request_scout_description(req)
|
31
|
+
path = req.path
|
32
|
+
path = path.path if path.respond_to?(:path)
|
33
|
+
(@address + path.split('?').first)[0..99]
|
34
|
+
end
|
35
|
+
|
31
36
|
alias request_without_scout_instruments request
|
32
37
|
alias request request_with_scout_instruments
|
33
38
|
end
|
@@ -1,36 +1,53 @@
|
|
1
1
|
module ScoutApm
|
2
2
|
module Instruments
|
3
|
+
|
4
|
+
class HistogramReport
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :histogram
|
7
|
+
|
8
|
+
def initialize(name, histogram)
|
9
|
+
@name = name
|
10
|
+
@histogram = histogram
|
11
|
+
end
|
12
|
+
|
13
|
+
def combine!(other)
|
14
|
+
raise "Mismatched Histogram Names" unless name == other.name
|
15
|
+
histogram.combine!(other.histogram)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
3
20
|
class PercentileSampler
|
4
21
|
attr_reader :logger
|
5
22
|
|
6
|
-
|
23
|
+
# A hash of { time => RequestHistograms }
|
24
|
+
attr_reader :histograms
|
7
25
|
|
8
|
-
def initialize(logger,
|
26
|
+
def initialize(logger, histograms)
|
9
27
|
@logger = logger
|
10
|
-
@
|
28
|
+
@histograms = histograms
|
11
29
|
end
|
12
30
|
|
13
31
|
def human_name
|
14
|
-
|
32
|
+
'Percentiles'
|
15
33
|
end
|
16
34
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
meta = MetricMeta.new("Percentile/#{percentile}/#{name}")
|
24
|
-
stat = MetricStats.new
|
25
|
-
stat.update!(histos.quantile(name, percentile))
|
26
|
-
ms[meta] = stat
|
27
|
-
end
|
28
|
-
end
|
35
|
+
def metrics(timestamp, store)
|
36
|
+
store.track_histograms!(percentiles(timestamp), :timestamp => timestamp)
|
37
|
+
end
|
38
|
+
|
39
|
+
def percentiles(time)
|
40
|
+
result = []
|
29
41
|
|
30
|
-
|
31
|
-
|
42
|
+
histogram = histograms.delete(time)
|
43
|
+
|
44
|
+
return result unless histogram
|
45
|
+
|
46
|
+
histogram.each_name do |name|
|
47
|
+
result << HistogramReport.new(name, histogram.raw(name))
|
48
|
+
end
|
32
49
|
|
33
|
-
|
50
|
+
result
|
34
51
|
end
|
35
52
|
end
|
36
53
|
end
|
@@ -29,16 +29,17 @@ module ScoutApm
|
|
29
29
|
"Process CPU"
|
30
30
|
end
|
31
31
|
|
32
|
-
def metrics(
|
32
|
+
def metrics(timestamp, store)
|
33
33
|
result = run
|
34
34
|
if result
|
35
35
|
meta = MetricMeta.new("#{metric_type}/#{metric_name}")
|
36
36
|
stat = MetricStats.new(false)
|
37
37
|
stat.update!(result)
|
38
|
-
{ meta => stat }
|
38
|
+
store.track!({ meta => stat }, :timestamp => timestamp)
|
39
39
|
else
|
40
40
|
{}
|
41
41
|
end
|
42
|
+
|
42
43
|
end
|
43
44
|
|
44
45
|
# TODO: Figure out a good default instead of nil
|
@@ -33,20 +33,20 @@ module ScoutApm
|
|
33
33
|
"Process Memory"
|
34
34
|
end
|
35
35
|
|
36
|
-
def metrics(
|
36
|
+
def metrics(timestamp, store)
|
37
37
|
result = run
|
38
38
|
if result
|
39
39
|
meta = MetricMeta.new("#{metric_type}/#{metric_name}")
|
40
40
|
stat = MetricStats.new(false)
|
41
41
|
stat.update!(result)
|
42
|
-
{ meta => stat }
|
42
|
+
store.track!({ meta => stat }, :timestamp => timestamp)
|
43
43
|
else
|
44
44
|
{}
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
def run
|
49
|
-
self.class.rss_in_mb.tap { |res| logger.debug "#{human_name}: #{res.inspect}" }
|
49
|
+
self.class.rss_in_mb.tap { |res| logger.debug "#{human_name}: #{res.inspect}" }
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
module Resque
|
4
|
+
def around_perform_with_scout_instruments(*args)
|
5
|
+
job_name = self.to_s
|
6
|
+
queue = find_queue
|
7
|
+
|
8
|
+
if job_name == "ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper"
|
9
|
+
job_name = args.first["job_class"] rescue job_name
|
10
|
+
queue = args.first["queue_name"] rescue queue_name
|
11
|
+
end
|
12
|
+
|
13
|
+
req = ScoutApm::RequestManager.lookup
|
14
|
+
req.job!
|
15
|
+
|
16
|
+
begin
|
17
|
+
req.start_layer(ScoutApm::Layer.new('Queue', queue))
|
18
|
+
started_queue = true
|
19
|
+
req.start_layer(ScoutApm::Layer.new('Job', job_name))
|
20
|
+
started_job = true
|
21
|
+
|
22
|
+
yield
|
23
|
+
rescue => e
|
24
|
+
req.error!
|
25
|
+
raise
|
26
|
+
ensure
|
27
|
+
req.stop_layer if started_job
|
28
|
+
req.stop_layer if started_queue
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_queue
|
33
|
+
return @queue if @queue
|
34
|
+
return queue if self.respond_to?(:queue)
|
35
|
+
return "unknown"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
data/lib/scout_apm/layaway.rb
CHANGED
@@ -7,13 +7,13 @@
|
|
7
7
|
#
|
8
8
|
module ScoutApm
|
9
9
|
class Layaway
|
10
|
-
# How old a file needs to be in Seconds before it gets reported.
|
11
|
-
REPORTING_AGE = 120
|
12
|
-
|
13
10
|
# How long to let a stale file sit before deleting it.
|
14
11
|
# Letting it sit a bit may be useful for debugging
|
15
12
|
STALE_AGE = 10 * 60
|
16
13
|
|
14
|
+
# Failsafe to prevent writing layaway files if for some reason they are not being cleaned up
|
15
|
+
MAX_FILES_LIMIT = 5000
|
16
|
+
|
17
17
|
# A strftime format string for how we render timestamps in filenames.
|
18
18
|
# Must be sortable as an integer
|
19
19
|
TIME_FORMAT = "%Y%m%d%H%M"
|
@@ -48,7 +48,11 @@ module ScoutApm
|
|
48
48
|
@directory = Pathname.new(found)
|
49
49
|
end
|
50
50
|
|
51
|
-
def write_reporting_period(reporting_period)
|
51
|
+
def write_reporting_period(reporting_period, files_limit = MAX_FILES_LIMIT)
|
52
|
+
if at_layaway_file_limit?(files_limit)
|
53
|
+
ScoutApm::Agent.instance.logger.error("Hit layaway file limit. Not writing to layaway file")
|
54
|
+
return false
|
55
|
+
end
|
52
56
|
filename = file_for(reporting_period.timestamp)
|
53
57
|
layaway_file = LayawayFile.new(filename)
|
54
58
|
layaway_file.write(reporting_period)
|
@@ -60,41 +64,56 @@ module ScoutApm
|
|
60
64
|
def with_claim(timestamp)
|
61
65
|
coordinator_file = glob_pattern(timestamp, :coordinator)
|
62
66
|
|
63
|
-
|
64
|
-
# This file gets deleted only by a process that successfully obtained a lock
|
65
|
-
f = File.open(coordinator_file, File::RDWR | File::CREAT)
|
66
67
|
begin
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
files = all_files_for(timestamp).reject{|l| l.to_s == coordinator_file.to_s }
|
73
|
-
rps = files.map{ |layaway| LayawayFile.new(layaway).load }.compact
|
74
|
-
if rps.any?
|
75
|
-
yield rps
|
68
|
+
# This file gets deleted only by a process that successfully created and obtained the exclusive lock
|
69
|
+
f = File.open(coordinator_file, File::RDWR | File::CREAT | File::EXCL | File::NONBLOCK)
|
70
|
+
rescue Errno::EEXIST
|
71
|
+
false
|
72
|
+
end
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
74
|
+
begin
|
75
|
+
if f
|
76
|
+
begin
|
77
|
+
ScoutApm::Agent.instance.logger.debug("Obtained Reporting Lock")
|
78
|
+
|
79
|
+
log_layaway_file_information
|
80
|
+
|
81
|
+
files = all_files_for(timestamp).reject{|l| l.to_s == coordinator_file.to_s }
|
82
|
+
rps = files.map{ |layaway| LayawayFile.new(layaway).load }.compact
|
83
|
+
if rps.any?
|
84
|
+
yield rps
|
85
|
+
|
86
|
+
ScoutApm::Agent.instance.logger.debug("Deleting the now-reported layaway files for #{timestamp.to_s}")
|
87
|
+
delete_files_for(timestamp) # also removes the coodinator_file
|
88
|
+
|
89
|
+
ScoutApm::Agent.instance.logger.debug("Checking for any Stale layaway files")
|
90
|
+
delete_stale_files(timestamp.to_time - STALE_AGE)
|
91
|
+
else
|
92
|
+
File.unlink(coordinator_file)
|
93
|
+
ScoutApm::Agent.instance.logger.debug("No layaway files to report")
|
94
|
+
end
|
95
|
+
|
96
|
+
true
|
97
|
+
rescue Exception => e
|
98
|
+
ScoutApm::Agent.instance.logger.debug("Caught an exception in with_claim, with the coordination file locked: #{e.message}, #{e.backtrace.inspect}")
|
99
|
+
raise
|
100
|
+
ensure
|
101
|
+
# Unlock the file when done!
|
102
|
+
f.flock(File::LOCK_UN | File::LOCK_NB)
|
103
|
+
f.close
|
82
104
|
end
|
83
|
-
|
84
|
-
# Unlock the file when done!
|
85
|
-
f.flock(File::LOCK_UN | File::LOCK_NB)
|
86
|
-
f.close
|
87
|
-
true
|
88
105
|
else
|
89
106
|
# Didn't obtain lock, another process is reporting. Return false from this function, but otherwise no work
|
90
|
-
f.close
|
91
107
|
false
|
92
108
|
end
|
93
109
|
end
|
94
110
|
end
|
95
111
|
|
96
112
|
def delete_files_for(timestamp)
|
97
|
-
all_files_for(timestamp).each { |layaway|
|
113
|
+
all_files_for(timestamp).each { |layaway|
|
114
|
+
ScoutApm::Agent.instance.logger.debug("Deleting layaway file: #{layaway}")
|
115
|
+
File.unlink(layaway)
|
116
|
+
}
|
98
117
|
end
|
99
118
|
|
100
119
|
def delete_stale_files(older_than)
|
@@ -105,6 +124,8 @@ module ScoutApm
|
|
105
124
|
select { |timestamp| timestamp.to_i < older_than.strftime(TIME_FORMAT).to_i }.
|
106
125
|
tap { |timestamps| ScoutApm::Agent.instance.logger.debug("Deleting stale layaway files with timestamps: #{timestamps.inspect}") }.
|
107
126
|
map { |timestamp| delete_files_for(timestamp) }
|
127
|
+
rescue => e
|
128
|
+
ScoutApm::Agent.instance.logger.debug("Problem deleting stale files: #{e.message}, #{e.backtrace.inspect}")
|
108
129
|
end
|
109
130
|
|
110
131
|
private
|
@@ -155,6 +176,24 @@ module ScoutApm
|
|
155
176
|
nil
|
156
177
|
end
|
157
178
|
end
|
179
|
+
|
180
|
+
def at_layaway_file_limit?(files_limit = MAX_FILES_LIMIT)
|
181
|
+
all_files_for(:all).count >= files_limit
|
182
|
+
end
|
183
|
+
|
184
|
+
def log_layaway_file_information
|
185
|
+
files_in_temp = Dir["#{directory}/*"].count
|
186
|
+
|
187
|
+
all_filenames = all_files_for(:all)
|
188
|
+
count_per_timestamp = Hash[
|
189
|
+
all_filenames.
|
190
|
+
group_by {|f| timestamp_from_filename(f) }.
|
191
|
+
map{ |timestamp, list| [timestamp, list.length] }
|
192
|
+
]
|
193
|
+
|
194
|
+
|
195
|
+
ScoutApm::Agent.instance.logger.debug("Total in #{directory}: #{files_in_temp}. Total Layaway Files: #{all_filenames.size}. By Timestamp: #{count_per_timestamp.inspect}")
|
196
|
+
end
|
158
197
|
end
|
159
198
|
end
|
160
199
|
|
data/lib/scout_apm/layer.rb
CHANGED
@@ -13,13 +13,17 @@ module ScoutApm
|
|
13
13
|
# instrumentation for an example of how this is useful
|
14
14
|
attr_accessor :name
|
15
15
|
|
16
|
-
# An array of children layers
|
16
|
+
# An array of children layers
|
17
17
|
# For instance, if we are in a middleware, there will likely be only a single
|
18
18
|
# child, which is another middleware. In a Controller, we may have a handful
|
19
19
|
# of children: [ActiveRecord, ActiveRecord, View, HTTP Call].
|
20
20
|
#
|
21
21
|
# This useful to get actual time spent in this layer vs. children time
|
22
|
-
|
22
|
+
#
|
23
|
+
# TODO: Check callers for compatibility w/ nil to avoid making an empty array
|
24
|
+
def children
|
25
|
+
@children || LayerChildrenSet.new
|
26
|
+
end
|
23
27
|
|
24
28
|
# Time objects recording the start & stop times of this layer
|
25
29
|
attr_reader :start_time, :stop_time
|
@@ -38,41 +42,31 @@ module ScoutApm
|
|
38
42
|
# Known Keys:
|
39
43
|
# :record_count - The number of rows returned by an AR query (From notification instantiation.active_record)
|
40
44
|
# :class_name - The ActiveRecord class name (From notification instantiation.active_record)
|
45
|
+
#
|
46
|
+
# If no annotations are ever set, this will return nil
|
41
47
|
attr_reader :annotations
|
42
48
|
|
43
|
-
# ScoutProf - trace_index is an index into the Stack structure in the C
|
44
|
-
# code, used to store captured traces.
|
45
|
-
attr_reader :trace_index
|
46
|
-
|
47
|
-
# ScoutProf - frame_index is an optimization to not capture a few frames
|
48
|
-
# during scoutprof instrumentation
|
49
|
-
attr_reader :frame_index
|
50
|
-
|
51
|
-
# Captured backtraces from ScoutProf. This is distinct from the backtrace
|
52
|
-
# attribute, which gets the ruby backtrace of any given layer. StackProf
|
53
|
-
# focuses on Controller layers, and requires a native extension and a
|
54
|
-
# reasonably recent Ruby.
|
55
|
-
attr_reader :traces
|
56
|
-
|
57
49
|
BACKTRACE_CALLER_LIMIT = 50 # maximum number of lines to send thru for backtrace analysis
|
58
50
|
|
59
51
|
def initialize(type, name, start_time = Time.now)
|
60
52
|
@type = type
|
61
53
|
@name = name
|
62
|
-
@annotations = {}
|
63
54
|
@start_time = start_time
|
64
55
|
@allocations_start = ScoutApm::Instruments::Allocations.count
|
65
56
|
@allocations_stop = 0
|
66
|
-
|
57
|
+
|
58
|
+
# initialize these only on first use
|
59
|
+
@children = nil
|
60
|
+
@annotations = nil
|
67
61
|
@desc = nil
|
62
|
+
end
|
68
63
|
|
69
|
-
|
70
|
-
|
71
|
-
@frame_index = ScoutApm::Instruments::Stacks.current_frame_index # For efficiency sake, try to skip the bottom X frames when collecting traces
|
72
|
-
@trace_index = ScoutApm::Instruments::Stacks.current_trace_index
|
64
|
+
def limited?
|
65
|
+
false
|
73
66
|
end
|
74
67
|
|
75
68
|
def add_child(child)
|
69
|
+
@children ||= LayerChildrenSet.new
|
76
70
|
@children << child
|
77
71
|
end
|
78
72
|
|
@@ -91,6 +85,7 @@ module ScoutApm
|
|
91
85
|
|
92
86
|
# This data is internal to ScoutApm, to add custom information, use the Context api.
|
93
87
|
def annotate_layer(hsh)
|
88
|
+
@annotations ||= {}
|
94
89
|
@annotations.merge!(hsh)
|
95
90
|
end
|
96
91
|
|
@@ -102,14 +97,6 @@ module ScoutApm
|
|
102
97
|
@subscopable
|
103
98
|
end
|
104
99
|
|
105
|
-
def traced!
|
106
|
-
@traced = true
|
107
|
-
end
|
108
|
-
|
109
|
-
def traced?
|
110
|
-
@traced
|
111
|
-
end
|
112
|
-
|
113
100
|
# This is the old style name. This function is used for now, but should be
|
114
101
|
# removed, and the new type & name split should be enforced through the
|
115
102
|
# app.
|
@@ -131,35 +118,6 @@ module ScoutApm
|
|
131
118
|
end
|
132
119
|
end
|
133
120
|
|
134
|
-
# Set the name of the file that this action is coming from.
|
135
|
-
# TraceSet uses this to more accurately filter backtraces
|
136
|
-
def set_root_class(klass_name)
|
137
|
-
@traces.set_root_class(klass_name)
|
138
|
-
end
|
139
|
-
|
140
|
-
def start_sampling
|
141
|
-
if ScoutApm::Agent.instance.config.value('profile') && traced?
|
142
|
-
ScoutApm::Instruments::Stacks.update_indexes(frame_index, trace_index)
|
143
|
-
ScoutApm::Instruments::Stacks.start_sampling
|
144
|
-
else
|
145
|
-
ScoutApm::Instruments::Stacks.stop_sampling(false)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def record_traces!
|
150
|
-
if ScoutApm::Agent.instance.config.value('profile')
|
151
|
-
ScoutApm::Instruments::Stacks.stop_sampling(false)
|
152
|
-
if traced?
|
153
|
-
traces.raw_traces = ScoutApm::Instruments::Stacks.profile_frames
|
154
|
-
traces.skipped_in_gc = ScoutApm::Instruments::Stacks.skipped_in_gc
|
155
|
-
traces.skipped_in_handler = ScoutApm::Instruments::Stacks.skipped_in_handler
|
156
|
-
traces.skipped_in_job_registered = ScoutApm::Instruments::Stacks.skipped_in_job_registered
|
157
|
-
traces.skipped_in_not_running = ScoutApm::Instruments::Stacks.skipped_in_not_running
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
|
163
121
|
######################################
|
164
122
|
# Debugging Helpers
|
165
123
|
######################################
|
@@ -200,6 +158,7 @@ module ScoutApm
|
|
200
158
|
map { |child| child.total_call_time }.
|
201
159
|
inject(0) { |sum, time| sum + time }
|
202
160
|
end
|
161
|
+
private :child_time
|
203
162
|
|
204
163
|
######################################
|
205
164
|
# Allocation Calculations
|
@@ -225,5 +184,6 @@ module ScoutApm
|
|
225
184
|
map { |child| child.total_allocations }.
|
226
185
|
inject(0) { |sum, obj| sum + obj }
|
227
186
|
end
|
187
|
+
private :child_allocations
|
228
188
|
end
|
229
189
|
end
|