Class: ScoutApm::TrackedRequest

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTrackedRequest

Returns a new instance of TrackedRequest.



32
33
34
35
36
37
38
39
40
# File 'lib/scout_apm/tracked_request.rb', line 32

def initialize
  @layers = []
  @annotations = {}
  @ignoring_children = false
  @context = Context.new
  @root_layer = nil
  @stackprof = nil
  @error = false
end

Instance Attribute Details

#annotationsObject (readonly)

As we go through a request, instrumentation can mark more general data into the Request Known Keys:

:uri - the full URI requested by the user


22
23
24
# File 'lib/scout_apm/tracked_request.rb', line 22

def annotations
  @annotations
end

#contextObject (readonly)

Context is application defined extra information. (ie, which user, what is their email/ip, what plan are they on, what locale are they using, etc) See documentation for examples on how to set this from a before_filter



13
14
15
# File 'lib/scout_apm/tracked_request.rb', line 13

def context
  @context
end

#headersObject (readonly)

Headers as recorded by rails Can be nil if we never reach a Rails Controller



30
31
32
# File 'lib/scout_apm/tracked_request.rb', line 30

def headers
  @headers
end

#root_layerObject (readonly)

The first layer registered with this request. All other layers will be children of this layer.



17
18
19
# File 'lib/scout_apm/tracked_request.rb', line 17

def root_layer
  @root_layer
end

#stackprofObject (readonly)

Nil until the request is finalized, at which point it will hold the entire raw stackprof output for this request



26
27
28
# File 'lib/scout_apm/tracked_request.rb', line 26

def stackprof
  @stackprof
end

Instance Method Details

#acknowledge_children!Object



168
169
170
# File 'lib/scout_apm/tracked_request.rb', line 168

def acknowledge_children!
  @ignoring_children = false
end

#annotate_request(hsh) ⇒ Object

As we learn things about this request, we can add data here. For instance, when we know where Rails routed this request to, we can store that scope info. Or as soon as we know which URI it was directed at, we can store that.

This data is internal to ScoutApm, to add custom information, use the Context api.



104
105
106
# File 'lib/scout_apm/tracked_request.rb', line 104

def annotate_request(hsh)
  @annotations.merge!(hsh)
end

#error!Object

This request had an exception. Mark it down as an error



109
110
111
# File 'lib/scout_apm/tracked_request.rb', line 109

def error!
  @error = true
end

#error?Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/scout_apm/tracked_request.rb', line 113

def error?
  @error
end

#finalized?Boolean

Are we finished with this request? We’re done if we have no layers left after popping one off

Returns:

  • (Boolean)


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

def finalized?
  @layers.none?
end

#ignore_children!Object

Enable this when you would otherwise double track something interesting. This came up when we implemented InfluxDB instrumentation, which is more specific, and useful than the fact that InfluxDB happens to use Net::HTTP internally

When enabled, new layers won’t be added to the current Request.



164
165
166
# File 'lib/scout_apm/tracked_request.rb', line 164

def ignore_children!
  @ignoring_children = true
end

#record!Object

Convert this request to the appropriate structure, then report it into the peristent Store object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/scout_apm/tracked_request.rb', line 127

def record!
  @recorded = true

  metrics = LayerMetricConverter.new(self).call
  ScoutApm::Agent.instance.store.track!(metrics)

  slow, slow_metrics = LayerSlowTransactionConverter.new(self).call
  ScoutApm::Agent.instance.store.track_slow_transaction!(slow)
  ScoutApm::Agent.instance.store.track!(slow_metrics)

  error_metrics = LayerErrorConverter.new(self).call
  ScoutApm::Agent.instance.store.track!(error_metrics)

  queue_time_metrics = RequestQueueTime.new(self).call
  ScoutApm::Agent.instance.store.track!(queue_time_metrics)

  # ScoutApm::Agent.instance.logger.debug("Finished recording request") if metrics.any?
end

#recorded?Boolean

Have we already persisted this request? Used to know when we should just create a new one (don’t attempt to add data to an already-recorded request). See RequestManager

Returns:

  • (Boolean)


149
150
151
# File 'lib/scout_apm/tracked_request.rb', line 149

def recorded?
  @recorded
end

#set_headers(headers) ⇒ Object



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

def set_headers(headers)
  @headers = headers
end

#start_layer(layer) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/scout_apm/tracked_request.rb', line 42

def start_layer(layer)
  start_request(layer) unless @root_layer

  # ScoutApm::Agent.instance.logger.info("Starting Layer: #{layer.to_s}")
  @layers[-1].add_child(layer) if @layers.any?
  @layers.push(layer)
end

#start_request(layer) ⇒ Object

Run at the beginning of the whole request

  • Capture the first layer as the root_layer

  • Start Stackprof (disabling to avoid conflicts if stackprof is included as middleware since we aren’t sending this up to server now)



78
79
80
81
# File 'lib/scout_apm/tracked_request.rb', line 78

def start_request(layer)
  @root_layer = layer unless @root_layer # capture root layer
  #StackProf.start(:mode => :wall, :interval => ScoutApm::Agent.instance.config.value("stackprof_interval"))
end

#stop_layerObject



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/scout_apm/tracked_request.rb', line 50

def stop_layer
  layer = @layers.pop
  layer.record_stop_time!

  # Do this here, rather than in the layer because we need this caller. Maybe able to move it?
  if layer.total_exclusive_time > ScoutApm::SlowTransaction::BACKTRACE_THRESHOLD
    layer.store_backtrace(caller)
  end

  if finalized?
    stop_request
  end
end

#stop_requestObject

Run at the end of the whole request

  • Collect stackprof info

  • Send the request off to be stored



87
88
89
90
91
92
93
# File 'lib/scout_apm/tracked_request.rb', line 87

def stop_request
  # ScoutApm::Agent.instance.logger.debug("stop_request: #{annotations[:uri]}" )
  #StackProf.stop # disabling to avoid conflicts if stackprof is included as middleware since we aren't sending this up to server now
  #@stackprof = StackProf.results

  record!
end