|
4 | 4 |
|
5 | 5 | module Perf |
6 | 6 |
|
| 7 | + # Calculate cpu util for a time period, use start() and end() |
7 | 8 | class System |
8 | 9 | attr_reader :hostname |
9 | 10 |
|
10 | 11 | def initialize(node, data = {}) |
11 | 12 | @node = node |
12 | | - @hostname = node.hostname |
| 13 | + @hostname = node.hostname unless node == nil |
13 | 14 | @data = data |
14 | 15 | @start_cpu_used = 0 |
15 | 16 | @start_cpu_total = 0 |
16 | 17 | @end_cpu_used = 0 |
17 | 18 | @end_cpu_total = 0 |
18 | | - @ysar_binary = propose_ysar_gather # TODO Remove dependency on internal tooling |
19 | 19 | end |
20 | 20 |
|
21 | | - def propose_ysar_gather |
22 | | - @ysar_binary = "#{Environment.instance.vespa_home}/sbin/ysar_gather" |
23 | | - @ysar_binary = "/usr/sbin/ysar_gather" unless has_ysar |
| 21 | + # For unit testing |
| 22 | + def self.create_for_testing(hostname) |
| 23 | + @hostname = hostname |
| 24 | + new(nil) |
24 | 25 | end |
25 | 26 |
|
26 | | - def has_ysar |
27 | | - @node.file?(@ysar_binary) |
| 27 | + def cpu_usage |
| 28 | + calculate_cpu_usage(@node.execute("cat /proc/stat", :noecho => true)) |
28 | 29 | end |
29 | 30 |
|
30 | | - def ysar_gather_cmd |
31 | | - "#{@ysar_binary} --list --delay-mode=none" |
32 | | - end |
33 | | - |
34 | | - def load |
35 | | - unless has_ysar |
36 | | - return [0, 0] |
37 | | - end |
38 | | - output = @node.execute(ysar_gather_cmd, :noecho => true) |
39 | | - output.split("\n").each do |l| |
40 | | - if l =~ /^cput=/ |
41 | | - key,value = l.split('=') |
42 | | - values = value.split(',').collect(&:to_i) |
43 | | - |
| 31 | + def calculate_cpu_usage(stat_output) |
| 32 | + # See 'man proc_stat' for format. Basically this sums all cpu usage types and subtracts idle time to find cpu used |
| 33 | + stat_output.split("\n").each do |line| |
| 34 | + if line =~ /^cpu / |
| 35 | + values = line.split(' ').collect(&:to_i) |
| 36 | + values.delete(0) # Remove first item ('cpu') |
44 | 37 | total = values.inject(:+) |
45 | | - used = total - values[4] |
| 38 | + # Subtract idle time to find cpu usage |
| 39 | + used = total - values[3] |
46 | 40 |
|
47 | 41 | return [used, total] |
48 | 42 | end |
49 | 43 | end |
50 | 44 |
|
51 | | - return [0, 0] |
| 45 | + [0, 0] |
52 | 46 | end |
53 | 47 |
|
54 | 48 | def start |
55 | | - @start_cpu_used, @start_cpu_total = load |
| 49 | + @start_cpu_used, @start_cpu_total = cpu_usage |
56 | 50 | end |
57 | 51 |
|
58 | 52 | def end |
59 | | - @end_cpu_used, @end_cpu_total = load |
60 | | - cpu_util = (@end_cpu_used - @start_cpu_used).to_f / (@end_cpu_total - @start_cpu_total) |
| 53 | + @end_cpu_used, @end_cpu_total = cpu_usage |
| 54 | + set_cpu_util([@start_cpu_used, @start_cpu_total], [@end_cpu_used, @end_cpu_total]) |
| 55 | + end |
| 56 | + |
| 57 | + def set_cpu_util(start_data, end_data) |
| 58 | + cpu_util = (end_data[0] - start_data[0]).to_f / (end_data[1] - start_data[1]).to_f |
61 | 59 | @data['cpuutil'] = cpu_util.nan? ? 0.0 : cpu_util |
62 | 60 | end |
63 | 61 |
|
| 62 | + def cpu_util |
| 63 | + @data['cpuutil'] |
| 64 | + end |
| 65 | + |
64 | 66 | def fill |
65 | 67 | Proc.new do |result| |
66 | 68 | result.add_metric('cpuutil', @data['cpuutil'], @hostname) |
|
0 commit comments