Module: Beaker::DSL::BeakerBenchmark::Helpers

Includes:
HostPrebuiltSteps
Included in:
Beaker::DSL::BeakerBenchmark
Defined in:
lib/beaker-benchmark/helpers.rb

Defined Under Namespace

Classes: PerformanceResult

Constant Summary collapse

MEASURE_TYPE_INDEX =

Column indexes for atop CSV style output

0
SYSTEM_CPU_INDEX =
8
USR_CPU_INDEX =
9
IOWAIT_CPU_INDEX =
12
IDLE_CPU_INDEX =
11
MEM_INDEX =
10
DISK_READ_INDEX =
9
DISK_WRITE_INDEX =
11
PROC_PID_INDEX =
6
PROC_CPU_INDEX =
16
PROC_MEM_INDEX =
11
PROC_DISK_READ_INDEX =
11
PROC_DISK_WRITE_INDEX =
13
TMP_DIR =
"tmp/atop/#{@@session_timestamp}"
@@session_timestamp =
Time.now.getutc.to_i

Instance Method Summary collapse

Instance Method Details

#add_process_measure(measure_type, pid, value) ⇒ Object



160
161
162
163
164
# File 'lib/beaker-benchmark/helpers.rb', line 160

def add_process_measure measure_type, pid, value
  if @processes_to_monitor.keys.include? pid
    @processes_to_monitor[pid][measure_type].push value
  end
end

#measure_perf_on(infrastructure_host, action_name, include_processes = false, process_regex = '/opt/puppetlabs', &block) ⇒ Object

test_name(‘measure_perf_on_puppetserver_start’) {

on(master, 'puppet resource service pe-puppetserver ensure=stopped')
result = measure_perf_on(master, 'start_pe-puppetserver', true) {
  on(master, 'puppet resource service pe-puppetserver ensure=running')
  # on(master, 'facter fqdn')
}
raise("pe-puppetserver restart took longer than 120 seconds: #{result.duration} seconds") if result.duration > 120
raise("pe-puppetserver restart used an average of more than 1gb of memory: #{result.avg_mem} bytes") if result.avg_mem > 1073741824
process_cpu = result.processes.select{ |pid, process| process[:cmd] =~ /puppet-server-release.jar/ }.values[0][:avg_cpu]
raise("pe-puppetserver restart caused pe-puppetserver service to use more than 95% of CPU: #{process_cpu}") if process_cpu > 95

}



48
49
50
51
52
53
54
55
56
57
# File 'lib/beaker-benchmark/helpers.rb', line 48

def measure_perf_on(infrastructure_host, action_name, include_processes=false, process_regex='/opt/puppetlabs', &block)
  # Append action name to test case name if test name is available
  action_name = [:case][:name] + "_#{action_name}" if defined?  && [:case] && [:case][:name]

  start_monitoring(infrastructure_host, action_name, include_processes)

  yield

  stop_monitoring(infrastructure_host, include_processes.nil? ? nil : process_regex)
end

#parse_atop_log(infrastructure_host, duration) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/beaker-benchmark/helpers.rb', line 99

def parse_atop_log(infrastructure_host, duration)
  unless infrastructure_host.file_exist?(@atop_log_filename)
    raise("atop log does not exist at #{@atop_log_filename}")
  end

  log_dir = "#{TMP_DIR}/#{infrastructure_host.hostname}"
  FileUtils::mkdir_p log_dir unless Dir.exist? log_dir
  scp_from(infrastructure_host, @atop_log_filename, log_dir)
  cpu_usage  = []
  mem_usage  = []
  disk_read  = []
  disk_write = []

  skip        = true
  CSV.parse(File.read(File.expand_path(@atop_log_filename, log_dir)), { :col_sep => ' ' }) do |row|
    #skip the first entry, until the first separator 'SEP'.
    measure_type = row[MEASURE_TYPE_INDEX]
    if skip
      skip = (measure_type != 'SEP')
      next
    end
    case measure_type
      when 'CPU'
        # system + usr + iowait
        cpu_active = row[SYSTEM_CPU_INDEX].to_i + row[USR_CPU_INDEX].to_i + row[IOWAIT_CPU_INDEX].to_i
        # active + idle
        cpu_total = cpu_active + row[IDLE_CPU_INDEX].to_i
        cpu_percent = cpu_active * 100 / cpu_total
        cpu_usage.push(cpu_percent)
      when 'SWP'
        mem_usage.push(row[MEM_INDEX].to_i)
      when 'DSK'
        disk_read.push(row[DISK_READ_INDEX].to_i)
        disk_write.push(row[DISK_WRITE_INDEX].to_i)
      when 'PRC'
        add_process_measure(:cpu_usage, row[PROC_PID_INDEX], row[PROC_CPU_INDEX].to_i)
      when 'PRM'
        add_process_measure(:mem_usage, row[PROC_PID_INDEX], row[PROC_MEM_INDEX].to_i)
      when 'PRD'
        # TODO: investigate why atop always shows disk_read as 0
        # add_process_measure(:disk_read, row[PROC_PID_INDEX], row[PROC_DISK_READ_INDEX].to_i)
        add_process_measure(:disk_write, row[PROC_PID_INDEX], row[PROC_DISK_WRITE_INDEX].to_i)
    end
  end

  PerformanceResult.new({ :cpu => cpu_usage, :mem => mem_usage, :disk_read => disk_read, :disk_write => disk_write, :action => @action_name, :duration => duration, :processes => @processes_to_monitor, :logger => @logger, :hostname => infrastructure_host})
end

#set_processes_to_monitor(infrastructure_host, process_regex) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/beaker-benchmark/helpers.rb', line 147

def set_processes_to_monitor(infrastructure_host, process_regex)
  @processes_to_monitor = {}
  return unless process_regex
  result = on(infrastructure_host, "ps -eo pid,cmd | grep #{process_regex}").output
  result.each_line do |line|
    # use the PID as key and command with args as value
    # also ignore the ps and grep commands executed above.
    unless line.include? "grep #{process_regex}"
      @processes_to_monitor[line.split(' ').first] = { :cmd => line.split(' ')[1..-1].join(' '), :cpu_usage => [], :mem_usage => [], :disk_read => [], :disk_write => [] }
    end
  end
end

#setup_atop(infrastructure_host) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/beaker-benchmark/helpers.rb', line 59

def setup_atop(infrastructure_host)
  # Only install atop once per host
  unless infrastructure_host.check_for_package('atop')
    add_el_extras(infrastructure_host, @options)
    infrastructure_host.install_package('atop')
  end
end

#start_monitoring(infrastructure_host, action_name, include_processes = false, sample_interval = 1) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/beaker-benchmark/helpers.rb', line 67

def start_monitoring(infrastructure_host, action_name, include_processes=false, sample_interval=1)
  raise('Monitoring already in progress, call stop_monitoring before calling start_monitoring a second time') unless @beaker_benchmark_start.nil?
  @atop_log_filename = "atop_log_#{action_name.downcase.gsub(/[^a-z0-9]/i, '_')}.log"
  @action_name       = action_name
  setup_atop(infrastructure_host)
  additional_args = ''
  additional_args = ',PRC,PRM,PRD' if include_processes
  atop_cmd        = "sh -c 'nohup atop -P CPU,SWP,DSK#{additional_args} -i #{sample_interval} >  #{@atop_log_filename} 2>&1 &'"

  on(infrastructure_host, atop_cmd)
  @beaker_benchmark_start = Time.now
  return @@session_timestamp
end

#stop_monitoring(infrastructure_host, process_regex = '.*') ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/beaker-benchmark/helpers.rb', line 81

def stop_monitoring(infrastructure_host, process_regex='.*')
  begin
    if defined?@beaker_benchmark_start && !@beaker_benchmark_start.nil?
      duration = Time.now - @beaker_benchmark_start
    else
      raise('No monitoring in progress, call start_monitoring before calling stop_monitoring')
    end

    # The atop process sticks around unless killed
    # It can also take some time to kill depending on how long it has been running and sampling rate.
    retry_on infrastructure_host, 'pkill -15 -f atop', {:max_retries => 3, :retry_interval => 5}
    set_processes_to_monitor(infrastructure_host, process_regex)
    parse_atop_log(infrastructure_host, duration)
  ensure
    @beaker_benchmark_start = nil
  end
end