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
@@ -0,0 +1,34 @@
1
+ # Scope is determined by the first Controller we hit. Most of the time
2
+ # there will only be 1 anyway. But if you have a controller that calls
3
+ # another controller method, we may pick that up:
4
+ # def update
5
+ # show
6
+ # render :update
7
+ # end
8
+ module ScoutApm
9
+ module LayerConverters
10
+ class FindLayerByType
11
+ def initialize(request)
12
+ @request = request
13
+ end
14
+
15
+ def scope
16
+ @scope ||= call(["Controller", "Job"])
17
+ end
18
+
19
+ def job
20
+ @job ||= call(["Job"])
21
+ end
22
+
23
+ def queue
24
+ @queue ||= call(["Queue"])
25
+ end
26
+
27
+ def call(layer_types)
28
+ walker = DepthFirstWalker.new(@request.root_layer)
29
+ walker.on {|l| return l if layer_types.include?(l.type) }
30
+ walker.walk
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ module ScoutApm
2
+ module LayerConverters
3
+ class Histograms < ConverterBase
4
+ # Updates immediate and long-term histograms for both job and web requests
5
+ def record!
6
+ if request.unique_name != :unknown
7
+ ScoutApm::Agent.instance.request_histograms.add(request.unique_name, root_layer.total_call_time)
8
+ ScoutApm::Agent.instance.request_histograms_by_time[@store.current_timestamp].
9
+ add(request.unique_name, root_layer.total_call_time)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -10,54 +10,20 @@
10
10
  module ScoutApm
11
11
  module LayerConverters
12
12
  class JobConverter < ConverterBase
13
- def call
14
- return unless request.job?
15
-
16
- JobRecord.new(
17
- queue_layer.name,
18
- job_layer.name,
19
- job_layer.total_call_time,
20
- job_layer.total_exclusive_time,
21
- errors,
22
- create_metrics
23
- )
24
- end
25
-
26
- def queue_layer
27
- @queue_layer ||= find_first_layer_of_type("Queue")
28
- end
13
+ attr_reader :meta_options
29
14
 
30
- def job_layer
31
- @job_layer ||= find_first_layer_of_type("Job")
32
- end
33
-
34
- def errors
35
- if request.error?
36
- 1
37
- else
38
- 0
39
- end
40
- end
41
-
42
- def find_first_layer_of_type(layer_type)
43
- walker.walk do |layer|
44
- return layer if layer.type == layer_type
45
- end
46
- end
15
+ def register_hooks(walker)
16
+ return unless request.job?
47
17
 
48
- # Full metrics from this request. These get aggregated in Store for the
49
- # overview metrics, or stored permanently in a SlowTransaction
50
- # Some merging of metrics will happen here, so if a request calls the same
51
- # ActiveRecord or View repeatedly, it'll get merged.
52
- def create_metrics
53
- metric_hash = Hash.new
18
+ super
54
19
 
55
- meta_options = {:scope => job_layer.legacy_metric_name}
20
+ @metrics = Hash.new
21
+ @meta_options = {:scope => layer_finder.job.legacy_metric_name}
56
22
 
57
- walker.walk do |layer|
58
- next if layer == job_layer
59
- next if layer == queue_layer
60
- next if layer.annotations[:ignorable]
23
+ walker.on do |layer|
24
+ next if layer == layer_finder.job
25
+ next if layer == layer_finder.queue
26
+ next if skip_layer?(layer)
61
27
 
62
28
  # we don't need to use the full metric name for scoped metrics as we
63
29
  # only display metrics aggregrated by type, just use "ActiveRecord"
@@ -65,20 +31,40 @@ module ScoutApm
65
31
  metric_name = layer.type
66
32
 
67
33
  meta = MetricMeta.new(metric_name, meta_options)
68
- metric_hash[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
34
+ @metrics[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
69
35
 
70
- stat = metric_hash[meta]
36
+ stat = @metrics[meta]
71
37
  stat.update!(layer.total_call_time, layer.total_exclusive_time)
72
38
  end
73
39
 
74
- # Add the latency metric, which wasn't stored as a distinct layer
40
+ end
41
+
42
+ def record!
43
+ return unless request.job?
44
+
45
+ errors = request.error? ? 1 : 0
46
+ add_latency_metric!
47
+
48
+ record = JobRecord.new(
49
+ layer_finder.queue.name,
50
+ layer_finder.job.name,
51
+ layer_finder.job.total_call_time,
52
+ layer_finder.job.total_exclusive_time,
53
+ errors,
54
+ @metrics
55
+ )
56
+
57
+ @store.track_job!(record)
58
+ end
59
+
60
+ # This isn't stored as a specific layer, so grabbing it doesn't use the
61
+ # walker callbacks
62
+ def add_latency_metric!
75
63
  latency = request.annotations[:queue_latency] || 0
76
64
  meta = MetricMeta.new("Latency", meta_options)
77
65
  stat = MetricStats.new
78
66
  stat.update!(latency)
79
- metric_hash[meta] = stat
80
-
81
- metric_hash
67
+ @metrics[meta] = stat
82
68
  end
83
69
  end
84
70
  end
@@ -1,27 +1,22 @@
1
1
  # Take a TrackedRequest and turn it into a hash of:
2
2
  # MetricMeta => MetricStats
3
+
4
+ # Full metrics from this request. These get aggregated in Store for the
5
+ # overview metrics, or stored permanently in a SlowTransaction
6
+ # Some merging of metrics will happen here, so if a request calls the same
7
+ # ActiveRecord or View repeatedly, it'll get merged.
3
8
  module ScoutApm
4
9
  module LayerConverters
5
10
  class MetricConverter < ConverterBase
6
- def call
7
- scope = scope_layer
8
-
9
- # TODO: Track requests that never reach a Controller (for example, when
10
- # Middleware decides to return rather than passing onward)
11
- return {} unless scope
11
+ def register_hooks(walker)
12
+ super
12
13
 
13
- create_metrics
14
- end
14
+ @metrics = {}
15
15
 
16
- # Full metrics from this request. These get aggregated in Store for the
17
- # overview metrics, or stored permanently in a SlowTransaction
18
- # Some merging of metrics will happen here, so if a request calls the same
19
- # ActiveRecord or View repeatedly, it'll get merged.
20
- def create_metrics
21
- metric_hash = Hash.new
16
+ return unless scope_layer
22
17
 
23
- walker.walk do |layer|
24
- next if layer.annotations[:ignorable]
18
+ walker.on do |layer|
19
+ next if skip_layer?(layer)
25
20
 
26
21
  meta_options = if layer == scope_layer # We don't scope the controller under itself
27
22
  {}
@@ -34,12 +29,15 @@ module ScoutApm
34
29
  metric_name = meta_options.has_key?(:scope) ? layer.type : layer.legacy_metric_name
35
30
 
36
31
  meta = MetricMeta.new(metric_name, meta_options)
37
- metric_hash[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
32
+ @metrics[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
38
33
 
39
- stat = metric_hash[meta]
34
+ stat = @metrics[meta]
40
35
  stat.update!(layer.total_call_time, layer.total_exclusive_time)
41
36
  end
42
- metric_hash
37
+ end
38
+
39
+ def record!
40
+ @store.track!(@metrics)
43
41
  end
44
42
  end
45
43
  end
@@ -4,38 +4,36 @@ module ScoutApm
4
4
 
5
5
  HEADERS = %w(X-Queue-Start X-Request-Start X-QUEUE-START X-REQUEST-START x-queue-start x-request-start)
6
6
 
7
- # Headers is a hash of request headers. In Rails, request.headers would be appropriate
8
- def initialize(request)
9
- super(request)
10
- @headers = request.headers
7
+ def headers
8
+ request.headers
11
9
  end
12
10
 
13
- def call
14
- return {} unless headers
11
+ def record!
12
+ return unless request.web?
13
+
14
+ return unless headers
15
15
 
16
16
  raw_start = locate_timestamp
17
- return {} unless raw_start
17
+ return unless raw_start
18
18
 
19
19
  parsed_start = parse(raw_start)
20
- return {} unless parsed_start
20
+ return unless parsed_start
21
21
 
22
22
  request_start = root_layer.start_time
23
23
  queue_time = (request_start - parsed_start).to_f
24
24
 
25
25
  # If we end up with a negative value, just bail out and don't report anything
26
- return {} if queue_time < 0
26
+ return if queue_time < 0
27
27
 
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
31
 
32
- { meta => stat }
32
+ @store.track!({ meta => stat })
33
33
  end
34
34
 
35
35
  private
36
36
 
37
- attr_reader :headers
38
-
39
37
  # Looks through the possible headers with this data, and extracts the raw
40
38
  # value of the header
41
39
  # Returns nil if not found
@@ -1,30 +1,33 @@
1
+ # Uses a different workflow than normal metrics. We ignore the shared walk of
2
+ # the layer tree, and instead wait until we're sure we even want to do any
3
+ # work. Only then do we go realize all the SlowJobRecord & metrics associated.
4
+ #
1
5
  module ScoutApm
2
6
  module LayerConverters
3
7
  class SlowJobConverter < ConverterBase
4
- def initialize(*)
5
- @backtraces = []
6
- super
7
-
8
- # After call to super, so @request is populated
9
- @points = if request.job?
10
- ScoutApm::Agent.instance.slow_job_policy.score(request)
11
- else
12
- -1
13
- end
14
- end
8
+ ###################
9
+ # Converter API #
10
+ ###################
11
+ def record!
12
+ return nil unless request.job?
13
+ @points = ScoutApm::Agent.instance.slow_job_policy.score(request)
15
14
 
16
- def name
17
- request.unique_name
15
+ # Let the store know we're here, and if it wants our data, it will call
16
+ # back into #call
17
+ @store.track_slow_job!(self)
18
18
  end
19
19
 
20
- def score
21
- @points
22
- end
20
+ #####################
21
+ # ScoreItemSet API #
22
+ #####################
23
+ def name; request.unique_name; end
24
+ def score; @points; end
23
25
 
26
+ # Called by the set to force this to actually be created.
24
27
  def call
25
28
  return nil unless request.job?
26
- return nil unless queue_layer
27
- return nil unless job_layer
29
+ return nil unless layer_finder.queue
30
+ return nil unless layer_finder.job
28
31
 
29
32
  ScoutApm::Agent.instance.slow_job_policy.stored!(request)
30
33
 
@@ -32,6 +35,7 @@ module ScoutApm
32
35
  mem_delta = ScoutApm::Instruments::Process::ProcessMemory.rss_to_mb(request.capture_mem_delta!)
33
36
 
34
37
  timing_metrics, allocation_metrics = create_metrics
38
+
35
39
  unless ScoutApm::Instruments::Allocations::ENABLED
36
40
  allocation_metrics = {}
37
41
  end
@@ -47,120 +51,42 @@ module ScoutApm
47
51
  allocation_metrics,
48
52
  mem_delta,
49
53
  job_layer.total_allocations,
50
- score)
51
- end
52
-
53
- def queue_layer
54
- @queue_layer ||= find_first_layer_of_type("Queue")
55
- end
56
-
57
- def job_layer
58
- @job_layer ||= find_first_layer_of_type("Job")
54
+ score,
55
+ limited?
56
+ )
59
57
  end
60
58
 
61
59
  def create_metrics
60
+ # Create a new walker, and wire up the subscope stuff
61
+ walker = LayerConverters::DepthFirstWalker.new(self.root_layer)
62
+ register_hooks(walker)
63
+
62
64
  metric_hash = Hash.new
63
65
  allocation_metric_hash = Hash.new
64
66
 
65
- # Keep a list of subscopes, but only ever use the front one. The rest
66
- # get pushed/popped in cases when we have many levels of subscopable
67
- # layers. This lets us push/pop without otherwise keeping track very closely.
68
- subscope_layers = []
69
-
70
- walker.before do |layer|
71
- if layer.subscopable?
72
- subscope_layers.push(layer)
73
- end
74
- end
75
-
76
- walker.after do |layer|
77
- if layer.subscopable?
78
- subscope_layers.pop
79
- end
80
- end
81
-
82
- walker.walk do |layer|
83
- # Sometimes we start capturing a layer without knowing if we really
84
- # want to make an entry for it. See ActiveRecord instrumentation for
85
- # an example. We start capturing before we know if a query is cached
86
- # or not, and want to skip any cached queries.
87
- next if layer.annotations[:ignorable]
67
+ walker.on do |layer|
68
+ next if skip_layer?(layer)
88
69
 
89
70
  # The queue_layer is useful to capture for other reasons, but doesn't
90
71
  # create a MetricMeta/Stat of its own
91
72
  next if layer == queue_layer
92
73
 
93
- meta_options = if subscope_layers.first && layer != subscope_layers.first # Don't scope under ourself.
94
- subscope_name = subscope_layers.first.legacy_metric_name
95
- {:scope => subscope_name}
96
- elsif layer == job_layer # We don't scope the controller under itself
97
- {}
98
- else
99
- {:scope => job_layer.legacy_metric_name}
100
- end
101
-
102
- # Specific Metric
103
- meta_options.merge!(:desc => layer.desc.to_s) if layer.desc
104
- meta = MetricMeta.new(layer.legacy_metric_name, meta_options)
105
- meta.extra.merge!(layer.annotations)
106
-
107
- if layer.backtrace
108
- bt = ScoutApm::Utils::BacktraceParser.new(layer.backtrace).call
109
- if bt.any? # we could walk thru the call stack and not find in-app code
110
- meta.backtrace = bt
111
- # Why not just call meta.backtrace and call it done? The walker could access a later later that generates the same MetricMeta but doesn't have a backtrace. This could be
112
- # lost in the metric_hash if it is replaced by the new key.
113
- @backtraces << meta
114
- else
115
- ScoutApm::Agent.instance.logger.debug { "Unable to capture an app-specific backtrace for #{meta.inspect}\n#{layer.backtrace}" }
116
- end
117
- end
118
-
119
- metric_hash[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
120
- allocation_metric_hash[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
121
- stat = metric_hash[meta]
122
- stat.update!(layer.total_call_time, layer.total_exclusive_time)
123
- stat = allocation_metric_hash[meta]
124
- stat.update!(layer.total_allocations, layer.total_exclusive_allocations)
125
-
126
- # Merged Metric (no specifics, just sum up by type)
127
- meta = MetricMeta.new("#{layer.type}/all")
128
- metric_hash[meta] ||= MetricStats.new(false)
129
- allocation_metric_hash[meta] ||= MetricStats.new(false)
130
- stat = metric_hash[meta]
131
- stat.update!(layer.total_call_time, layer.total_exclusive_time)
132
- stat = allocation_metric_hash[meta]
133
- stat.update!(layer.total_allocations, layer.total_exclusive_allocations)
134
-
135
- stat.add_traces(layer.traces.as_json)
136
-
137
- # Debug logging for scoutprof traces
138
- if ScoutApm::Agent.instance.config.value('profile')
139
- if layer.type =~ %r{^(Controller|Queue|Job)$}.freeze
140
- ScoutApm::Agent.instance.logger.debug do
141
- traces_inspect = layer.traces.inspect
142
- "****** Slow Request #{layer.type} Traces (#{layer.name}, tet: #{layer.total_exclusive_time}, tct: #{layer.total_call_time}), total raw traces: #{layer.traces.cube.total_count}, total clean traces: #{layer.traces.total_count}, skipped gc: #{layer.traces.skipped_in_gc}, skipped handler: #{layer.traces.skipped_in_handler}, skipped registered #{layer.traces.skipped_in_job_registered}, skipped not_running #{layer.traces.skipped_in_not_running}:\n#{traces_inspect}"
143
- end
144
- end
145
- else
146
- if layer.type =~ %r{^(Controller|Queue|Job)$}.freeze
147
- ScoutApm::Agent.instance.logger.debug "****** Slow Request #{layer.type} Traces: Scoutprof is not enabled"
148
- end
149
- end
150
- end # walker.walk
74
+ store_specific_metric(layer, metric_hash, allocation_metric_hash)
75
+ store_aggregate_metric(layer, metric_hash, allocation_metric_hash)
76
+ end
77
+
78
+ # And now run through the walk we just defined
79
+ walker.walk
151
80
 
152
81
  metric_hash = attach_backtraces(metric_hash)
153
82
  allocation_metric_hash = attach_backtraces(allocation_metric_hash)
154
83
 
155
- [metric_hash,allocation_metric_hash]
84
+ [metric_hash, allocation_metric_hash]
156
85
  end
157
86
 
158
- def attach_backtraces(metric_hash)
159
- @backtraces.each do |meta_with_backtrace|
160
- metric_hash.keys.find { |k| k == meta_with_backtrace }.backtrace = meta_with_backtrace.backtrace
161
- end
162
- metric_hash
163
- end
87
+ def skip_layer?(layer); super(layer) || layer == queue_layer; end
88
+ def queue_layer; layer_finder.queue; end
89
+ def job_layer; layer_finder.job; end
164
90
  end
165
91
  end
166
92
  end