Class: ScoutApm::Instruments::Process::ProcessCpu

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_apm/instruments/process/process_cpu.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context) ⇒ ProcessCpu

Returns a new instance of ProcessCpu.

[View source]

9
10
11
12
13
14
15
16
17
18
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 9

def initialize(context)
  @context = context

  @num_processors = [context.environment.processors, 1].compact.max

  t = ::Process.times
  @last_run = Time.now
  @last_utime = t.utime
  @last_stime = t.stime
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.


7
8
9
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 7

def context
  @context
end

#last_runObject

Returns the value of attribute last_run.


6
7
8
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 6

def last_run
  @last_run
end

#last_stimeObject

Returns the value of attribute last_stime.


6
7
8
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 6

def last_stime
  @last_stime
end

#last_utimeObject

Returns the value of attribute last_utime.


6
7
8
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 6

def last_utime
  @last_utime
end

#num_processorsObject (readonly)

Returns the value of attribute num_processors.


5
6
7
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 5

def num_processors
  @num_processors
end

Instance Method Details

#human_nameObject

[View source]

28
29
30
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 28

def human_name
  "Process CPU"
end

#loggerObject

[View source]

102
103
104
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 102

def logger
  context.logger
end

#metric_nameObject

[View source]

24
25
26
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 24

def metric_name
  "Utilization"
end

#metric_typeObject

[View source]

20
21
22
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 20

def metric_type
  "CPU"
end

#metrics(timestamp, store) ⇒ Object

[View source]

32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 32

def metrics(timestamp, store)
  result = run
  if result
    meta = MetricMeta.new("#{metric_type}/#{metric_name}")
    stat = MetricStats.new(false)
    stat.update!(result)
    store.track!({ meta => stat }, :timestamp => timestamp)
  else
    {}
  end

end

#runObject

TODO: Figure out a good default instead of nil

[View source]

46
47
48
49
50
51
52
53
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 46

def run
  res = nil

  t = ::Process.times
  now = Time.now
  utime = t.utime
  stime = t.stime

  wall_clock_elapsed  = now - last_run
  if wall_clock_elapsed < 0
    save_times(now, utime, stime)
    logger.info "#{human_name}: Negative time elapsed.  now: #{now}, last_run: #{last_run}, total time: #{wall_clock_elapsed}."
    return nil
  end

  utime_elapsed   = utime - last_utime
  stime_elapsed   = stime - last_stime
  process_elapsed = utime_elapsed + stime_elapsed

  # This can happen right after a fork.  This class starts up in
  # pre-fork, records {u,s}time, then forks. This resets {u,s}time to 0
  if process_elapsed < 0
    save_times(now, utime, stime)
    logger.debug "#{human_name}: Negative process time elapsed.  utime: #{utime_elapsed}, stime: #{stime_elapsed}, total time: #{process_elapsed}. This is normal to see when starting a forking web server."
    return nil
  end

  # Normalized to # of processors
  normalized_wall_clock_elapsed = wall_clock_elapsed * num_processors

  # If somehow we run for 0 seconds between calls, don't try to divide by 0
  res = if normalized_wall_clock_elapsed == 0
          0
        else
          ( process_elapsed / normalized_wall_clock_elapsed )*100
        end

  if res < 0
    save_times(now, utime, stime)
    logger.info "#{human_name}: Negative CPU.  #{process_elapsed} / #{normalized_wall_clock_elapsed} * 100 ==> #{res}"
    return nil
  end

  save_times(now, utime, stime)

  logger.debug "#{human_name}: #{res.inspect} [#{num_processors} CPU(s)]"

  return res
end

#save_times(now, utime, stime) ⇒ Object

[View source]

96
97
98
99
100
# File 'lib/scout_apm/instruments/process/process_cpu.rb', line 96

def save_times(now, utime, stime)
  self.last_run = now
  self.last_utime = utime
  self.last_stime = stime
end