Class: Rack::ProcessUtilization

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/process_utilization.rb

Overview

Middleware that tracks the amount of time this process spends processing requests, as opposed to being idle waiting for a connection. Statistics are dumped to rack.errors every 5 minutes.

NOTE This middleware is not thread safe. It should only be used when rack.multiprocess is true and rack.multithread is false.

Defined Under Namespace

Classes: Body

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ ProcessUtilization

Returns a new instance of ProcessUtilization.



18
19
20
21
22
23
24
25
26
27
# File 'lib/rack/process_utilization.rb', line 18

def initialize(app, opts={})
  @app = app
  @window = opts[:window] || 100
  @horizon = nil
  @requests = nil
  @active_time = nil
  @total_requests = 0

  self.class.singleton = self
end

Class Attribute Details

.singletonObject

The instance of this middleware in a single-threaded production server. Useful for fetching stats about the current request:

o = Rack::ProcessUtilization.singleton
time, calls = o.gc_stats if o.track_gc?


15
16
17
# File 'lib/rack/process_utilization.rb', line 15

def singleton
  @singleton
end

Instance Attribute Details

#active_timeObject

decimal number of seconds the worker has been active within a request since the horizon time.



39
40
41
# File 'lib/rack/process_utilization.rb', line 39

def active_time
  @active_time
end

#horizonObject

time when we began sampling. this is reset every once in a while so averages don’t skew over time.



31
32
33
# File 'lib/rack/process_utilization.rb', line 31

def horizon
  @horizon
end

#requestsObject

total number of requests that have been processed by this worker since the horizon time.



35
36
37
# File 'lib/rack/process_utilization.rb', line 35

def requests
  @requests
end

#total_requestsObject

total requests processed by this worker process since it started



42
43
44
# File 'lib/rack/process_utilization.rb', line 42

def total_requests
  @total_requests
end

Instance Method Details

#average_response_timeObject

average response time since the horizon in milliseconds



71
72
73
# File 'lib/rack/process_utilization.rb', line 71

def average_response_time
  (active_time / requests.to_f) * 1000
end

#call(env) ⇒ Object

Rack entry point.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/rack/process_utilization.rb', line 125

def call(env)
  @env = env
  reset_stats

  @total_requests += 1
  first_request if @total_requests == 1

  env['process.request_start'] = @start.to_f
  env['process.total_requests'] = total_requests

  # newrelic X-Request-Start
  env.delete('HTTP_X_REQUEST_START')

  status, headers, body = @app.call(env)
  body = Body.new(body) { record_request }
  [status, headers, body]
end

#first_requestObject

called exactly once before the first request is processed by a worker



76
77
78
# File 'lib/rack/process_utilization.rb', line 76

def first_request
  reset_horizon
end

#horizon_timeObject

the amount of time since the horizon



45
46
47
# File 'lib/rack/process_utilization.rb', line 45

def horizon_time
  Time.now - horizon
end

#idle_timeObject

decimal number of seconds this process has been active since the horizon time. This is the inverse of the active time.



51
52
53
# File 'lib/rack/process_utilization.rb', line 51

def idle_time
  horizon_time - active_time
end

#percentage_activeObject

percentage of time this process has been active since the horizon time.



56
57
58
# File 'lib/rack/process_utilization.rb', line 56

def percentage_active
  (active_time / horizon_time) * 100
end

#percentage_idleObject

percentage of time this process has been idle since the horizon time.



61
62
63
# File 'lib/rack/process_utilization.rb', line 61

def percentage_idle
  (idle_time / horizon_time) * 100
end

#record_requestObject

called immediately after a request to record statistics, update the procline, and dump information to the logfile



94
95
96
97
98
99
100
101
102
103
# File 'lib/rack/process_utilization.rb', line 94

def record_request
  now = Time.now
  diff = (now - @start)
  @active_time += diff
  @requests += 1

  reset_horizon if now - horizon > @window
rescue => boom
  warn "ProcessUtilization#record_request failed: #{boom.inspect}"
end

#requests_per_secondObject

number of requests processed per second since the horizon



66
67
68
# File 'lib/rack/process_utilization.rb', line 66

def requests_per_second
  requests / horizon_time
end

#reset_horizonObject

resets the horizon and all dependent variables



86
87
88
89
90
# File 'lib/rack/process_utilization.rb', line 86

def reset_horizon
  @horizon = Time.now
  @active_time = 0.0
  @requests = 0
end

#reset_statsObject

reset various counters before the new request



81
82
83
# File 'lib/rack/process_utilization.rb', line 81

def reset_stats
  @start = Time.now
end