Class: ScoutApm::Layer
- Inherits:
-
Object
- Object
- ScoutApm::Layer
- Defined in:
- lib/scout_apm/layer.rb
Constant Summary collapse
- BACKTRACE_CALLER_LIMIT =
maximum number of lines to send thru for backtrace analysis
50
Instance Attribute Summary collapse
-
#allocations_start ⇒ Object
readonly
Returns the value of attribute allocations_start.
-
#allocations_stop ⇒ Object
readonly
Returns the value of attribute allocations_stop.
-
#annotations ⇒ Object
readonly
As we go through a part of a request, instrumentation can store additional data Known Keys: :record_count - The number of rows returned by an AR query (From notification instantiation.active_record) :class_name - The ActiveRecord class name (From notification instantiation.active_record).
-
#backtrace ⇒ Object
readonly
If this layer took longer than a fixed amount of time, store the backtrace of where it occurred.
-
#desc ⇒ Object
The description of this layer.
-
#name ⇒ Object
Name: a more specific name of this single item Examples: “Rack::Cache”, “User#find”, “users/index”, “users/index.html.erb”.
-
#start_time ⇒ Object
readonly
Time objects recording the start & stop times of this layer.
-
#stop_time ⇒ Object
readonly
Time objects recording the start & stop times of this layer.
-
#type ⇒ Object
readonly
Type: a general name for the kind of thing being tracked.
Instance Method Summary collapse
- #add_child(child) ⇒ Object
-
#annotate_layer(hsh) ⇒ Object
This data is internal to ScoutApm, to add custom information, use the Context api.
-
#caller_array ⇒ Object
In Ruby 2.0+, we can pass the range directly to the caller to reduce the memory footprint.
- #capture_backtrace! ⇒ Object
-
#children ⇒ Object
An array of children layers For instance, if we are in a middleware, there will likely be only a single child, which is another middleware.
-
#initialize(type, name, start_time = Time.now) ⇒ Layer
constructor
A new instance of Layer.
-
#legacy_metric_name ⇒ Object
This is the old style name.
- #limited? ⇒ Boolean
-
#record_allocations! ⇒ Object
Fetch the current number of allocated objects.
- #record_stop_time!(stop_time = Time.now) ⇒ Object
- #subscopable! ⇒ Object
- #subscopable? ⇒ Boolean
-
#to_s ⇒ Object
May not be safe to call in every rails app, relies on Time#iso8601.
-
#total_allocations ⇒ Object
These are almost identical to the timing metrics.
-
#total_call_time ⇒ Object
Time Calculations.
- #total_exclusive_allocations ⇒ Object
- #total_exclusive_time ⇒ Object
Constructor Details
#initialize(type, name, start_time = Time.now) ⇒ Layer
Returns a new instance of Layer.
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/scout_apm/layer.rb', line 53 def initialize(type, name, start_time = Time.now) @type = type @name = name @start_time = start_time @allocations_start = ScoutApm::Instruments::Allocations.count @allocations_stop = 0 # initialize these only on first use @children = nil @annotations = nil @desc = nil end |
Instance Attribute Details
#allocations_start ⇒ Object (readonly)
Returns the value of attribute allocations_start.
49 50 51 |
# File 'lib/scout_apm/layer.rb', line 49 def allocations_start @allocations_start end |
#allocations_stop ⇒ Object (readonly)
Returns the value of attribute allocations_stop.
49 50 51 |
# File 'lib/scout_apm/layer.rb', line 49 def allocations_stop @allocations_stop end |
#annotations ⇒ Object (readonly)
As we go through a part of a request, instrumentation can store additional data Known Keys:
:record_count - The number of rows returned by an AR query (From notification instantiation.active_record)
:class_name - The ActiveRecord class name (From notification instantiation.active_record)
If no annotations are ever set, this will return nil
47 48 49 |
# File 'lib/scout_apm/layer.rb', line 47 def annotations @annotations end |
#backtrace ⇒ Object (readonly)
If this layer took longer than a fixed amount of time, store the backtrace of where it occurred.
39 40 41 |
# File 'lib/scout_apm/layer.rb', line 39 def backtrace @backtrace end |
#desc ⇒ Object
The description of this layer. Will contain additional details specific to the type of layer. For an ActiveRecord metric, it will contain the SQL run For an outoing HTTP call, it will contain the remote URL accessed Leave blank if there is nothing to note
35 36 37 |
# File 'lib/scout_apm/layer.rb', line 35 def desc @desc end |
#name ⇒ Object
Name: a more specific name of this single item
Examples: "Rack::Cache", "User#find", "users/index", "users/index.html.erb"
Accessor, so we can update a layer if multiple pieces of instrumentation work
together at different layers to fill in the full data. See the ActiveRecord
instrumentation for an example of how this is useful
14 15 16 |
# File 'lib/scout_apm/layer.rb', line 14 def name @name end |
#start_time ⇒ Object (readonly)
Time objects recording the start & stop times of this layer
29 30 31 |
# File 'lib/scout_apm/layer.rb', line 29 def start_time @start_time end |
#stop_time ⇒ Object (readonly)
Time objects recording the start & stop times of this layer
29 30 31 |
# File 'lib/scout_apm/layer.rb', line 29 def stop_time @stop_time end |
#type ⇒ Object (readonly)
Type: a general name for the kind of thing being tracked.
Examples: "Middleware", "ActiveRecord", "Controller", "View"
6 7 8 |
# File 'lib/scout_apm/layer.rb', line 6 def type @type end |
Instance Method Details
#add_child(child) ⇒ Object
70 71 72 73 |
# File 'lib/scout_apm/layer.rb', line 70 def add_child(child) @children ||= LayerChildrenSet.new @children << child end |
#annotate_layer(hsh) ⇒ Object
This data is internal to ScoutApm, to add custom information, use the Context api.
89 90 91 92 |
# File 'lib/scout_apm/layer.rb', line 89 def annotate_layer(hsh) @annotations ||= {} @annotations.merge!(hsh) end |
#caller_array ⇒ Object
In Ruby 2.0+, we can pass the range directly to the caller to reduce the memory footprint.
114 115 116 117 118 119 120 121 |
# File 'lib/scout_apm/layer.rb', line 114 def caller_array # omits the first several callers which are in the ScoutAPM stack. if ScoutApm::Agent.instance.context.environment.ruby_2? caller(3...BACKTRACE_CALLER_LIMIT) else caller[3...BACKTRACE_CALLER_LIMIT] end end |
#capture_backtrace! ⇒ Object
109 110 111 |
# File 'lib/scout_apm/layer.rb', line 109 def capture_backtrace! @backtrace = caller_array end |
#children ⇒ Object
An array of children layers For instance, if we are in a middleware, there will likely be only a single child, which is another middleware. In a Controller, we may have a handful of children: [ActiveRecord, ActiveRecord, View, HTTP Call].
This useful to get actual time spent in this layer vs. children time
TODO: Check callers for compatibility w/ nil to avoid making an empty array
24 25 26 |
# File 'lib/scout_apm/layer.rb', line 24 def children @children || LayerChildrenSet.new end |
#legacy_metric_name ⇒ Object
This is the old style name. This function is used for now, but should be removed, and the new type & name split should be enforced through the app.
105 106 107 |
# File 'lib/scout_apm/layer.rb', line 105 def legacy_metric_name "#{type}/#{name}" end |
#limited? ⇒ Boolean
66 67 68 |
# File 'lib/scout_apm/layer.rb', line 66 def limited? false end |
#record_allocations! ⇒ Object
Fetch the current number of allocated objects. This will always increment - we fetch when initializing and when stopping the layer.
80 81 82 |
# File 'lib/scout_apm/layer.rb', line 80 def record_allocations! @allocations_stop = ScoutApm::Instruments::Allocations.count end |
#record_stop_time!(stop_time = Time.now) ⇒ Object
75 76 77 |
# File 'lib/scout_apm/layer.rb', line 75 def record_stop_time!(stop_time = Time.now) @stop_time = stop_time end |
#subscopable! ⇒ Object
94 95 96 |
# File 'lib/scout_apm/layer.rb', line 94 def subscopable! @subscopable = true end |
#subscopable? ⇒ Boolean
98 99 100 |
# File 'lib/scout_apm/layer.rb', line 98 def subscopable? @subscopable end |
#to_s ⇒ Object
May not be safe to call in every rails app, relies on Time#iso8601
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/scout_apm/layer.rb', line 128 def to_s name_clause = "#{type}/#{name}" total_string = total_call_time == 0 ? nil : "Total: #{total_call_time}" self_string = total_exclusive_time == 0 ? nil : "Self: #{total_exclusive_time}" timing_string = [total_string, self_string].compact.join(", ") time_clause = "(Start: #{start_time.iso8601} / Stop: #{stop_time.try(:iso8601)} [#{timing_string}])" desc_clause = "Description: #{desc.inspect}" children_clause = "Children: #{children.length}" "<Layer: #{name_clause} #{time_clause} #{desc_clause} #{children_clause}>" end |
#total_allocations ⇒ Object
These are almost identical to the timing metrics.
171 172 173 174 175 176 177 178 |
# File 'lib/scout_apm/layer.rb', line 171 def total_allocations if @allocations_stop > 0 allocations = (@allocations_stop - @allocations_start) else allocations = (ScoutApm::Instruments::Allocations.count - @allocations_start) end allocations < 0 ? 0 : allocations end |
#total_call_time ⇒ Object
Time Calculations
146 147 148 149 150 151 152 |
# File 'lib/scout_apm/layer.rb', line 146 def total_call_time if stop_time stop_time - start_time else Time.now - start_time end end |
#total_exclusive_allocations ⇒ Object
180 181 182 |
# File 'lib/scout_apm/layer.rb', line 180 def total_exclusive_allocations total_allocations - child_allocations end |
#total_exclusive_time ⇒ Object
154 155 156 |
# File 'lib/scout_apm/layer.rb', line 154 def total_exclusive_time total_call_time - child_time end |