Class: Solanum::Source::Cpu

Inherits:
Solanum::Source show all
Defined in:
lib/solanum/source/cpu.rb

Constant Summary collapse

STAT_FILE =
'/proc/stat'
STATES =
%w{user nice system idle iowait irqhard irqsoft}

Instance Attribute Summary collapse

Attributes inherited from Solanum::Source

#attributes, #period, #type

Instance Method Summary collapse

Methods inherited from Solanum::Source

#next_run

Constructor Details

#initialize(opts) ⇒ Cpu

Returns a new instance of Cpu.



11
12
13
14
15
16
17
# File 'lib/solanum/source/cpu.rb', line 11

def initialize(opts)
  super(opts)
  @last = nil
  @detailed = opts['detailed'] || false
  @per_core = opts['per_core'] || false
  @usage_states = opts['usage_states'] || {}
end

Instance Attribute Details

#detailedObject (readonly)

Returns the value of attribute detailed.



5
6
7
# File 'lib/solanum/source/cpu.rb', line 5

def detailed
  @detailed
end

#per_coreObject (readonly)

Returns the value of attribute per_core.



5
6
7
# File 'lib/solanum/source/cpu.rb', line 5

def per_core
  @per_core
end

#usage_statesObject (readonly)

Returns the value of attribute usage_states.



5
6
7
# File 'lib/solanum/source/cpu.rb', line 5

def usage_states
  @usage_states
end

Instance Method Details

#collect!Object

Collect metric events.



34
35
36
37
38
39
40
41
42
43
44
45
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/solanum/source/cpu.rb', line 34

def collect!
  # Parse lines from usage stats.
  lines = File.readlines(STAT_FILE).take_while {|l| l.start_with? 'cpu' }
  totals = {}
  lines.each do |line|
    name, data = parse_info(line)
    totals[name] = data
  end

  # Need at least one run to start reporting accurate metrics.
  unless @last
    @last = totals
    return []
  end

  # Calculate diffs from previous measurements.
  diffs = {}
  totals.each do |name, data|
    diffs[name] = Hash.new(0)
    data.each do |state, jiffies|
      last = @last[name] && @last[name][state]
      diffs[name][state] = jiffies - last if last
    end
  end
  @last = totals

  # Convert diffs to relative percentages.
  diffs.each do |name, diff|
    elapsed = diff.values.reduce(&:+)
    diff.keys.each do |state|
      diff[state] = diff[state].to_f/elapsed
    end
  end

  # Generate metric events.
  events = []

  # aggregate cpu usage
  usage = 1.0 - diffs['cpu']['idle']
  events << {
    service: 'cpu usage',
    metric: usage,
    state: state_over(@usage_states, usage),
  }

  # detailed aggregate cpu state metrics
  if @detailed
    diffs['cpu'].each do |state, usage|
      events << {
        service: 'cpu state',
        metric: usage,
        cpu_state: state,
      }
    end
  end

  # even more detailed per-core usage
  if @per_core
    diffs.each do |name, diff|
      next if name == 'cpu'

      usage = 1.0 - diff['idle']
      events << {
        service: 'cpu core usage',
        metric: usage,
        state: state_over(@usage_states, usage),
        cpu_core: name,
      }

      if @detailed
        diff.each do |state, usage|
          events << {
            service: 'cpu core state',
            metric: usage,
            cpu_core: name,
            cpu_state: state,
          }
        end
      end
    end
  end

  events
end

#parse_info(line) ⇒ Object

Calculate cpu utilization from the cumulative time spent in ‘jiffies’ (1/100 sec) since system boot.



22
23
24
25
26
27
28
29
30
# File 'lib/solanum/source/cpu.rb', line 22

def parse_info(line)
  fields = line.chomp.split(' ')
  name = fields.shift
  data = Hash.new(0)
  STATES.each_with_index do |state, i|
    data[state] = fields[i].to_i
  end
  return name, data
end