perfmonger 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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