hansel 0.1.5 → 0.1.6
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.
- 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
|