Module: NewRelic::Agent::BusyCalculator

Extended by:
BusyCalculator
Included in:
BusyCalculator
Defined in:
lib/new_relic/agent/busy_calculator.rb

Overview

This module supports calculation of actual time spent processing requests over the course of one harvest period. It’s similar to what you would get if you just added up all the execution times of controller calls, however that will be inaccurate when requests span the minute boundaries. This module manages accounting of requests not yet completed.

Calls are re-entrant. All start calls must be paired with finish calls, or a reset call.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#accumulatorObject (readonly)

For testability, add accessors:



13
14
15
# File 'lib/new_relic/agent/busy_calculator.rb', line 13

def accumulator
  @accumulator
end

#harvest_startObject (readonly)

For testability, add accessors:



13
14
15
# File 'lib/new_relic/agent/busy_calculator.rb', line 13

def harvest_start
  @harvest_start
end

Instance Method Details

#busy_countObject



37
38
39
# File 'lib/new_relic/agent/busy_calculator.rb', line 37

def busy_count
  @entrypoint_stack.size
end

#dispatcher_finish(end_time = Time.now.to_f) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/new_relic/agent/busy_calculator.rb', line 24

def dispatcher_finish(end_time = Time.now.to_f)
  callers = Thread.current[:busy_entries] -= 1
  # Ignore nested calls
  return if callers > 0
  @lock.synchronize do
    if @entrypoint_stack.empty?
      NewRelic::Control.instance.log.error("Stack underflow tracking dispatcher entry and exit!\n  #{caller.join("  \n")}") 
    else
      @accumulator += (end_time - @entrypoint_stack.pop)
    end
  end
end

#dispatcher_start(time) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/new_relic/agent/busy_calculator.rb', line 15

def dispatcher_start(time)
  Thread.current[:busy_entries] ||= 0 
  callers = Thread.current[:busy_entries] += 1
  return if callers > 1
  @lock.synchronize do
    @entrypoint_stack.push time      
  end
end

#harvest_busyObject

Called before uploading to to the server to collect current busy stats.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/new_relic/agent/busy_calculator.rb', line 54

def harvest_busy
  busy = 0
  t0 = Time.now.to_f
  @lock.synchronize do
    busy = accumulator
    @accumulator = 0
    
    # Walk through the stack and capture all times up to 
    # now for entrypoints
    @entrypoint_stack.size.times do |frame| 
      busy += (t0 - @entrypoint_stack[frame])
      @entrypoint_stack[frame] = t0
    end
    
  end
  
  busy = 0.0 if busy < 0.0 # don't go below 0%
  
  time_window = (t0 - harvest_start)
  time_window = 1.0 if time_window == 0.0  # protect against divide by zero
  
  busy = busy / time_window
  
  instance_busy_stats.record_data_point busy
  @harvest_start = t0
end

#resetObject

Reset the state of the information accumulated by all threads, but only reset the recursion counter for this thread.



43
44
45
46
47
48
49
# File 'lib/new_relic/agent/busy_calculator.rb', line 43

def reset
  @entrypoint_stack = []
  Thread.current[:busy_entries] = 0
  @lock ||= Mutex.new
  @accumulator = 0
  @harvest_start = Time.now.to_f
end