perfmonger 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/.dir-locals.el +2 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +12 -0
  6. data/COPYING +674 -0
  7. data/Gemfile +5 -0
  8. data/HOWTO.md +15 -0
  9. data/NEWS +115 -0
  10. data/README.md +61 -0
  11. data/Rakefile +8 -0
  12. data/bin/perfmonger +6 -0
  13. data/data/NOTICE +8 -0
  14. data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
  15. data/data/assets/css/bootstrap-responsive.css +1109 -0
  16. data/data/assets/css/bootstrap.css +6167 -0
  17. data/data/assets/css/perfmonger.css +17 -0
  18. data/data/assets/dashboard.erb +319 -0
  19. data/data/assets/img/glyphicons-halflings-white.png +0 -0
  20. data/data/assets/img/glyphicons-halflings.png +0 -0
  21. data/data/assets/js/bootstrap.js +2280 -0
  22. data/data/assets/js/bootstrap.min.js +6 -0
  23. data/data/assets/js/canvasjs.js +9042 -0
  24. data/data/assets/js/canvasjs.min.js +271 -0
  25. data/data/sysstat.ioconf +268 -0
  26. data/ext/perfmonger/extconf.rb +19 -0
  27. data/ext/perfmonger/perfmonger.h +58 -0
  28. data/ext/perfmonger/perfmonger_record.c +754 -0
  29. data/ext/perfmonger/sysstat/common.c +627 -0
  30. data/ext/perfmonger/sysstat/common.h +207 -0
  31. data/ext/perfmonger/sysstat/ioconf.c +515 -0
  32. data/ext/perfmonger/sysstat/ioconf.h +84 -0
  33. data/ext/perfmonger/sysstat/iostat.c +1100 -0
  34. data/ext/perfmonger/sysstat/iostat.h +121 -0
  35. data/ext/perfmonger/sysstat/libsysstat.h +19 -0
  36. data/ext/perfmonger/sysstat/mpstat.c +953 -0
  37. data/ext/perfmonger/sysstat/mpstat.h +79 -0
  38. data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
  39. data/ext/perfmonger/sysstat/rd_stats.h +651 -0
  40. data/ext/perfmonger/sysstat/sysconfig.h +13 -0
  41. data/lib/perfmonger/cli.rb +115 -0
  42. data/lib/perfmonger/command/base_command.rb +39 -0
  43. data/lib/perfmonger/command/fingerprint.rb +453 -0
  44. data/lib/perfmonger/command/plot.rb +429 -0
  45. data/lib/perfmonger/command/record.rb +32 -0
  46. data/lib/perfmonger/command/record_option.rb +149 -0
  47. data/lib/perfmonger/command/server.rb +294 -0
  48. data/lib/perfmonger/command/stat.rb +60 -0
  49. data/lib/perfmonger/command/stat_option.rb +29 -0
  50. data/lib/perfmonger/command/summary.rb +402 -0
  51. data/lib/perfmonger/config.rb +6 -0
  52. data/lib/perfmonger/version.rb +5 -0
  53. data/lib/perfmonger.rb +12 -0
  54. data/misc/release-howto.txt +17 -0
  55. data/misc/sample-cpu.png +0 -0
  56. data/misc/sample-read-iops.png +0 -0
  57. data/perfmonger.gemspec +44 -0
  58. data/test/run-test.sh +39 -0
  59. data/test/spec/bin_spec.rb +37 -0
  60. data/test/spec/data/2devices.expected +42 -0
  61. data/test/spec/data/2devices.output +42 -0
  62. data/test/spec/spec_helper.rb +20 -0
  63. data/test/spec/summary_spec.rb +193 -0
  64. data/test/test-perfmonger.c +145 -0
  65. data/test/test.h +9 -0
  66. metadata +154 -0
@@ -0,0 +1,429 @@
1
+
2
+ require 'optparse'
3
+ require 'json'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+
7
+ module PerfMonger
8
+ module Command
9
+
10
+ class PlotCommand < BaseCommand
11
+ register_command 'plot', "Plot system performance graphs collected by 'record'"
12
+
13
+ def initialize
14
+ @parser = OptionParser.new
15
+ @parser.banner = <<EOS
16
+ Usage: perfmonger plot [options] LOG_FILE
17
+
18
+ Options:
19
+ EOS
20
+
21
+ @data_file = nil
22
+ @offset_time = 0.0
23
+ @output_dir = Dir.pwd
24
+ @output_type = 'pdf'
25
+ @output_prefix = ''
26
+ @save_gpfiles = false
27
+ end
28
+
29
+ def parse_args(argv)
30
+ @parser.on('--offset-time TIME') do |time|
31
+ @offset_time = Float(time)
32
+ end
33
+
34
+ @parser.on('-o', '--output-dir DIR') do |dir|
35
+ unless File.directory?(dir)
36
+ puts("ERROR: no such directory: #{dir}")
37
+ puts(@parser.help)
38
+ exit(false)
39
+ end
40
+
41
+ @output_dir = dir
42
+ end
43
+
44
+ @parser.on('-T', '--output-type TYPE', 'Available: pdf, png') do |typ|
45
+ unless ['pdf', 'png'].include?(typ)
46
+ puts("ERROR: non supported image type: #{typ}")
47
+ puts(@parser.help)
48
+ exit(false)
49
+ end
50
+
51
+ if typ != 'pdf' && ! system('which convert >/dev/null 2>&1')
52
+ puts("ERROR: convert(1) not found.")
53
+ puts("ERROR: ImageMagick is required for #{typ}")
54
+ puts(@parser.help)
55
+ exit(false)
56
+ end
57
+
58
+ @output_type = typ
59
+ end
60
+
61
+ @parser.on('-p', '--prefix PREFIX',
62
+ 'Output file name prefix.') do |prefix|
63
+ if ! (prefix =~ /-\Z/)
64
+ prefix += '-'
65
+ end
66
+
67
+ @output_prefix = prefix
68
+ end
69
+
70
+ @parser.on('-s', '--save',
71
+ 'Save GNUPLOT and data files.') do
72
+ @save_gpfiles = true
73
+ end
74
+
75
+
76
+ @parser.parse!(argv)
77
+
78
+ if argv.size == 0
79
+ puts("ERROR: PerfMonger log file is required")
80
+ puts(@parser.help)
81
+ exit(false)
82
+ end
83
+
84
+
85
+ @data_file = File.expand_path(argv.shift)
86
+ end
87
+
88
+ def run(argv)
89
+ parse_args(argv)
90
+ unless system('which gnuplot >/dev/null 2>&1')
91
+ puts("ERROR: gnuplot not found")
92
+ puts(@parser.help)
93
+ exit(false)
94
+ end
95
+
96
+ unless system('gnuplot -e "set terminal"|grep pdfcairo >/dev/null 2>&1')
97
+ puts("ERROR: pdfcairo is not supported by installed gnuplot")
98
+ puts("ERROR: PerfMonger requires pdfcairo-supported gnuplot")
99
+ puts(@parser.help)
100
+ exit(false)
101
+ end
102
+
103
+ plot_ioinfo()
104
+ plot_cpuinfo()
105
+ end
106
+
107
+ private
108
+ def plot_ioinfo()
109
+ iops_pdf_filename = @output_prefix + 'iops.pdf'
110
+ transfer_pdf_filename = @output_prefix + 'transfer.pdf'
111
+ gp_filename = @output_prefix + 'io.gp'
112
+ dat_filename = @output_prefix + 'io.dat'
113
+ if @output_type != 'pdf'
114
+ iops_img_filename = @output_prefix + 'iops.' + @output_type
115
+ transfer_img_filename = @output_prefix + 'transfer.' + @output_type
116
+ else
117
+ iops_img_filename = nil
118
+ transfer_img_filename = nil
119
+ end
120
+
121
+ Dir.mktmpdir do |working_dir|
122
+ Dir.chdir(working_dir) do
123
+ datafile = File.open(dat_filename, 'w')
124
+ gpfile = File.new(gp_filename, 'w')
125
+
126
+ start_time = nil
127
+ devices = nil
128
+
129
+ File.open(@data_file).each_line do |line|
130
+ record = JSON.parse(line)
131
+ time = record["time"]
132
+ ioinfo = record["ioinfo"]
133
+ return unless ioinfo
134
+
135
+ start_time ||= time
136
+ devices ||= ioinfo["devices"]
137
+
138
+ datafile.puts([time - start_time,
139
+ devices.map{|device|
140
+ [ioinfo[device]["riops"], ioinfo[device]["wiops"],
141
+ ioinfo[device]["rsecps"] * 512 / 1024 / 1024, # in MB/s
142
+ ioinfo[device]["wsecps"] * 512 / 1024 / 1024, # in MB/s
143
+ ]
144
+ }].flatten.map(&:to_s).join("\t"))
145
+ end
146
+
147
+ datafile.close
148
+
149
+ col_idx = 2
150
+ iops_plot_stmt_list = devices.map do |device|
151
+ plot_stmt = []
152
+ plot_stmt.push("\"#{dat_filename}\" usi 1:#{col_idx} with lines lw 2 title \"#{device} read\"")
153
+ plot_stmt.push("\"#{dat_filename}\" usi 1:#{col_idx + 1} with lines lw 2 title \"#{device} write\"")
154
+ col_idx += 4
155
+ plot_stmt
156
+ end.flatten
157
+
158
+ col_idx = 4
159
+ transfer_plot_stmt_list = devices.map do |device|
160
+ plot_stmt = []
161
+ plot_stmt.push("\"#{dat_filename}\" usi 1:#{col_idx} with lines lw 2 title \"#{device} read\"")
162
+ plot_stmt.push("\"#{dat_filename}\" usi 1:#{col_idx + 1} with lines lw 2 title \"#{device} write\"")
163
+ col_idx += 4
164
+ plot_stmt
165
+ end.flatten
166
+
167
+ gpfile.puts <<EOS
168
+ set term pdfcairo enhanced color
169
+ set title "IOPS: #{File.basename(@data_file)}"
170
+ set size 1.0, 1.0
171
+ set output "#{iops_pdf_filename}"
172
+
173
+ set xlabel "elapsed time [sec]"
174
+ set ylabel "IOPS"
175
+
176
+ set grid
177
+ set xrange [#{@offset_time}:*]
178
+ set yrange [0:*]
179
+
180
+ set key below center
181
+
182
+ plot #{iops_plot_stmt_list.join(",\\\n ")}
183
+
184
+
185
+ set title "Transfer rate: #{File.basename(@data_file)}"
186
+ set output "#{transfer_pdf_filename}"
187
+ set ylabel "transfer rate [MB/s]"
188
+ plot #{transfer_plot_stmt_list.join(",\\\n ")}
189
+ EOS
190
+
191
+ gpfile.close
192
+
193
+ system("gnuplot #{gpfile.path}")
194
+
195
+ if @output_type != 'pdf'
196
+ system("convert -density 150 -background white #{iops_pdf_filename} #{iops_img_filename}")
197
+ system("convert -density 150 -background white #{transfer_pdf_filename} #{transfer_img_filename}")
198
+ end
199
+
200
+ end # chdir
201
+
202
+ copy_targets = [iops_pdf_filename, transfer_pdf_filename]
203
+ copy_targets.push(iops_img_filename) if iops_img_filename
204
+ copy_targets.push(transfer_img_filename) if transfer_img_filename
205
+
206
+ if @save_gpfiles
207
+ copy_targets.push(dat_filename)
208
+ copy_targets.push(gp_filename)
209
+ end
210
+
211
+ copy_targets.each do |target|
212
+ FileUtils.copy(File.join(working_dir, target), @output_dir)
213
+ end
214
+ end # mktempdir
215
+ end # def
216
+
217
+ def plot_cpuinfo()
218
+ pdf_filename = @output_prefix + 'cpu.pdf'
219
+ gp_filename = @output_prefix + 'cpu.gp'
220
+ dat_filename = @output_prefix + 'cpu.dat'
221
+
222
+ all_pdf_filename = @output_prefix + 'allcpu.pdf'
223
+ all_gp_filename = @output_prefix + 'allcpu.gp'
224
+ all_dat_filename = @output_prefix + 'allcpu.dat'
225
+
226
+ if @output_type != 'pdf'
227
+ img_filename = @output_prefix + 'cpu.' + @output_type
228
+ all_img_filename = @output_prefix + 'allcpu.' + @output_type
229
+ else
230
+ img_filename = nil
231
+ all_img_filename = nil
232
+ end
233
+
234
+ Dir.mktmpdir do |working_dir|
235
+ Dir.chdir(working_dir) do
236
+ datafile = File.open(dat_filename, 'w')
237
+ gpfile = File.open(gp_filename, 'w')
238
+ all_datafile = File.open(all_dat_filename, 'w')
239
+ all_gpfile = File.open(all_gp_filename, 'w')
240
+
241
+ start_time = nil
242
+ end_time = 0
243
+ devices = nil
244
+ nr_cpu = nil
245
+
246
+ File.open(@data_file).each_line do |line|
247
+ record = JSON.parse(line)
248
+
249
+ time = record["time"]
250
+ cpuinfo = record["cpuinfo"]
251
+ return unless cpuinfo
252
+ nr_cpu = cpuinfo['nr_cpu']
253
+
254
+ cores = cpuinfo['cpus']
255
+
256
+ start_time ||= time
257
+ end_time = [end_time, time].max
258
+
259
+ datafile.puts([time - start_time,
260
+ %w|usr nice sys iowait irq soft steal guest idle|.map do |key|
261
+ cores.map{|core| core[key]}.inject(&:+)
262
+ end].flatten.map(&:to_s).join("\t"))
263
+ end
264
+ datafile.close
265
+
266
+ col_idx = 2
267
+ columns = []
268
+ plot_stmt_list = []
269
+ %w|%usr %nice %sys %iowait %irq %soft %steal %guest|.each do |key|
270
+ columns << col_idx
271
+ plot_stmt = "\"#{datafile.path}\" usi 1:(#{columns.map{|i| "$#{i}"}.join("+")}) with filledcurve x1 lw 0 lc #{col_idx - 1} title \"#{key}\""
272
+ plot_stmt_list << plot_stmt
273
+ col_idx += 1
274
+ end
275
+
276
+ pdf_file = File.join(@output_dir, "cpu.pdf")
277
+ gpfile.puts <<EOS
278
+ set term pdfcairo enhanced color
279
+ set title "CPU usage: #{File.basename(@data_file)} (max: #{nr_cpu*100}%)"
280
+ set output "#{pdf_filename}"
281
+ set key outside center bottom horizontal
282
+ set size 1.0, 1.0
283
+
284
+ set xlabel "elapsed time [sec]"
285
+ set ylabel "CPU usage"
286
+
287
+ set grid
288
+ set xrange [#{@offset_time}:#{end_time - start_time}]
289
+ set yrange [0:*]
290
+
291
+ plot #{plot_stmt_list.reverse.join(",\\\n ")}
292
+ EOS
293
+
294
+ gpfile.close
295
+ system("gnuplot #{gpfile.path}")
296
+
297
+ if @output_type != 'pdf'
298
+ system("convert -density 150 -background white #{pdf_filename} #{img_filename}")
299
+ end
300
+
301
+ ## Plot all CPUs in a single file
302
+
303
+ nr_cpu_factors = factors(nr_cpu)
304
+ nr_cols = nr_cpu_factors.select do |x|
305
+ x <= Math.sqrt(nr_cpu)
306
+ end.max
307
+ nr_cols ||= Math.sqrt(nr_cpu).ceil
308
+ nr_rows = nr_cpu / nr_cols
309
+
310
+ all_gpfile.puts <<EOS
311
+ set term pdfcairo color enhanced size 8.5inch, 11inch
312
+ set output "#{all_pdf_filename}"
313
+ set size 1.0, 1.0
314
+ set multiplot
315
+ set grid
316
+ set xrange [#{@offset_time}:#{end_time - start_time}]
317
+ set yrange [0:101]
318
+
319
+ EOS
320
+
321
+ legend_height = 0.04
322
+ nr_cpu.times do |cpu_idx|
323
+ all_datafile.puts("# cpu #{cpu_idx}")
324
+ File.open(@data_file).each_line do |line|
325
+ record = JSON.parse(line)
326
+ time = record["time"]
327
+ cpurec = record["cpuinfo"]["cpus"][cpu_idx]
328
+ all_datafile.puts([time - start_time,
329
+ cpurec["usr"] + cpurec["nice"],
330
+ cpurec["sys"],
331
+ cpurec["irq"],
332
+ cpurec["soft"],
333
+ cpurec["steal"] + cpurec["guest"],
334
+ cpurec["iowait"]].map(&:to_s).join("\t"))
335
+ end
336
+ all_datafile.puts("")
337
+ all_datafile.puts("")
338
+
339
+ xpos = (1.0 / nr_cols) * (cpu_idx % nr_cols)
340
+ ypos = ((1.0 - legend_height) / nr_rows) * (nr_rows - 1 - (cpu_idx / nr_cols).to_i) + legend_height
341
+
342
+ all_gpfile.puts <<EOS
343
+ set title 'cpu #{cpu_idx}' offset 0.0,-0.7 font 'Arial,16'
344
+ unset key
345
+ set origin #{xpos}, #{ypos}
346
+ set size #{1.0/nr_cols}, #{(1.0 - legend_height)/nr_rows}
347
+ set rmargin 0.5
348
+ set lmargin 3.5
349
+ set tmargin 1.3
350
+ set bmargin 1.3
351
+ set xtics offset 0.0,0.5
352
+ set ytics offset 0.5,0
353
+ set style fill noborder
354
+ plot '#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4+$5+$6+$7) with filledcurve x1 lw 0 lc 6 title '%iowait', \\
355
+ '#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4+$5+$6) with filledcurve x1 lw 0 lc 5 title '%other', \\
356
+ '#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4+$5) with filledcurve x1 lw 0 lc 4 title '%soft', \\
357
+ '#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3+$4) with filledcurve x1 lw 0 lc 3 title '%irq', \\
358
+ '#{all_datafile.path}' index #{cpu_idx} using 1:($2+$3) with filledcurve x1 lw 0 lc 2 title '%sys', \\
359
+ '#{all_datafile.path}' index #{cpu_idx} using 1:2 with filledcurve x1 lw 0 lc 1 title '%usr'
360
+
361
+ EOS
362
+
363
+ end
364
+
365
+ all_gpfile.puts <<EOS
366
+ unset title
367
+ set key center center horizontal font "Arial,16"
368
+ set origin 0.0, 0.0
369
+ set size 1.0, #{legend_height}
370
+ set rmargin 0
371
+ set lmargin 0
372
+ set tmargin 0
373
+ set bmargin 0
374
+ unset tics
375
+ set border 0
376
+ set yrange [0:1]
377
+ # plot -1 with filledcurve x1 title '%usr'
378
+
379
+ plot -1 with filledcurve x1 lw 0 lc 1 title '%usr', \\
380
+ -1 with filledcurve x1 lw 0 lc 2 title '%sys', \\
381
+ -1 with filledcurve x1 lw 0 lc 3 title '%irq', \\
382
+ -1 with filledcurve x1 lw 0 lc 4 title '%soft', \\
383
+ -1 with filledcurve x1 lw 0 lc 5 title '%other', \\
384
+ -1 with filledcurve x1 lw 0 lc 6 title '%iowait'
385
+ EOS
386
+
387
+ all_datafile.fsync
388
+ all_gpfile.fsync
389
+ all_datafile.close
390
+ all_gpfile.close
391
+
392
+ system("gnuplot #{all_gpfile.path}")
393
+
394
+ if @output_type != 'pdf'
395
+ system("convert -density 150 -background white #{all_pdf_filename} #{all_img_filename}")
396
+ end
397
+
398
+ end # chdir
399
+
400
+ copy_targets = []
401
+
402
+ copy_targets << pdf_filename
403
+ copy_targets << img_filename if img_filename
404
+ copy_targets << all_pdf_filename
405
+ copy_targets << all_img_filename if all_img_filename
406
+
407
+ if @save_gpfiles
408
+ copy_targets << gp_filename
409
+ copy_targets << dat_filename
410
+ copy_targets << all_gp_filename
411
+ copy_targets << all_dat_filename
412
+ end
413
+
414
+ copy_targets.each do |target|
415
+ FileUtils.copy(File.join(working_dir, target), @output_dir)
416
+ end
417
+ end # mktempdir
418
+ end # def
419
+
420
+ private
421
+ def factors(n)
422
+ (2..([n, n / 2].max).to_i).select do |x|
423
+ n % x == 0
424
+ end.sort
425
+ end
426
+ end
427
+
428
+ end # module Command
429
+ end # module PerfMonger
@@ -0,0 +1,32 @@
1
+
2
+ require 'optparse'
3
+ require 'json'
4
+ require 'tempfile'
5
+ require 'tmpdir'
6
+
7
+ module PerfMonger
8
+ module Command
9
+
10
+ class RecordCommand < BaseCommand
11
+ register_command 'record', 'Record system performance information'
12
+
13
+ def initialize
14
+ super
15
+ end
16
+
17
+ def run(argv)
18
+ @argv, @option = PerfMonger::Command::RecordOption.parse(argv)
19
+
20
+ exec_record_cmd()
21
+ end
22
+
23
+ private
24
+ def exec_record_cmd()
25
+ cmd = @option.make_command
26
+
27
+ Process.exec(*cmd)
28
+ end
29
+ end
30
+
31
+ end # module Command
32
+ end # module PerfMonger
@@ -0,0 +1,149 @@
1
+
2
+ module PerfMonger
3
+ module Command
4
+
5
+ class RecordOption
6
+ attr_reader :devices
7
+ attr_reader :interval
8
+ attr_reader :verbose
9
+ attr_reader :report_cpu
10
+ attr_reader :report_io
11
+ attr_reader :report_ctx_switch
12
+ attr_reader :logfile
13
+
14
+ attr_reader :parser
15
+
16
+ def self.parse(argv)
17
+ option = self.new
18
+ argv = option.parse(argv)
19
+
20
+ return argv, option
21
+ end
22
+
23
+ def parse(argv)
24
+ argv = @parser.parse(argv)
25
+
26
+ if ! @report_io && ! @report_ctx_switch && ! @report_cpu
27
+ @report_cpu = true
28
+ @report_io = true
29
+ @all_devices = true
30
+ end
31
+
32
+ argv
33
+ end
34
+
35
+ def make_command
36
+ # try to search perfmonger-record in build environment
37
+ # then search installed directory
38
+ record_bin = [File.expand_path("../../perfmonger_record", __FILE__),
39
+ File.expand_path("lib/perfmonger/perfmonger_record", PerfMonger::ROOTDIR),
40
+ File.expand_path("ext/perfmonger/perfmonger_record", PerfMonger::ROOTDIR)].find do |bin|
41
+ File.executable?(bin)
42
+ end
43
+
44
+ if record_bin == nil || ! File.executable?(record_bin)
45
+ puts("ERROR: perfmonger-record(1) not found!")
46
+ exit(false)
47
+ end
48
+
49
+ cmd = [record_bin]
50
+ cmd << '-i'
51
+ cmd << @interval.to_s
52
+ if @interval_backoff
53
+ cmd << '-b'
54
+ end
55
+ if @start_delay > 0
56
+ cmd << '-s'
57
+ cmd << @start_delay.to_s
58
+ end
59
+ if @timeout
60
+ cmd << '-t'
61
+ cmd << @timeout.to_s
62
+ end
63
+ cmd << '-C' if @report_cpu
64
+ cmd << '-S' if @report_ctx_switch
65
+ cmd << '-l' if @logfile != STDOUT
66
+ cmd << @logfile if @logfile != STDOUT
67
+ if @report_io
68
+ if @all_devices
69
+ cmd << '-D'
70
+ else
71
+ @devices.each do |device|
72
+ cmd << '-d'
73
+ cmd << device
74
+ end
75
+ end
76
+ end
77
+ cmd << '-v' if @verbose
78
+
79
+ cmd
80
+ end
81
+
82
+ private
83
+ def initialize
84
+ @devices = []
85
+ @all_devices = false
86
+ @interval = 1.0 # in second
87
+ @interval_backoff = true
88
+ @start_delay = 0.0 # in second
89
+ @timeout = nil # in second, or nil (= no timeout)
90
+ @verbose = false
91
+ @report_cpu = false
92
+ @report_io = false
93
+ @report_ctx_switch = false
94
+ @logfile = STDOUT
95
+
96
+ @parser = OptionParser.new
97
+
98
+ @parser.on('-d', '--device DEVICE',
99
+ 'Device name to be monitored (e.g. sda, sdb, md0, dm-1).') do |device|
100
+ @devices.push(device)
101
+ @report_io = true
102
+ end
103
+
104
+ @parser.on('-D', '--all-devices',
105
+ 'Monitor all block devices.') do
106
+ @all_devices = true
107
+ @report_io = true
108
+ end
109
+
110
+ @parser.on('-i', '--interval SEC',
111
+ 'Amount of time between each measurement report. Floating point is o.k.') do |interval|
112
+ @interval = Float(interval)
113
+ end
114
+
115
+ @parser.on('-B', '--no-interval-backoff',
116
+ 'Prevent interval to be set longer every after 100 records.') do
117
+ @interval_backoff = false
118
+ end
119
+
120
+ @parser.on('-s', '--start-delay SEC',
121
+ 'Amount of wait time before starting measurement. Floating point is o.k.') do |start_delay|
122
+ @start_delay = Float(start_delay)
123
+ end
124
+
125
+ @parser.on('-t', '--timeout SEC',
126
+ 'Amount of measurement time. Floating point is o.k.') do |timeout|
127
+ @timeout = Float(timeout)
128
+ end
129
+
130
+ @parser.on('-C', '--cpu', 'Report CPU usage.') do
131
+ @report_cpu = true
132
+ end
133
+
134
+ @parser.on('-S', '--context-switch', 'Report context switches per sec.') do
135
+ @report_ctx_switch = true
136
+ end
137
+
138
+ @parser.on('-l', '--logfile FILE') do |file|
139
+ @logfile = file
140
+ end
141
+
142
+ @parser.on('-v', '--verbose') do
143
+ @verbose = true
144
+ end
145
+ end
146
+ end
147
+
148
+ end # module Command
149
+ end # module PerfMonger