perfmonger 0.6.1 → 0.7.0
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.
- checksums.yaml +5 -13
- data/.gitignore +6 -0
- data/.tachikoma.yml +1 -0
- data/.travis.yml +18 -6
- data/Gemfile +1 -3
- data/Guardfile +26 -0
- data/NEWS +21 -0
- data/README.md +8 -9
- data/Rakefile +33 -1
- data/core/Makefile +23 -0
- data/core/build.sh +48 -0
- data/core/perfmonger-player.go +165 -0
- data/core/perfmonger-recorder.go +296 -0
- data/core/perfmonger-summarizer.go +207 -0
- data/core/subsystem/Makefile +3 -0
- data/core/subsystem/perfmonger.go +60 -0
- data/core/subsystem/perfmonger_darwin.go +22 -0
- data/core/subsystem/perfmonger_linux.go +292 -0
- data/core/subsystem/perfmonger_linux_test.go +73 -0
- data/core/subsystem/stat.go +214 -0
- data/core/subsystem/stat_test.go +281 -0
- data/core/subsystem/usage.go +410 -0
- data/core/subsystem/usage_test.go +496 -0
- data/lib/exec/operationBinding.rb.svn-base +59 -0
- data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-player_linux_386 +0 -0
- data/lib/exec/perfmonger-player_linux_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-recorder_linux_386 +0 -0
- data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_386 +0 -0
- data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
- data/lib/exec/perfmonger-summary_linux_386 +0 -0
- data/lib/exec/perfmonger-summary_linux_amd64 +0 -0
- data/lib/perfmonger/cli.rb +8 -3
- data/lib/perfmonger/command/core.rb +62 -0
- data/lib/perfmonger/command/live.rb +39 -0
- data/lib/perfmonger/command/play.rb +56 -0
- data/lib/perfmonger/command/plot.rb +30 -22
- data/lib/perfmonger/command/record.rb +3 -2
- data/lib/perfmonger/command/record_option.rb +40 -59
- data/lib/perfmonger/command/server.rb +7 -2
- data/lib/perfmonger/command/stat.rb +2 -2
- data/lib/perfmonger/command/stat_option.rb +1 -1
- data/lib/perfmonger/command/summary.rb +11 -326
- data/lib/perfmonger/version.rb +1 -3
- data/lib/perfmonger.rb +3 -0
- data/misc/_perfmonger +128 -0
- data/misc/perfmonger-completion.bash +49 -0
- data/perfmonger.gemspec +6 -5
- data/spec/data/busy100.pgr +0 -0
- data/spec/fingerprint_spec.rb +35 -0
- data/spec/live_spec.rb +25 -0
- data/spec/perfmonger_spec.rb +37 -0
- data/spec/play_spec.rb +21 -0
- data/spec/plot_spec.rb +42 -0
- data/spec/record_spec.rb +15 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/stat_spec.rb +15 -0
- data/spec/summary_spec.rb +51 -0
- data/spec/support/aruba.rb +11 -0
- data/wercker.yml +59 -0
- metadata +117 -45
- data/ext/perfmonger/extconf.rb +0 -19
- data/ext/perfmonger/perfmonger.h +0 -58
- data/ext/perfmonger/perfmonger_record.c +0 -754
- data/ext/perfmonger/sysstat/common.c +0 -627
- data/ext/perfmonger/sysstat/common.h +0 -207
- data/ext/perfmonger/sysstat/ioconf.c +0 -515
- data/ext/perfmonger/sysstat/ioconf.h +0 -84
- data/ext/perfmonger/sysstat/iostat.c +0 -1100
- data/ext/perfmonger/sysstat/iostat.h +0 -121
- data/ext/perfmonger/sysstat/libsysstat.h +0 -19
- data/ext/perfmonger/sysstat/mpstat.c +0 -953
- data/ext/perfmonger/sysstat/mpstat.h +0 -79
- data/ext/perfmonger/sysstat/rd_stats.c +0 -2388
- data/ext/perfmonger/sysstat/rd_stats.h +0 -651
- data/ext/perfmonger/sysstat/sysconfig.h +0 -13
- data/test/run-test.sh +0 -39
- data/test/spec/bin_spec.rb +0 -37
- data/test/spec/data/2devices.expected +0 -42
- data/test/spec/data/2devices.output +0 -42
- data/test/spec/spec_helper.rb +0 -20
- data/test/spec/summary_spec.rb +0 -193
- data/test/test-perfmonger.c +0 -145
- data/test/test.h +0 -9
@@ -61,340 +61,25 @@ EOS
|
|
61
61
|
|
62
62
|
summary_title ||= @logfile
|
63
63
|
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
def read_logfile(logfile)
|
69
|
-
File.read(logfile).lines.map do |line|
|
70
|
-
begin
|
71
|
-
JSON.parse(line)
|
72
|
-
rescue JSON::ParserError => err
|
73
|
-
nil
|
74
|
-
end
|
75
|
-
end.compact
|
76
|
-
end
|
77
|
-
|
78
|
-
def make_accumulation(records)
|
79
|
-
unless records.all?{|record| record.has_key?("ioinfo")}
|
80
|
-
return nil
|
81
|
-
end
|
82
|
-
unless records.size > 1
|
83
|
-
return nil
|
84
|
-
end
|
85
|
-
|
86
|
-
accum = Hash.new
|
87
|
-
|
88
|
-
devices = records.first["ioinfo"]["devices"]
|
89
|
-
accum["ioinfo"] = Hash.new
|
90
|
-
|
91
|
-
devices.each do |device|
|
92
|
-
read_requests = 0
|
93
|
-
read_bytes = 0
|
94
|
-
write_requests = 0
|
95
|
-
write_bytes = 0
|
96
|
-
|
97
|
-
(1..(records.size - 1)).each do |idx|
|
98
|
-
last_record = records[idx - 1]
|
99
|
-
record = records[idx]
|
100
|
-
dt = record["time"] - last_record["time"]
|
101
|
-
|
102
|
-
read_requests += record["ioinfo"][device]["riops"] * dt
|
103
|
-
write_requests += record["ioinfo"][device]["wiops"] * dt
|
104
|
-
read_bytes += record["ioinfo"][device]["rsecps"] * 512 * dt
|
105
|
-
write_bytes += record["ioinfo"][device]["wsecps"] * 512 * dt
|
106
|
-
end
|
107
|
-
|
108
|
-
accum["ioinfo"][device] = Hash.new
|
109
|
-
accum["ioinfo"][device]["read_requests"] = read_requests
|
110
|
-
accum["ioinfo"][device]["read_bytes"] = read_bytes
|
111
|
-
accum["ioinfo"][device]["write_requests"] = write_requests
|
112
|
-
accum["ioinfo"][device]["write_bytes"] = write_bytes
|
113
|
-
end
|
114
|
-
|
115
|
-
accum
|
116
|
-
end
|
117
|
-
|
118
|
-
def make_summary(records)
|
119
|
-
if records.empty?
|
120
|
-
return nil
|
121
|
-
elsif records.size == 1
|
122
|
-
return records.first
|
123
|
-
end
|
124
|
-
|
125
|
-
# setup getters and setters all attributes for avg. calculation
|
126
|
-
# getter.call(record) returns value
|
127
|
-
# setter.call(record, value) set value
|
128
|
-
# getters and setters include attribute info as a closure
|
129
|
-
getters = []
|
130
|
-
setters = []
|
131
|
-
|
132
|
-
if records.first.include?("ioinfo")
|
133
|
-
records.first["ioinfo"]["devices"].each do |device|
|
134
|
-
records.first["ioinfo"][device].keys.each do |attr|
|
135
|
-
getters << lambda do |record|
|
136
|
-
record["ioinfo"][device][attr]
|
137
|
-
end
|
138
|
-
setters << lambda do |record, value|
|
139
|
-
record["ioinfo"][device][attr] = value
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
records.first["ioinfo"]["total"].keys.each do |attr|
|
145
|
-
getters << lambda do |record|
|
146
|
-
record["ioinfo"]["total"][attr]
|
147
|
-
end
|
148
|
-
setters << lambda do |record, value|
|
149
|
-
record["ioinfo"]["total"][attr] = value
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
if records.first.include?("cpuinfo")
|
155
|
-
records.first["cpuinfo"]["all"].keys.each do |attr|
|
156
|
-
getters << lambda do |record|
|
157
|
-
record["cpuinfo"]["all"][attr]
|
158
|
-
end
|
159
|
-
setters << lambda do |record, value|
|
160
|
-
record["cpuinfo"]["all"][attr] = value
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
records.first["cpuinfo"]["nr_cpu"].times do |cpu_idx|
|
165
|
-
records.first["cpuinfo"]["cpus"][cpu_idx].keys.each do |attr|
|
166
|
-
getters << lambda do |record|
|
167
|
-
record["cpuinfo"]["cpus"][cpu_idx][attr]
|
168
|
-
end
|
169
|
-
setters << lambda do |record, value|
|
170
|
-
record["cpuinfo"]["cpus"][cpu_idx][attr] = value
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
avg_record = Marshal.load(Marshal.dump(records.first)); # deep copy
|
177
|
-
|
178
|
-
setters.each do |setter|
|
179
|
-
setter.call(avg_record, 0.0)
|
180
|
-
end
|
181
|
-
|
182
|
-
(1..(records.size - 1)).each do |idx|
|
183
|
-
record = records[idx]
|
184
|
-
|
185
|
-
last_t = records[idx - 1]["time"]
|
186
|
-
t = record["time"]
|
187
|
-
|
188
|
-
getters.size.times do |_etters_idx|
|
189
|
-
getter = getters[_etters_idx]
|
190
|
-
setter = setters[_etters_idx]
|
191
|
-
|
192
|
-
setter.call(avg_record,
|
193
|
-
getter.call(avg_record) + getter.call(record) * (t - last_t))
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
getters.size.times do |_etters_idx|
|
198
|
-
getter = getters[_etters_idx]
|
199
|
-
setter = setters[_etters_idx]
|
200
|
-
|
201
|
-
setter.call(avg_record,
|
202
|
-
getter.call(avg_record) / (records[-1]["time"] - records[0]["time"]))
|
203
|
-
end
|
204
|
-
|
64
|
+
@summarizer_bin = ::PerfMonger::Command::CoreFinder.summarizer()
|
205
65
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
accum_r_io_time = 0.0
|
210
|
-
accum_w_io_time = 0.0
|
211
|
-
r_io_count = 0
|
212
|
-
w_io_count = 0
|
213
|
-
|
214
|
-
(records.size - 1).times do |idx|
|
215
|
-
rec0 = records[idx]
|
216
|
-
rec1 = records[idx + 1]
|
217
|
-
dev_ioinfo = rec1["ioinfo"][device]
|
218
|
-
dt = rec1["time"] - rec0["time"]
|
219
|
-
|
220
|
-
accum_r_io_time += dev_ioinfo["r_await"] * dev_ioinfo["riops"] * dt
|
221
|
-
accum_w_io_time += dev_ioinfo["w_await"] * dev_ioinfo["wiops"] * dt
|
222
|
-
r_io_count += dev_ioinfo["riops"] * dt
|
223
|
-
w_io_count += dev_ioinfo["wiops"] * dt
|
224
|
-
end
|
225
|
-
|
226
|
-
if r_io_count > 0
|
227
|
-
avg_record["ioinfo"][device]["r_await"] = accum_r_io_time / r_io_count
|
228
|
-
else
|
229
|
-
avg_record["ioinfo"][device]["r_await"] = 0.0
|
230
|
-
end
|
231
|
-
|
232
|
-
if w_io_count > 0
|
233
|
-
avg_record["ioinfo"][device]["w_await"] = accum_w_io_time / w_io_count
|
234
|
-
else
|
235
|
-
avg_record["ioinfo"][device]["w_await"] = 0.0
|
236
|
-
end
|
237
|
-
end
|
66
|
+
if ! @summarizer_bin
|
67
|
+
puts("[ERROR] no executable binary found.")
|
68
|
+
exit(false)
|
238
69
|
end
|
239
70
|
|
240
|
-
|
241
|
-
end
|
242
|
-
|
243
|
-
def show_summary(logfile, summary_title)
|
244
|
-
records = read_logfile(logfile)
|
245
|
-
summary = make_summary(records)
|
246
|
-
accum = make_accumulation(records)
|
247
|
-
|
248
|
-
duration = records.last["time"] - records.first["time"]
|
71
|
+
cmd = [@summarizer_bin]
|
249
72
|
|
250
73
|
if @json
|
251
|
-
|
252
|
-
|
253
|
-
output["duration"] = duration
|
254
|
-
if summary
|
255
|
-
if summary["cpuinfo"]
|
256
|
-
output["cpuinfo"] = summary["cpuinfo"]
|
257
|
-
end
|
258
|
-
|
259
|
-
if summary['ioinfo']
|
260
|
-
output["ioinfo"] = summary["ioinfo"]
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
puts output.to_json
|
265
|
-
else
|
266
|
-
if $stdout.tty? && @pager
|
267
|
-
output_file = IO.popen(@pager, "w")
|
268
|
-
else
|
269
|
-
output_file = $stdout
|
270
|
-
end
|
271
|
-
|
272
|
-
output_file.puts("")
|
273
|
-
output_file.puts("== Performance summary of '#{summary_title}' ==")
|
274
|
-
output_file.puts("")
|
275
|
-
duration_str = sprintf("%.2f", duration)
|
276
|
-
output_file.puts("record duration: #{duration_str} sec")
|
277
|
-
|
278
|
-
if summary.nil?
|
279
|
-
output_file.puts("")
|
280
|
-
output_file.puts("No performance info was collected.")
|
281
|
-
output_file.puts("This is because command execution time was too short, or something went wrong.")
|
282
|
-
end
|
283
|
-
|
284
|
-
if summary && summary["cpuinfo"]
|
285
|
-
nr_cpu = records.first["cpuinfo"]["nr_cpu"]
|
286
|
-
|
287
|
-
usr, sys, iowait, irq, soft, idle =
|
288
|
-
[summary['cpuinfo']['all']['usr'] + summary['cpuinfo']['all']['nice'],
|
289
|
-
summary['cpuinfo']['all']['sys'],
|
290
|
-
summary['cpuinfo']['all']['iowait'],
|
291
|
-
summary['cpuinfo']['all']['irq'],
|
292
|
-
summary['cpuinfo']['all']['soft'],
|
293
|
-
summary['cpuinfo']['all']['idle']].map do |val|
|
294
|
-
val * nr_cpu
|
295
|
-
end
|
296
|
-
|
297
|
-
other = [100.0 - (usr + sys + iowait + irq + soft + idle), 0.0].max * nr_cpu
|
298
|
-
|
299
|
-
usr_str, sys_str, iowait_str, irq_str, soft_str, other_str, idle_str =
|
300
|
-
[usr, sys, iowait, irq, soft, other, idle].map do |value|
|
301
|
-
sprintf("%.2f", value)
|
302
|
-
end
|
303
|
-
|
304
|
-
total_non_idle_str = sprintf("%.2f", usr + sys + irq + soft + other)
|
305
|
-
total_idle_str = sprintf("%.2f", iowait + idle)
|
306
|
-
|
307
|
-
output_file.puts("")
|
308
|
-
output_file.puts <<EOS
|
309
|
-
* Average CPU usage (MAX: #{100 * nr_cpu} %)
|
310
|
-
* Non idle portion: #{total_non_idle_str}
|
311
|
-
%usr: #{usr_str}
|
312
|
-
%sys: #{sys_str}
|
313
|
-
%irq: #{irq_str}
|
314
|
-
%soft: #{soft_str}
|
315
|
-
%other: #{other_str}
|
316
|
-
* Idle portion: #{total_idle_str}
|
317
|
-
%iowait: #{iowait_str}
|
318
|
-
%idle: #{idle_str}
|
319
|
-
EOS
|
320
|
-
end
|
321
|
-
|
322
|
-
if summary && summary['ioinfo']
|
323
|
-
total_r_iops, total_w_iops, total_r_sec, total_w_sec = [0.0] * 4
|
324
|
-
|
325
|
-
summary['ioinfo']['devices'].each do |device|
|
326
|
-
r_iops, w_iops, r_sec, w_sec, r_await, w_await =
|
327
|
-
[summary['ioinfo'][device]['riops'],
|
328
|
-
summary['ioinfo'][device]['wiops'],
|
329
|
-
summary['ioinfo'][device]['rsecps'] * 512 / 1024.0 / 1024.0,
|
330
|
-
summary['ioinfo'][device]['wsecps'] * 512 / 1024.0 / 1024.0,
|
331
|
-
summary['ioinfo'][device]['r_await'],
|
332
|
-
summary['ioinfo'][device]['w_await']]
|
333
|
-
|
334
|
-
total_r_iops += r_iops
|
335
|
-
total_w_iops += w_iops
|
336
|
-
total_r_sec += r_sec
|
337
|
-
total_w_sec += w_sec
|
338
|
-
|
339
|
-
r_iops_str, w_iops_str, r_sec_str, w_sec_str = [r_iops, w_iops, r_sec, w_sec].map do |value|
|
340
|
-
sprintf("%.2f", value)
|
341
|
-
end
|
342
|
-
|
343
|
-
r_await_str, w_await_str = [r_await, w_await].map do |await|
|
344
|
-
if await < 1.0
|
345
|
-
sprintf("%.1f usec", await * 1000)
|
346
|
-
else
|
347
|
-
sprintf("%.2f msec", await)
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
total_r_bytes_str, total_w_bytes_str = ["read_bytes", "write_bytes"].map do |key|
|
352
|
-
bytes = accum["ioinfo"][device][key]
|
353
|
-
if bytes > 2**30
|
354
|
-
sprintf("%.2f GB", bytes / 2**30)
|
355
|
-
elsif bytes > 2**20
|
356
|
-
sprintf("%.2f MB", bytes / 2**20)
|
357
|
-
elsif bytes > 2**10
|
358
|
-
sprintf("%.2f KB", bytes / 2**10)
|
359
|
-
else
|
360
|
-
sprintf("%.2f bytes", bytes)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
output_file.puts("")
|
366
|
-
output_file.puts("* Average DEVICE usage: #{device}")
|
367
|
-
output_file.puts(" read IOPS: #{r_iops_str}")
|
368
|
-
output_file.puts(" write IOPS: #{w_iops_str}")
|
369
|
-
output_file.puts(" read throughput: #{r_sec_str} MB/s")
|
370
|
-
output_file.puts(" write throughput: #{w_sec_str} MB/s")
|
371
|
-
output_file.puts(" read latency: #{r_await_str}")
|
372
|
-
output_file.puts(" write latency: #{w_await_str}")
|
373
|
-
output_file.puts(" read amount: #{total_r_bytes_str}")
|
374
|
-
output_file.puts(" write amount: #{total_w_bytes_str}")
|
375
|
-
end
|
376
|
-
|
377
|
-
if summary['ioinfo']['devices'].size > 1
|
378
|
-
total_r_iops_str, total_w_iops_str, total_r_sec_str, total_w_sec_str =
|
379
|
-
[total_r_iops, total_w_iops, total_r_sec, total_w_sec].map do |value|
|
380
|
-
sprintf("%.2f", value)
|
381
|
-
end
|
74
|
+
cmd << "-json"
|
75
|
+
end
|
382
76
|
|
383
|
-
|
384
|
-
|
385
|
-
output_file.puts(" read IOPS: #{total_r_iops_str}")
|
386
|
-
output_file.puts(" write IOPS: #{total_w_iops_str}")
|
387
|
-
output_file.puts(" read throughput: #{total_r_sec_str} MB/s")
|
388
|
-
output_file.puts(" write throughput: #{total_w_sec_str} MB/s")
|
389
|
-
end
|
77
|
+
cmd << "-title"
|
78
|
+
cmd << summary_title
|
390
79
|
|
391
|
-
|
392
|
-
end
|
80
|
+
cmd << @logfile
|
393
81
|
|
394
|
-
|
395
|
-
output_file.close
|
396
|
-
end
|
397
|
-
end
|
82
|
+
Process.exec(*cmd)
|
398
83
|
end
|
399
84
|
end
|
400
85
|
|
data/lib/perfmonger/version.rb
CHANGED
data/lib/perfmonger.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'perfmonger/version.rb'
|
2
2
|
require 'perfmonger/config.rb'
|
3
3
|
require 'perfmonger/cli.rb'
|
4
|
+
require 'perfmonger/command/core.rb'
|
4
5
|
require 'perfmonger/command/base_command.rb'
|
5
6
|
require 'perfmonger/command/record.rb'
|
6
7
|
require 'perfmonger/command/record_option.rb'
|
8
|
+
require 'perfmonger/command/live.rb'
|
7
9
|
require 'perfmonger/command/stat.rb'
|
8
10
|
require 'perfmonger/command/stat_option.rb'
|
9
11
|
require 'perfmonger/command/summary.rb'
|
12
|
+
require 'perfmonger/command/play.rb'
|
10
13
|
require 'perfmonger/command/plot.rb'
|
11
14
|
require 'perfmonger/command/server.rb'
|
12
15
|
require 'perfmonger/command/fingerprint.rb'
|
data/misc/_perfmonger
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#compdef perfmonger
|
2
|
+
|
3
|
+
_perfmonger-record() {
|
4
|
+
local curcontext=$curcontext state line ret=1
|
5
|
+
declare -A opt_args
|
6
|
+
|
7
|
+
# TODO: match -d,--device multiple times
|
8
|
+
_arguments -w -C -S \
|
9
|
+
'(-D --all-devices)'{-d,--device}'[device name to be monitored]: :__perfmonger_devices' \
|
10
|
+
'(-d --device)'{-D,--all-devices}'[monitor all devices]' \
|
11
|
+
'(-i --interval)'{-i,--interval}'[measurement interval]: interval in sec' \
|
12
|
+
{-l,--logfile}'[log file name]:_files' \
|
13
|
+
{-B,--no-interval-backoff}'[prevent interval backoff]' \
|
14
|
+
{-s,--start-delay}'[wait specified time before starting measurement]: wait time in sec' \
|
15
|
+
{-t,--timeout}'[length of measurement time]: timeout in sec' \
|
16
|
+
{-C,--cpu}'[report CPU usage]' \
|
17
|
+
{-S,--context-switch}'[report context switches per sec]' \
|
18
|
+
{-v,--verbose}'[verbose]' \
|
19
|
+
{-h,--help}'[show help]' \
|
20
|
+
&& return
|
21
|
+
}
|
22
|
+
|
23
|
+
_perfmonger-stat() {
|
24
|
+
local ret
|
25
|
+
_call_function ret _perfmonger-record
|
26
|
+
return ret
|
27
|
+
}
|
28
|
+
|
29
|
+
_perfmonger-summary() {
|
30
|
+
local curcontext=$curcontext state line ret=1
|
31
|
+
declare -A opt_args
|
32
|
+
|
33
|
+
# TODO: accept only 1 file
|
34
|
+
_arguments -w -C -S \
|
35
|
+
'--json[output summary in JSON format]' \
|
36
|
+
{-p,--pager}'[use pager to see summary output]: pager program' \
|
37
|
+
{-h,--help}'[show help]' \
|
38
|
+
{-h,--help}'[show help]' \
|
39
|
+
'*:: :_files' \
|
40
|
+
&& return
|
41
|
+
}
|
42
|
+
|
43
|
+
_perfmonger-plot() {
|
44
|
+
local curcontext=$curcontext state line ret=1
|
45
|
+
declare -A opt_args
|
46
|
+
|
47
|
+
# TODO: accept only 1 file
|
48
|
+
_arguments -w -C -S \
|
49
|
+
'--offset-time: offset time in sec' \
|
50
|
+
{-o,--output-dir}'[output directory]:_directories' \
|
51
|
+
{-T,--output-type}'[output image type]:output type:(pdf png)' \
|
52
|
+
{-p,--prefix}'[output file name prefix]:prefix' \
|
53
|
+
{-s,--save}'[save gnuplot script and data files]' \
|
54
|
+
{-h,--help}'[show help]' \
|
55
|
+
'*:: :_files' \
|
56
|
+
&& return
|
57
|
+
}
|
58
|
+
|
59
|
+
_perfmonger-fingerprint() {
|
60
|
+
local curcontext=$curcontext state line ret=1
|
61
|
+
declare -A opt_args
|
62
|
+
|
63
|
+
_arguments -w -C -S \
|
64
|
+
'*::output tarball:_files -g "*.((tar|TAR)(.gz|.GZ|.Z|.bz2|.lzma|.xz|)|(tbz|tgz|txz))(-.)"' \
|
65
|
+
{-h,--help}'[show help]' \
|
66
|
+
&& return
|
67
|
+
}
|
68
|
+
|
69
|
+
_perfmonger-server() {
|
70
|
+
local curcontext=$curcontext state line ret=1
|
71
|
+
declare -A opt_args
|
72
|
+
|
73
|
+
# TODO: complete record options after '--'
|
74
|
+
_arguments -w -C \
|
75
|
+
{-H,--hostname}'[host name to display]:host name' \
|
76
|
+
'--http-host[host name for HTTP URL]:host name' \
|
77
|
+
'--port[port number]:port number' \
|
78
|
+
{-h,--help}'[show help]' \
|
79
|
+
&& return
|
80
|
+
|
81
|
+
return $ret
|
82
|
+
}
|
83
|
+
|
84
|
+
__perfmonger_devices() {
|
85
|
+
_values 'device' $(tail -n +3 /proc/partitions | awk '{print $4}')
|
86
|
+
}
|
87
|
+
|
88
|
+
# main completion function
|
89
|
+
# (( $+functions[_perfmonger] )) ||
|
90
|
+
_perfmonger() {
|
91
|
+
local curcontext context state line
|
92
|
+
declare -A opt_args
|
93
|
+
|
94
|
+
integer ret=1
|
95
|
+
|
96
|
+
_arguments -C -S \
|
97
|
+
'(- :)'{-h,--help}'[show help]' \
|
98
|
+
'(- :)'{-v,--version}'[show version]' \
|
99
|
+
'(-): :->commands' \
|
100
|
+
'(-)*:: :->option-or-argument' && return
|
101
|
+
|
102
|
+
case $state in
|
103
|
+
(commands)
|
104
|
+
_perfmonger_commands && ret=0
|
105
|
+
;;
|
106
|
+
(option-or-argument)
|
107
|
+
if (( $+functions[_perfmonger-$words[1]] )); then
|
108
|
+
_call_function ret _perfmonger-$words[1]
|
109
|
+
else
|
110
|
+
_message 'unknown sub-command'
|
111
|
+
fi
|
112
|
+
;;
|
113
|
+
esac
|
114
|
+
|
115
|
+
return $ret
|
116
|
+
}
|
117
|
+
|
118
|
+
_perfmonger_commands() {
|
119
|
+
_values 'command' \
|
120
|
+
'record[record system performance]' \
|
121
|
+
'stat[run a command and record system performance during execution]' \
|
122
|
+
'plot[plot system performance graphs from a perfmonger log file]' \
|
123
|
+
'fingerprint[gather all possible system config information]' \
|
124
|
+
'server[launch self-contained HTML5 realtime graph server]' \
|
125
|
+
'summary[show summary of a perfmonger log file]'
|
126
|
+
}
|
127
|
+
|
128
|
+
compdef _perfmonger perfmonger
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# bash completion support for PerfMonger
|
2
|
+
|
3
|
+
_perfmonger() {
|
4
|
+
local cmd cur prev subcmd
|
5
|
+
cmd=$1
|
6
|
+
cur=$2
|
7
|
+
prev=$3
|
8
|
+
|
9
|
+
subcmds="record stat plot fingerprint server summary"
|
10
|
+
|
11
|
+
# contextual completion
|
12
|
+
case $prev in
|
13
|
+
perfmonger)
|
14
|
+
COMPREPLY=( $(compgen -W "$subcmds" $cur) )
|
15
|
+
return 0
|
16
|
+
;;
|
17
|
+
-d|--device)
|
18
|
+
COMPREPLY=( $(tail -n +3 /proc/partitions | awk '{print $4}') )
|
19
|
+
return 0
|
20
|
+
;;
|
21
|
+
-l|--logfile)
|
22
|
+
COMPREPLY=( $(compgen -o default) )
|
23
|
+
return 0
|
24
|
+
;;
|
25
|
+
-i|--interval|-s|--start-delay|-t|--timeout)
|
26
|
+
COMPREPLY=()
|
27
|
+
return 0
|
28
|
+
;;
|
29
|
+
esac
|
30
|
+
|
31
|
+
# complete options
|
32
|
+
subcmd=${COMP_WORDS[1]}
|
33
|
+
|
34
|
+
case "$cur" in
|
35
|
+
# complete options
|
36
|
+
-*)
|
37
|
+
COMPREPLY=( $(compgen -W "$(perfmonger $subcmd -h | egrep -o ' ([-][[:alnum:]]|-{2}[[:alnum:]-]+)\b')" -- "$cur") )
|
38
|
+
return 0
|
39
|
+
;;
|
40
|
+
*)
|
41
|
+
COMPREPLY=( $(compgen -o default "$cur") )
|
42
|
+
return 0
|
43
|
+
;;
|
44
|
+
esac
|
45
|
+
|
46
|
+
return 0
|
47
|
+
}
|
48
|
+
|
49
|
+
complete -F _perfmonger perfmonger
|
data/perfmonger.gemspec
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# -*- mode: ruby -*-
|
2
2
|
|
3
3
|
$:.push File.expand_path("../lib", __FILE__)
|
4
|
-
require 'perfmonger'
|
4
|
+
require 'perfmonger/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = 'perfmonger'
|
8
8
|
s.version = PerfMonger::VERSION
|
9
|
-
s.date = '2015-01-19'
|
10
9
|
s.summary = "yet anothor performance measurement/monitoring tool"
|
11
10
|
s.description = "yet anothor performance measurement/monitoring tool"
|
12
11
|
s.authors = ["Yuto HAYAMIZU"]
|
@@ -14,18 +13,20 @@ Gem::Specification.new do |s|
|
|
14
13
|
s.homepage = 'http://github.com/hayamiz/perfmonger/'
|
15
14
|
s.license = 'GPL-2'
|
16
15
|
|
17
|
-
s.required_ruby_version = '>= 1.9.
|
16
|
+
s.required_ruby_version = '>= 1.9.3'
|
18
17
|
|
18
|
+
s.add_development_dependency "bundler"
|
19
19
|
s.add_development_dependency "rake"
|
20
20
|
s.add_development_dependency "rspec"
|
21
21
|
s.add_development_dependency "rake-compiler"
|
22
|
+
s.add_development_dependency "guard-rspec"
|
23
|
+
s.add_development_dependency "aruba"
|
22
24
|
|
23
25
|
s.files = `git ls-files`.split("\n")
|
26
|
+
s.files += Dir.glob("lib/exec/*")
|
24
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
28
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
|
26
29
|
|
27
|
-
s.extensions << 'ext/perfmonger/extconf.rb'
|
28
|
-
|
29
30
|
s.post_install_message = <<EOS
|
30
31
|
|
31
32
|
============================================================
|
Binary file
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
describe '[fingerprint] subcommand' do
|
5
|
+
before(:each) do
|
6
|
+
@old_pwd = Dir.pwd
|
7
|
+
@tmpdir = Dir.mktmpdir
|
8
|
+
Dir.chdir(@tmpdir)
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
Dir.chdir(@old_pwd)
|
13
|
+
FileUtils.rm_rf(@tmpdir)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should create output tgz successfully' do
|
17
|
+
run("#{perfmonger_bin} fingerprint output.tgz", 20)
|
18
|
+
assert_success(true)
|
19
|
+
check_file_presence("output.tgz")
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should create output tgz successfully with alias invocation' do
|
23
|
+
run("#{perfmonger_bin} fp output.tgz", 20)
|
24
|
+
assert_success(true)
|
25
|
+
check_file_presence("output.tgz")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should create output tgz successfully with content" do
|
29
|
+
run("#{perfmonger_bin} fingerprint output.tgz", 20)
|
30
|
+
assert_success(true)
|
31
|
+
run("tar xf output.tgz")
|
32
|
+
assert_success(true)
|
33
|
+
check_directory_presence(["output"], true)
|
34
|
+
end
|
35
|
+
end
|
data/spec/live_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe '[live] subcommand' do
|
4
|
+
before(:each) do
|
5
|
+
skip_if_proc_is_not_available
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should print JSON records for 3 seconds and exit successfully.' do
|
9
|
+
cmd = "#{perfmonger_bin} live --timeout 3"
|
10
|
+
run(cmd, 5)
|
11
|
+
assert_success(true)
|
12
|
+
expect(stdout_from(cmd).lines.to_a.size).to eq 3
|
13
|
+
|
14
|
+
stdout_from(cmd).each_line do |line|
|
15
|
+
expect do
|
16
|
+
JSON.parse(line)
|
17
|
+
end.not_to raise_error
|
18
|
+
|
19
|
+
json = JSON.parse(line)
|
20
|
+
expect(json.keys.sort).to eq %w{time cpu disk net}.sort
|
21
|
+
end
|
22
|
+
|
23
|
+
check_file_presence("perfmonger.pgr")
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe "perfmonger command" do
|
5
|
+
it "should be an executable" do
|
6
|
+
expect(File.executable?(perfmonger_bin)).to be true
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should print help and exit with failure when no arguments given' do
|
10
|
+
cmd = "#{perfmonger_bin}"
|
11
|
+
run(cmd)
|
12
|
+
assert_success(false)
|
13
|
+
expect(stdout_from(cmd)).to match(/^Usage: perfmonger/)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should print help and exit with success when --help is given' do
|
17
|
+
["-h", "--help"].each do |arg|
|
18
|
+
cmd = "#{perfmonger_bin} #{arg}"
|
19
|
+
run(cmd)
|
20
|
+
assert_success(true)
|
21
|
+
expect(stdout_from(cmd)).to match(/^Usage: perfmonger/)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should print version number if --version given' do
|
26
|
+
cmd = "#{perfmonger_bin} --version"
|
27
|
+
run(cmd)
|
28
|
+
assert_success(true)
|
29
|
+
expect(stdout_from(cmd)).to include(PerfMonger::VERSION)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'fails if unknown subcommand given' do
|
33
|
+
cmd = "#{perfmonger_bin} piyo"
|
34
|
+
run(cmd)
|
35
|
+
assert_success(false)
|
36
|
+
end
|
37
|
+
end
|