Class: ScoutApm::LayerConverters::SlowRequestConverter
- Inherits:
-
ConverterBase
- Object
- ConverterBase
- ScoutApm::LayerConverters::SlowRequestConverter
- Defined in:
- lib/scout_apm/layer_converters/slow_request_converter.rb
Instance Attribute Summary
Attributes inherited from ConverterBase
#request, #root_layer, #walker
Instance Method Summary collapse
-
#attach_backtraces(metric_hash) ⇒ Object
Iterates over the TrackedRequest’s MetricMetas that have backtraces and attaches each to correct MetricMeta in the Metric Hash.
- #call ⇒ Object
-
#create_metrics ⇒ Object
Full metrics from this request.
-
#initialize ⇒ SlowRequestConverter
constructor
A new instance of SlowRequestConverter.
Methods inherited from ConverterBase
Constructor Details
#initialize ⇒ SlowRequestConverter
Returns a new instance of SlowRequestConverter.
4 5 6 7 |
# File 'lib/scout_apm/layer_converters/slow_request_converter.rb', line 4 def initialize(*) @backtraces = [] # An Array of MetricMetas that have a backtrace super end |
Instance Method Details
#attach_backtraces(metric_hash) ⇒ Object
Iterates over the TrackedRequest’s MetricMetas that have backtraces and attaches each to correct MetricMeta in the Metric Hash.
50 51 52 53 54 55 |
# File 'lib/scout_apm/layer_converters/slow_request_converter.rb', line 50 def attach_backtraces(metric_hash) @backtraces.each do || metric_hash.keys.find { |k| k == }.backtrace = .backtrace end metric_hash end |
#call ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/scout_apm/layer_converters/slow_request_converter.rb', line 9 def call scope = scope_layer return [nil, {}] unless scope policy = ScoutApm::Agent.instance.slow_request_policy.capture_type(root_layer.total_call_time) if policy == ScoutApm::SlowRequestPolicy::CAPTURE_NONE return [nil, {}] end # increment the slow transaction count if this is a slow transaction. = MetricMeta.new("SlowTransaction/#{scope.legacy_metric_name}") stat = MetricStats.new stat.update!(1) uri = request.annotations[:uri] || "" ScoutApm::Agent.instance.config.value("ignore_traces").each do |pattern| if /#{pattern}/ =~ uri ScoutApm::Agent.instance.logger.debug("Skipped recording a trace for #{uri} due to `ignore_traces` pattern: #{pattern}") return [nil, { => stat }] end end metrics = create_metrics # Disable stackprof output for now stackprof = [] # request.stackprof [ SlowTransaction.new(uri, scope.legacy_metric_name, root_layer.total_call_time, metrics, request.context, root_layer.stop_time, stackprof), { => stat } ] end |
#create_metrics ⇒ Object
Full metrics from this request. These get aggregated in Store for the overview metrics, or stored permanently in a SlowTransaction Some merging of metrics will happen here, so if a request calls the same ActiveRecord or View repeatedly, it’ll get merged.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/scout_apm/layer_converters/slow_request_converter.rb', line 61 def create_metrics metric_hash = Hash.new # Keep a list of subscopes, but only ever use the front one. The rest # get pushed/popped in cases when we have many levels of subscopable # layers. This lets us push/pop without otherwise keeping track very closely. subscope_layers = [] walker.before do |layer| if layer.subscopable? subscope_layers.push(layer) end end walker.after do |layer| if layer.subscopable? subscope_layers.pop end end walker.walk do |layer| = if subscope_layers.first && layer != subscope_layers.first # Don't scope under ourself. subscope_name = subscope_layers.first.legacy_metric_name {:scope => subscope_name} elsif layer == scope_layer # We don't scope the controller under itself {} else {:scope => scope_layer.legacy_metric_name} end # Specific Metric .merge!(:desc => layer.desc.to_s) if layer.desc = MetricMeta.new(layer.legacy_metric_name, ) if layer.backtrace bt = ScoutApm::Utils::BacktraceParser.new(layer.backtrace).call if bt.any? # we could walk thru the call stack and not find in-app code .backtrace = bt # 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 lost in the # metric_hash if it is replaced by the new key. @backtraces << else ScoutApm::Agent.instance.logger.debug { "Unable to capture an app-specific backtrace for #{.inspect}\n#{layer.backtrace}" } end end metric_hash[] ||= MetricStats.new( .has_key?(:scope) ) stat = metric_hash[] stat.update!(layer.total_call_time, layer.total_exclusive_time) # Merged Metric (no specifics, just sum up by type) = MetricMeta.new("#{layer.type}/all") metric_hash[] ||= MetricStats.new(false) stat = metric_hash[] stat.update!(layer.total_call_time, layer.total_exclusive_time) end metric_hash = attach_backtraces(metric_hash) metric_hash end |