hansel 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Rakefile +47 -0
- data/VERSION +1 -1
- data/hansel.gemspec +12 -3
- data/lib/arg_parser.rb +27 -14
- data/lib/csv_formatter.rb +10 -19
- data/lib/hansel.rb +37 -88
- data/lib/httperf_result.rb +19 -0
- data/lib/httperf_result_parser.rb +67 -0
- data/lib/octave_formatter.rb +9 -56
- data/spec/httperf_result_parser_spec.rb +119 -0
- data/spec/spec_helper.rb +11 -0
- data/templates/octave.m.erb +30 -0
- metadata +11 -5
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
Spec::Rake::SpecTask.new do |t|
|
8
|
+
t.spec_opts = %w(-fs -c)
|
9
|
+
t.spec_files = FileList["spec/**_spec.rb"]
|
10
|
+
end
|
11
|
+
|
12
|
+
begin
|
13
|
+
require 'metric_fu'
|
14
|
+
rescue LoadError
|
15
|
+
puts "metric_fu (or a dependency) not available. Install it with: gem install metric_fu"
|
16
|
+
end
|
3
17
|
|
4
18
|
begin
|
5
19
|
require 'jeweler'
|
@@ -16,3 +30,36 @@ begin
|
|
16
30
|
rescue LoadError
|
17
31
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
32
|
end
|
33
|
+
|
34
|
+
MetricFu::Configuration.run do |config|
|
35
|
+
#define which metrics you want to use
|
36
|
+
config.metrics = [:churn, :saikuro, :flog, :flay, :reek, :roodi]
|
37
|
+
config.graphs = [:flog, :flay, :reek, :roodi]
|
38
|
+
config.flay = { :dirs_to_flay => ['app', 'lib'],
|
39
|
+
:minimum_score => 100 }
|
40
|
+
config.flog = { :dirs_to_flog => ['app', 'lib'] }
|
41
|
+
config.reek = { :dirs_to_reek => ['app', 'lib'] }
|
42
|
+
config.roodi = { :dirs_to_roodi => ['app', 'lib'] }
|
43
|
+
|
44
|
+
config.saikuro = { :output_directory => 'scratch_directory/saikuro',
|
45
|
+
:input_directory => ['app', 'lib'],
|
46
|
+
:cyclo => "",
|
47
|
+
:filter_cyclo => "0",
|
48
|
+
:warn_cyclo => "5",
|
49
|
+
:error_cyclo => "7",
|
50
|
+
:formater => "text"} #this needs to be set to "text"
|
51
|
+
config.churn = { :start_date => "1 year ago", :minimum_churn_count => 10}
|
52
|
+
|
53
|
+
config.rcov = { :environment => 'test',
|
54
|
+
:test_files => ['test/**/*_test.rb',
|
55
|
+
'spec/**/*_spec.rb'],
|
56
|
+
:rcov_opts => ["--sort coverage",
|
57
|
+
"--no-html",
|
58
|
+
"--text-coverage",
|
59
|
+
"--no-color",
|
60
|
+
"--profile",
|
61
|
+
"--rails",
|
62
|
+
"--exclude /gems/,/Library/,spec"]}
|
63
|
+
|
64
|
+
config.graph_engine = :bluff
|
65
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/hansel.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hansel}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Paul Mylchreest"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-05-05}
|
13
13
|
s.default_executable = %q{hansel}
|
14
14
|
s.description = %q{Ruby driver for httperf - automated load and performance testing}
|
15
15
|
s.email = %q{paul.mylchreest@mac.com}
|
@@ -31,14 +31,23 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/config.rb",
|
32
32
|
"lib/csv_formatter.rb",
|
33
33
|
"lib/hansel.rb",
|
34
|
+
"lib/httperf_result.rb",
|
35
|
+
"lib/httperf_result_parser.rb",
|
34
36
|
"lib/octave_formatter.rb",
|
35
|
-
"lib/yaml_formatter.rb"
|
37
|
+
"lib/yaml_formatter.rb",
|
38
|
+
"spec/httperf_result_parser_spec.rb",
|
39
|
+
"spec/spec_helper.rb",
|
40
|
+
"templates/octave.m.erb"
|
36
41
|
]
|
37
42
|
s.homepage = %q{http://github.com/xlymian/hansel}
|
38
43
|
s.rdoc_options = ["--charset=UTF-8"]
|
39
44
|
s.require_paths = ["lib"]
|
40
45
|
s.rubygems_version = %q{1.3.6}
|
41
46
|
s.summary = %q{Ruby driver for httperf - automated load and performance testing}
|
47
|
+
s.test_files = [
|
48
|
+
"spec/httperf_result_parser_spec.rb",
|
49
|
+
"spec/spec_helper.rb"
|
50
|
+
]
|
42
51
|
|
43
52
|
if s.respond_to? :specification_version then
|
44
53
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
data/lib/arg_parser.rb
CHANGED
@@ -11,20 +11,22 @@ module Hansel
|
|
11
11
|
def initialize args
|
12
12
|
@args = args
|
13
13
|
@options = OpenStruct.new(
|
14
|
-
:verbose
|
15
|
-
:server
|
16
|
-
:port
|
17
|
-
:uri
|
18
|
-
:num_conns
|
19
|
-
:rate
|
20
|
-
:cookie
|
21
|
-
:low_rate
|
22
|
-
:high_rate
|
23
|
-
:rate_step
|
24
|
-
:output_format
|
25
|
-
:output
|
26
|
-
:output_dir
|
27
|
-
:
|
14
|
+
:verbose => false,
|
15
|
+
:server => 'localhost',
|
16
|
+
:port => '80',
|
17
|
+
:uri => '/',
|
18
|
+
:num_conns => 1,
|
19
|
+
:rate => 1,
|
20
|
+
:cookie => nil,
|
21
|
+
:low_rate => 1,
|
22
|
+
:high_rate => 2,
|
23
|
+
:rate_step => 1,
|
24
|
+
:output_format => :yaml,
|
25
|
+
:output => nil,
|
26
|
+
:output_dir => File.join(ENV['HOME'], 'hansel_output'),
|
27
|
+
:template_path => 'templates',
|
28
|
+
:template => nil,
|
29
|
+
:exit => false
|
28
30
|
)
|
29
31
|
end
|
30
32
|
|
@@ -83,6 +85,17 @@ module Hansel
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
88
|
+
def template_options options
|
89
|
+
options.on("-m", "--template_path=PATH", "Specify template path.") do |template_path|
|
90
|
+
@options.template_path = template_path
|
91
|
+
end
|
92
|
+
|
93
|
+
options.on("-t", "--template=TEMPLATE_NAME",
|
94
|
+
"Specify a template for output.") do |template|
|
95
|
+
@options.template = template
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
86
99
|
def other_options options
|
87
100
|
options.on("-c", "--cookie=C", "Specify a cookie.") do |cookie|
|
88
101
|
@options.cookie = cookie
|
data/lib/csv_formatter.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
1
|
require 'csv'
|
2
|
+
|
2
3
|
module Hansel
|
3
|
-
|
4
|
+
|
4
5
|
# Output to csv format
|
5
6
|
#
|
6
7
|
class CsvFormatter
|
8
|
+
COLUMNS = %w(rate replies connection_rate request_rate reply_time net_io
|
9
|
+
errors status reply_rate_min reply_rate_avg reply_rate_max
|
10
|
+
reply_rate_stddev)
|
11
|
+
|
7
12
|
def initialize(data)
|
8
|
-
return if data.empty?
|
9
13
|
@data = data
|
10
14
|
@csv = ""
|
11
|
-
@info_keys = []
|
12
|
-
@data_keys = []
|
13
|
-
@data.keys.each do |key|
|
14
|
-
@info_keys << key if key.instance_of? Symbol
|
15
|
-
@data_keys << key if key.instance_of? Fixnum
|
16
|
-
end
|
17
|
-
@keys ||= @data[@data_keys.first].keys
|
18
|
-
@info = @info_keys.collect{|key| @data[key]}
|
19
|
-
line header
|
20
15
|
end
|
21
16
|
|
22
17
|
def line text
|
@@ -24,17 +19,13 @@ module Hansel
|
|
24
19
|
@csv << "\n"
|
25
20
|
end
|
26
21
|
|
27
|
-
def
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def format_line data_key
|
32
|
-
line CSV.generate_line(@info + @keys.collect{|key| @data[data_key][key]})
|
22
|
+
def format_line data
|
23
|
+
line CSV.generate_line( COLUMNS.map { |column| data.send column.to_sym } )
|
33
24
|
end
|
34
25
|
|
35
26
|
def format
|
36
|
-
|
37
|
-
@
|
27
|
+
line CSV.generate_line(COLUMNS)
|
28
|
+
@data.each { |data| format_line data } unless @data.empty?
|
38
29
|
@csv
|
39
30
|
end
|
40
31
|
end
|
data/lib/hansel.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'lib/httperf_result_parser'
|
3
|
+
require 'lib/httperf_result'
|
4
|
+
|
2
5
|
module Hansel
|
3
6
|
#
|
4
7
|
# Class wrapper over httperf.
|
@@ -6,66 +9,10 @@ module Hansel
|
|
6
9
|
class Hansel
|
7
10
|
def initialize(options = {})
|
8
11
|
@options = options
|
9
|
-
@results =
|
12
|
+
@results = []
|
10
13
|
@current_rate = nil
|
11
14
|
end
|
12
15
|
|
13
|
-
def options
|
14
|
-
@options
|
15
|
-
end
|
16
|
-
|
17
|
-
def parse_replies line
|
18
|
-
@result[:replies] = $1 if line =~ /^Total: .*replies (\d+)/
|
19
|
-
end
|
20
|
-
|
21
|
-
def parse_connection_rate line
|
22
|
-
@result[:connection_rate] = $1 if line =~ /^Connection rate: (\d+\.\d)/
|
23
|
-
end
|
24
|
-
|
25
|
-
def parse_request_rate line
|
26
|
-
@result[:request_rate] = $1 if line =~ /^Request rate: (\d+\.\d)/
|
27
|
-
end
|
28
|
-
|
29
|
-
def parse_reply_time line
|
30
|
-
@result[:reply_time] = $1 if line =~ /^Reply time .* response (\d+\.\d)/
|
31
|
-
end
|
32
|
-
|
33
|
-
def parse_net_io line
|
34
|
-
@result[:net_io] = $1 if line =~ /^Net I\/O: (\d+\.\d)/
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse_errors line
|
38
|
-
@result[:errors] = $1 if line =~ /^Errors: total (\d+)/
|
39
|
-
end
|
40
|
-
|
41
|
-
def parse_status line
|
42
|
-
@result[:status] = $1 if line =~ /^Reply status: 1xx=\d+ 2xx=\d+ 3xx=\d+ 4xx=\d+ 5xx=(\d+)/
|
43
|
-
end
|
44
|
-
|
45
|
-
def parse_reply_rate line
|
46
|
-
if line =~ /^Reply rate .*min (\d+\.\d) avg (\d+\.\d) max (\d+\.\d) stddev (\d+\.\d)/
|
47
|
-
@result[:reply_rate_min] = $1
|
48
|
-
@result[:reply_rate_avg] = $2
|
49
|
-
@result[:reply_rate_max] = $3
|
50
|
-
@result[:reply_rate_stddev] = $4
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def parse_line line
|
55
|
-
%w(parse_replies parse_connection_rate parse_request_rate
|
56
|
-
parse_reply_time parse_net_io parse_errors parse_status
|
57
|
-
parse_reply_rate).map(&:to_sym).each do |method|
|
58
|
-
self.send method, line
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def parse pipe
|
63
|
-
@result = {:output => ""}
|
64
|
-
while line = pipe.gets
|
65
|
-
parse_line line
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
16
|
def build_httperf_cmd
|
70
17
|
cookie = @options.cookie
|
71
18
|
httperf_cmd = [
|
@@ -79,17 +26,23 @@ module Hansel
|
|
79
26
|
].compact.join ' '
|
80
27
|
end
|
81
28
|
|
82
|
-
#
|
29
|
+
#
|
83
30
|
# Runs httperf with a given request rate. Parses the output and returns
|
84
31
|
# a hash with the results.
|
85
|
-
#
|
32
|
+
#
|
86
33
|
def httperf
|
87
34
|
httperf_cmd = build_httperf_cmd
|
88
35
|
IO.popen("#{httperf_cmd} 2>&1") do |pipe|
|
89
36
|
puts "\n#{httperf_cmd}"
|
90
|
-
|
37
|
+
@results << (httperf_result = HttperfResult.new({
|
38
|
+
:rate => @current_rate,
|
39
|
+
:server => @options.server,
|
40
|
+
:port => @options.port,
|
41
|
+
:uri => @options.uri,
|
42
|
+
:num_conns => @options.num_conns
|
43
|
+
}))
|
44
|
+
HttperfResultParser.new(pipe).parse(httperf_result)
|
91
45
|
end
|
92
|
-
@results[@current_rate] = @result
|
93
46
|
end
|
94
47
|
|
95
48
|
def yaml_formatter
|
@@ -105,17 +58,22 @@ module Hansel
|
|
105
58
|
def octave_formatter
|
106
59
|
load File.here '/../lib/octave_formatter.rb'
|
107
60
|
puts @output_file_name
|
108
|
-
OctaveFormatter.new(@results, {
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
61
|
+
OctaveFormatter.new(@results, {
|
62
|
+
:output_file_name => @output_file_name,
|
63
|
+
:template => File.join([@options.template_path,
|
64
|
+
@options.template || 'octave.m.erb']),
|
65
|
+
}
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def format format
|
70
|
+
formatter = "#{format}_formatter".to_sym
|
71
|
+
unless self.respond_to? formatter
|
72
|
+
puts "Using default octave_formatter"
|
73
|
+
octave_formatter
|
74
|
+
else
|
75
|
+
puts "Using #{formatter}"
|
76
|
+
self.send formatter
|
119
77
|
end
|
120
78
|
end
|
121
79
|
|
@@ -125,13 +83,13 @@ module Hansel
|
|
125
83
|
output_format = @options.output_format
|
126
84
|
type = { :yaml => 'yml', :csv => 'csv', :octave => 'm' }[output_format]
|
127
85
|
File.open([output_file, type].join('.'), "w+") do |file|
|
128
|
-
file.puts
|
86
|
+
file.puts format(output_format).format
|
129
87
|
end
|
130
88
|
end
|
131
89
|
|
132
|
-
#
|
90
|
+
#
|
133
91
|
# Output the results based on the requested output format
|
134
|
-
#
|
92
|
+
#
|
135
93
|
def output
|
136
94
|
if @options.output
|
137
95
|
FileUtils.mkdir_p @options.output_dir
|
@@ -143,31 +101,22 @@ module Hansel
|
|
143
101
|
puts text if @options.verbose
|
144
102
|
end
|
145
103
|
|
146
|
-
def one_run
|
147
|
-
@results[:server] = @options.server
|
148
|
-
@results[:port] = @options.port
|
149
|
-
@results[:uri] = @options.uri
|
150
|
-
@results[:num_conns] = @options.num_conns
|
151
|
-
httperf
|
152
|
-
end
|
153
|
-
|
154
104
|
def run_all
|
155
105
|
(@options.low_rate.to_i..@options.high_rate.to_i).step(@options.rate_step.to_i) do |rate|
|
156
106
|
status "running httperf at rate: #{rate}"
|
157
107
|
@current_rate = rate
|
158
|
-
|
108
|
+
httperf
|
159
109
|
end
|
160
110
|
end
|
161
111
|
|
162
|
-
#
|
112
|
+
#
|
163
113
|
# Run httperf from low_rate to high_rate, stepping by rate_step
|
164
|
-
#
|
114
|
+
#
|
165
115
|
def run
|
166
116
|
status "starting run..."
|
167
117
|
run_all
|
168
|
-
status "ending run..."
|
169
118
|
output
|
170
|
-
|
119
|
+
status "ending run..."
|
171
120
|
end
|
172
121
|
|
173
122
|
trap("INT") {
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hansel
|
2
|
+
#
|
3
|
+
# Wrapper for parsing of the httperf run result.
|
4
|
+
#
|
5
|
+
class HttperfResult
|
6
|
+
attr_accessor :rate, :server, :port, :uri, :num_conns, :replies,
|
7
|
+
:connection_rate, :request_rate, :reply_time, :net_io,
|
8
|
+
:errors, :status, :reply_rate_min, :reply_rate_avg,
|
9
|
+
:reply_rate_max, :reply_rate_stddev
|
10
|
+
|
11
|
+
def initialize opt
|
12
|
+
@rate = opt[:rate]
|
13
|
+
@server = opt[:server]
|
14
|
+
@port = opt[:port]
|
15
|
+
@uri = opt[:uri]
|
16
|
+
@num_conns = opt[:num_conns]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Hansel
|
2
|
+
#
|
3
|
+
# Parse httperf output.
|
4
|
+
#
|
5
|
+
class HttperfResultParser
|
6
|
+
attr_accessor :rate, :replies, :connection_rate, :request_rate, :reply_time,
|
7
|
+
:net_io, :errors, :status, :reply_rate_min, :reply_rate_avg,
|
8
|
+
:reply_rate_max, :reply_rate_stddev
|
9
|
+
|
10
|
+
def initialize input
|
11
|
+
@input = input
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_replies line
|
15
|
+
@httperf_result.replies = $1.to_i if line =~ /^Total: .*replies (\d+)/
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_connection_rate line
|
19
|
+
@httperf_result.connection_rate = $1.to_f if line =~ /^Connection rate: (\d+\.\d)/
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_request_rate line
|
23
|
+
@httperf_result.request_rate = $1.to_f if line =~ /^Request rate: (\d+\.\d)/
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_reply_time line
|
27
|
+
@httperf_result.reply_time = $1.to_f if line =~ /^Reply time .* response (\d+\.\d)/
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_net_io line
|
31
|
+
@httperf_result.net_io = $1.to_f if line =~ /^Net I\/O: (\d+\.\d)/
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_errors line
|
35
|
+
@httperf_result.errors = $1.to_i if line =~ /^Errors: total (\d+)/
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_status line
|
39
|
+
@httperf_result.status = $1.to_i if line =~ /^Reply status: 1xx=\d+ 2xx=\d+ 3xx=\d+ 4xx=\d+ 5xx=(\d+)/
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_reply_rate line
|
43
|
+
if line =~ /^Reply rate .*min (\d+\.\d) avg (\d+\.\d) max (\d+\.\d) stddev (\d+\.\d)/
|
44
|
+
@httperf_result.reply_rate_min = $1.to_f
|
45
|
+
@httperf_result.reply_rate_avg = $2.to_f
|
46
|
+
@httperf_result.reply_rate_max = $3.to_f
|
47
|
+
@httperf_result.reply_rate_stddev = $4.to_f
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_line line
|
52
|
+
%w(parse_replies parse_connection_rate parse_request_rate
|
53
|
+
parse_reply_time parse_net_io parse_errors parse_status
|
54
|
+
parse_reply_rate).map(&:to_sym).each do |method|
|
55
|
+
self.send method, line
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse httperf_result
|
60
|
+
@httperf_result = httperf_result
|
61
|
+
@input.each_line do |line|
|
62
|
+
parse_line line
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/octave_formatter.rb
CHANGED
@@ -1,69 +1,22 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
1
3
|
module Hansel
|
2
4
|
#
|
3
5
|
# Output to a Octave script.
|
4
6
|
#
|
5
7
|
class OctaveFormatter
|
6
8
|
def initialize(data, options = {})
|
7
|
-
@data
|
8
|
-
@
|
9
|
+
@data = data
|
10
|
+
@template = options[:template]
|
11
|
+
@rates = @data.map(&:rate)
|
12
|
+
@max_rate = @rates.max
|
9
13
|
@png_output = [(options[:output_file_name] || 'stats'), 'png'].join('.')
|
10
|
-
@rates = @data.keys.select{|key| key.instance_of? Fixnum}.map(&:to_i).sort
|
11
|
-
@max_rate = @rates.last
|
12
|
-
@results = OpenStruct.new(
|
13
|
-
:request_rate => [],
|
14
|
-
:connection_rate => [],
|
15
|
-
:reply_rate_avg => [],
|
16
|
-
:reply_rate_max => [],
|
17
|
-
:reply_time => [],
|
18
|
-
:reply_rate_stddev => [],
|
19
|
-
:errors => []
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
def build_arrays rate, data
|
24
|
-
%w(request_rate connection_rate reply_rate_avg reply_rate_max
|
25
|
-
reply_time reply_rate_stddev errors).map(&:to_sym).each do |method|
|
26
|
-
(@results.send method) << data[method]
|
27
|
-
end
|
28
14
|
end
|
29
15
|
|
16
|
+
# For each value of rate, collate the values in each variable in @vars
|
17
|
+
# and format using the erb template
|
30
18
|
def format
|
31
|
-
|
32
|
-
@rates.each { |rate| build_arrays rate, @data[rate] }
|
33
|
-
result = <<-EOS
|
34
|
-
rate = [#{@rates.join(',')}];
|
35
|
-
request_rate = [#{@results.request_rate.join(',')}];
|
36
|
-
connection_rate = [#{@results.connection_rate.join(',')}];
|
37
|
-
reply_rate_avg = [#{@results.reply_rate_avg.join(',')}];
|
38
|
-
reply_rate_max = [#{@results.reply_rate_max.join(',')}];
|
39
|
-
reply_time = [#{@results.reply_time.join(',')}];
|
40
|
-
reply_rate_stddev = [#{@results.reply_rate_stddev.join(',')}];
|
41
|
-
errors = [#{@results.errors.join(',')}];
|
42
|
-
|
43
|
-
plot(rate, request_rate, '-k*');
|
44
|
-
hold on;
|
45
|
-
plot(rate, connection_rate, '-kd');
|
46
|
-
hold on;
|
47
|
-
plot(rate, reply_rate_max, '-kp');
|
48
|
-
hold on;
|
49
|
-
plot(rate, reply_rate_max, '-k+');
|
50
|
-
hold on;
|
51
|
-
plot(rate, reply_rate_stddev, '-kh');
|
52
|
-
hold on;
|
53
|
-
plot(rate, reply_time, '-g*');
|
54
|
-
hold on;
|
55
|
-
plot(rate, errors, '-r*');
|
56
|
-
|
57
|
-
grid on;
|
58
|
-
|
59
|
-
axis([0 #{@max_rate} 0 #{@max_rate}]);
|
60
|
-
title('Hansel report for #{@data[:server]}:#{@data[:port]}#{@data[:uri]} (#{@data[:num_conns]} connections per run)')
|
61
|
-
xlabel('Demanded Request Rate');
|
62
|
-
legend('Request Rate', 'Connection Rate', 'Avg. reply rate', 'Max. reply rate', 'Reply rate StdDev', 'Reply time', 'Errors');
|
63
|
-
print('#{@png_output}', '-dpng')
|
64
|
-
EOS
|
65
|
-
result = result.gsub ' ', ''
|
66
|
-
result
|
19
|
+
ERB.new(File.read(@template)).result(binding)
|
67
20
|
end
|
68
21
|
end
|
69
22
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
require 'httperf_result_parser'
|
3
|
+
require 'httperf_result'
|
4
|
+
|
5
|
+
SAMPLE_HTTPERF_OUTPUT = <<-EOS
|
6
|
+
|
7
|
+
Maximum connect burst length: 1
|
8
|
+
|
9
|
+
Total: connections 100 requests 99 replies 98 test-duration 10.082 s
|
10
|
+
|
11
|
+
Connection rate: 9.9 conn/s (100.8 ms/conn, <=3 concurrent connections)
|
12
|
+
Connection time [ms]: min 173.3 avg 180.0 max 205.1 median 178.5 stddev 5.6
|
13
|
+
Connection time [ms]: connect 89.8
|
14
|
+
Connection length [replies/conn]: 1.000
|
15
|
+
|
16
|
+
Request rate: 9.9 req/s (100.8 ms/req)
|
17
|
+
Request size [B]: 68.0
|
18
|
+
|
19
|
+
Reply rate [replies/s]: min 9.8 avg 9.9 max 10.0 stddev 0.1 (2 samples)
|
20
|
+
Reply time [ms]: response 90.1 transfer 0.0
|
21
|
+
Reply size [B]: header 287.0 content 438.0 footer 0.0 (total 725.0)
|
22
|
+
Reply status: 1xx=0 2xx=100 3xx=0 4xx=0 5xx=1
|
23
|
+
|
24
|
+
CPU time [s]: user 1.57 system 8.50 (user 15.6% system 84.3% total 99.8%)
|
25
|
+
Net I/O: 7.7 KB/s (0.1*10^6 bps)
|
26
|
+
|
27
|
+
Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
|
28
|
+
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
|
29
|
+
EOS
|
30
|
+
|
31
|
+
describe Hansel::HttperfResultParser, "#score" do
|
32
|
+
before(:each) do
|
33
|
+
@parser = Hansel::HttperfResultParser.new SAMPLE_HTTPERF_OUTPUT
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when calling parse" do
|
37
|
+
before(:each) do
|
38
|
+
@httperf_result = Hansel::HttperfResult.new(
|
39
|
+
:rate => 10,
|
40
|
+
:server => 'www.example.com',
|
41
|
+
:port => 80,
|
42
|
+
:uri => '/',
|
43
|
+
:num_conns => 100
|
44
|
+
)
|
45
|
+
@parser.parse @httperf_result
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should set the passed HttperfResult object" do
|
49
|
+
@httperf_result.class.name =~ /HttperfResult/
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "the HttperfResult object" do
|
53
|
+
it "initialize the rate should be 10" do
|
54
|
+
@httperf_result.rate.should == 10
|
55
|
+
end
|
56
|
+
|
57
|
+
it "initialize the server to 'www.example.com'" do
|
58
|
+
@httperf_result.server.should == 'www.example.com'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "initialize the port to 80" do
|
62
|
+
@httperf_result.port.should == 80
|
63
|
+
end
|
64
|
+
|
65
|
+
it "initialize the uri to '/'" do
|
66
|
+
@httperf_result.uri.should == '/'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "initialize the num_conns to 100" do
|
70
|
+
@httperf_result.num_conns.should == 100
|
71
|
+
end
|
72
|
+
|
73
|
+
it "the should be replies to 98" do
|
74
|
+
@httperf_result.replies.should == 98
|
75
|
+
end
|
76
|
+
|
77
|
+
it "the connection_rate should be 9.9" do
|
78
|
+
@httperf_result.connection_rate.should == 9.9
|
79
|
+
end
|
80
|
+
|
81
|
+
it "the request_rate should be 9.9" do
|
82
|
+
@httperf_result.request_rate.should == 9.9
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should set the reply_time to 90.1" do
|
86
|
+
@httperf_result.reply_time.should == 90.1
|
87
|
+
end
|
88
|
+
|
89
|
+
it "the net_io should be 7.7" do
|
90
|
+
@httperf_result.net_io.should == 7.7
|
91
|
+
end
|
92
|
+
|
93
|
+
it "the errors should be 0" do
|
94
|
+
@httperf_result.errors.should == 0
|
95
|
+
end
|
96
|
+
|
97
|
+
it "the status should be 1" do
|
98
|
+
@httperf_result.status.should == 1
|
99
|
+
end
|
100
|
+
|
101
|
+
it "reply_rate_min should be 9.8" do
|
102
|
+
@httperf_result.reply_rate_min.should == 9.8
|
103
|
+
end
|
104
|
+
|
105
|
+
it "the reply_rate_avg should be 9.9" do
|
106
|
+
@httperf_result.reply_rate_avg.should == 9.9
|
107
|
+
end
|
108
|
+
|
109
|
+
it "the reply_rate_max should be 10.0" do
|
110
|
+
@httperf_result.reply_rate_max.should == 10.0
|
111
|
+
end
|
112
|
+
|
113
|
+
it "the reply_rate_stddev should be 0.1" do
|
114
|
+
@httperf_result.reply_rate_stddev.should == 0.1
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
rate = [<%= @data.map(&:rate).join(', ') %>];
|
2
|
+
request_rate = [<%= @data.map(&:request_rate).join(', ') %>];
|
3
|
+
connection_rate = [<%= @data.map(&:connection_rate).join(', ') %>];
|
4
|
+
reply_rate_avg = [<%= @data.map(&:reply_rate_avg).join(', ') %>];
|
5
|
+
reply_rate_max = [<%= @data.map(&:reply_rate_max).join(', ') %>];
|
6
|
+
reply_time = [<%= @data.map(&:reply_time).join(', ') %>];
|
7
|
+
reply_rate_stddev = [<%= @data.map(&:reply_rate_stddev).join(', ') %>];
|
8
|
+
errors = [<%= @data.map(&:errors).join(', ') %>];
|
9
|
+
|
10
|
+
plot(rate, request_rate, '-k*');
|
11
|
+
hold on;
|
12
|
+
plot(rate, connection_rate, '-kd');
|
13
|
+
hold on;
|
14
|
+
plot(rate, reply_rate_max, '-kp');
|
15
|
+
hold on;
|
16
|
+
plot(rate, reply_rate_max, '-k+');
|
17
|
+
hold on;
|
18
|
+
plot(rate, reply_rate_stddev, '-kh');
|
19
|
+
hold on;
|
20
|
+
plot(rate, reply_time, '-g*');
|
21
|
+
hold on;
|
22
|
+
plot(rate, errors, '-r*');
|
23
|
+
|
24
|
+
grid on;
|
25
|
+
|
26
|
+
axis([0 <%= @max_rate %> 0 <%= @max_rate %>]);
|
27
|
+
title('Hansel report for <%= "#{@data.first.server}:#{@data.first.port}#{@data.first.uri} (#{@data.first.num_conns}" %> connections per run)')
|
28
|
+
xlabel('Demanded Request Rate');
|
29
|
+
legend('Request Rate', 'Connection Rate', 'Avg. reply rate', 'Max. reply rate', 'Reply rate StdDev', 'Reply time', 'Errors');
|
30
|
+
print('<%= @png_output %>', '-dpng')
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 6
|
9
|
+
version: 0.1.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Paul Mylchreest
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-05 00:00:00 -04:00
|
18
18
|
default_executable: hansel
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -40,8 +40,13 @@ files:
|
|
40
40
|
- lib/config.rb
|
41
41
|
- lib/csv_formatter.rb
|
42
42
|
- lib/hansel.rb
|
43
|
+
- lib/httperf_result.rb
|
44
|
+
- lib/httperf_result_parser.rb
|
43
45
|
- lib/octave_formatter.rb
|
44
46
|
- lib/yaml_formatter.rb
|
47
|
+
- spec/httperf_result_parser_spec.rb
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
- templates/octave.m.erb
|
45
50
|
has_rdoc: true
|
46
51
|
homepage: http://github.com/xlymian/hansel
|
47
52
|
licenses: []
|
@@ -72,5 +77,6 @@ rubygems_version: 1.3.6
|
|
72
77
|
signing_key:
|
73
78
|
specification_version: 3
|
74
79
|
summary: Ruby driver for httperf - automated load and performance testing
|
75
|
-
test_files:
|
76
|
-
|
80
|
+
test_files:
|
81
|
+
- spec/httperf_result_parser_spec.rb
|
82
|
+
- spec/spec_helper.rb
|