Class: ScoutApm::LayerSlowTransactionConverter

Inherits:
LayerConverterBase show all
Defined in:
lib/scout_apm/layer_converter.rb

Overview

Take a TrackedRequest and turn it into a slow transaction if needed return a 2 element array, [ Slow Transaction or Nil , Hash of metrics to store ]

Instance Attribute Summary

Attributes inherited from LayerConverterBase

#request, #root_layer, #walker

Instance Method Summary collapse

Methods inherited from LayerConverterBase

#initialize, #scope_layer

Constructor Details

This class inherits a constructor from ScoutApm::LayerConverterBase

Instance Method Details

#callObject



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
122
# File 'lib/scout_apm/layer_converter.rb', line 91

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.
  meta = MetricMeta.new("SlowTransaction/#{scope.legacy_metric_name}")
  stat = MetricStats.new
  stat.update!(1)

  uri = request.annotations[:uri] || ""

  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),
    { meta => stat }
  ]

end

#create_metricsObject

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.



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/scout_apm/layer_converter.rb', line 128

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|
    meta_options = 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
    meta_options.merge!(:desc => layer.desc.to_s) if layer.desc
    meta = MetricMeta.new(layer.legacy_metric_name, meta_options)
    meta.extra.merge!(:backtrace => ScoutApm::SlowTransaction.backtrace_parser(layer.backtrace)) if layer.backtrace
    metric_hash[meta] ||= MetricStats.new( meta_options.has_key?(:scope) )
    stat = metric_hash[meta]
    stat.update!(layer.total_call_time, layer.total_exclusive_time)

    # Merged Metric (no specifics, just sum up by type)
    meta = MetricMeta.new("#{layer.type}/all")
    metric_hash[meta] ||= MetricStats.new(false)
    stat = metric_hash[meta]
    stat.update!(layer.total_call_time, layer.total_exclusive_time)
  end

  metric_hash
end