Class: ScoutApm::Layer

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_apm/layer.rb

Constant Summary collapse

BACKTRACE_CALLER_LIMIT =

maximum number of lines to send thru for backtrace analysis

30

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, name, start_time = Time.now) ⇒ Layer

Returns a new instance of Layer.



35
36
37
38
39
40
41
# File 'lib/scout_apm/layer.rb', line 35

def initialize(type, name, start_time = Time.now)
  @type = type
  @name = name
  @start_time = start_time
  @children = [] # In order of calls
  @desc = nil
end

Instance Attribute Details

#backtraceObject (readonly)

If this layer took longer than a fixed amount of time, store the backtrace of where it occurred.



31
32
33
# File 'lib/scout_apm/layer.rb', line 31

def backtrace
  @backtrace
end

#childrenObject (readonly)

An array of children layers, in call order. 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



18
19
20
# File 'lib/scout_apm/layer.rb', line 18

def children
  @children
end

#descObject

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



27
28
29
# File 'lib/scout_apm/layer.rb', line 27

def desc
  @desc
end

#nameObject (readonly)

Name: a more specific name of this single item

Examples: "Rack::Cache", "User#find", "users/index", "users/index.html.erb"


10
11
12
# File 'lib/scout_apm/layer.rb', line 10

def name
  @name
end

#start_timeObject (readonly)

Time objects recording the start & stop times of this layer



21
22
23
# File 'lib/scout_apm/layer.rb', line 21

def start_time
  @start_time
end

#stop_timeObject (readonly)

Time objects recording the start & stop times of this layer



21
22
23
# File 'lib/scout_apm/layer.rb', line 21

def stop_time
  @stop_time
end

#typeObject (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



43
44
45
# File 'lib/scout_apm/layer.rb', line 43

def add_child(child)
  @children << child
end

#caller_arrayObject

In Ruby 2.0+, we can pass the range directly to the caller to reduce the memory footprint.



76
77
78
79
80
81
82
83
# File 'lib/scout_apm/layer.rb', line 76

def caller_array
  # omits the first several callers which are in the ScoutAPM stack.
  if ScoutApm::Environment.instance.ruby_2?
    caller(3...BACKTRACE_CALLER_LIMIT)
  else
    caller[3...BACKTRACE_CALLER_LIMIT]
  end
end

#capture_backtrace!Object



70
71
72
73
# File 'lib/scout_apm/layer.rb', line 70

def capture_backtrace!
  ScoutApm::Agent.instance.logger.debug { "Capturing Backtrace for Layer [#{type}/#{name}]" }
  @backtrace = caller_array
end

#child_timeObject



121
122
123
124
125
# File 'lib/scout_apm/layer.rb', line 121

def child_time
  children.
    map { |child| child.total_call_time }.
    inject(0) { |sum, time| sum + time }
end

#legacy_metric_nameObject

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.



66
67
68
# File 'lib/scout_apm/layer.rb', line 66

def legacy_metric_name
  "#{type}/#{name}"
end

#record_stop_time!(stop_time = Time.now) ⇒ Object



47
48
49
# File 'lib/scout_apm/layer.rb', line 47

def record_stop_time!(stop_time = Time.now)
  @stop_time = stop_time
end

#subscopable!Object



55
56
57
# File 'lib/scout_apm/layer.rb', line 55

def subscopable!
  @subscopable = true
end

#subscopable?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/scout_apm/layer.rb', line 59

def subscopable?
  @subscopable
end

#to_sObject

May not be safe to call in every rails app, relies on Time#iso8601



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/scout_apm/layer.rb', line 90

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_call_timeObject

Time Calculations



108
109
110
111
112
113
114
115
# File 'lib/scout_apm/layer.rb', line 108

def total_call_time
  if stop_time
    stop_time - start_time
  else
    # Shouldn't have called this yet. Return 0
    0
  end
end

#total_exclusive_timeObject



117
118
119
# File 'lib/scout_apm/layer.rb', line 117

def total_exclusive_time
  total_call_time - child_time
end