hansel 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -10,7 +10,6 @@ begin
10
10
  gem.email = "paul.mylchreest@mac.com"
11
11
  gem.homepage = "http://github.com/xlymian/hansel"
12
12
  gem.authors = ["Paul Mylchreest"]
13
- gem.add_dependency("mutter", ">= 0.5.2")
14
13
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
14
  end
16
15
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
data/bin/hansel CHANGED
@@ -11,13 +11,9 @@ class File
11
11
  end
12
12
 
13
13
  require File.here '/../lib/arg_parser'
14
- require File.here '/../lib/mutter'
15
14
  require File.here '/../lib/config'
16
15
  require File.here '/../lib/hansel'
17
16
 
18
- include Config
19
- include Mutter
20
-
21
- hansel = Hansel.new(options)
17
+ options = Hansel::Config.new(ARGV).options
22
18
  exit if options.exit
23
- hansel.run
19
+ Hansel::Hansel.new(options).run
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.3"
8
+ s.version = "0.1.4"
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-04-20}
12
+ s.date = %q{2010-04-27}
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}
@@ -27,19 +27,17 @@ Gem::Specification.new do |s|
27
27
  "VERSION",
28
28
  "bin/hansel",
29
29
  "hansel.gemspec",
30
- "hansel.rb",
31
30
  "lib/arg_parser.rb",
32
31
  "lib/config.rb",
33
32
  "lib/csv_formatter.rb",
34
33
  "lib/hansel.rb",
35
- "lib/mutter.rb",
36
34
  "lib/octave_formatter.rb",
37
35
  "lib/yaml_formatter.rb"
38
36
  ]
39
37
  s.homepage = %q{http://github.com/xlymian/hansel}
40
38
  s.rdoc_options = ["--charset=UTF-8"]
41
39
  s.require_paths = ["lib"]
42
- s.rubygems_version = %q{1.3.5}
40
+ s.rubygems_version = %q{1.3.6}
43
41
  s.summary = %q{Ruby driver for httperf - automated load and performance testing}
44
42
 
45
43
  if s.respond_to? :specification_version then
@@ -47,12 +45,9 @@ Gem::Specification.new do |s|
47
45
  s.specification_version = 3
48
46
 
49
47
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
- s.add_runtime_dependency(%q<mutter>, [">= 0.5.2"])
51
48
  else
52
- s.add_dependency(%q<mutter>, [">= 0.5.2"])
53
49
  end
54
50
  else
55
- s.add_dependency(%q<mutter>, [">= 0.5.2"])
56
51
  end
57
52
  end
58
53
 
data/lib/arg_parser.rb CHANGED
@@ -1,101 +1,144 @@
1
- class ArgParser
2
- # http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
3
- # Return a structure describing the options.
4
- def self.parse(args)
5
- # The options specified on the command line will be collected in *options*.
6
- # We set default values here.
7
- options = OpenStruct.new
8
- options.verbose = false
9
- options.server = 'localhost'
10
- options.port = '80'
11
- options.uri = '/'
12
- options.num_conns = 1
13
- options.rate = 1
14
- options.cookie = nil
15
- options.low_rate = 1
16
- options.high_rate = 2
17
- options.rate_step = 1
18
- options.output_format = :yaml
19
- options.output = nil
20
- options.output_dir = File.join ENV['HOME'], 'hansel_output'
21
- options.exit = false
22
-
23
- opts = OptionParser.new do |opts|
24
- opts.banner = "Usage: hansel [options]"
25
-
26
- opts.separator "Specific options:"
27
-
28
- # Mandatory argument.
29
- opts.on("-s", "--server=S",
1
+ module Hansel
2
+ #
3
+ # Parse the command configuration file options and command line arguments.
4
+ # Command line arguments override those from the configuration file
5
+ # See http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
6
+ #
7
+ class ArgParser
8
+ #
9
+ # Setup default values for the parsed options
10
+ #
11
+ def initialize args
12
+ @args = args
13
+ @options = OpenStruct.new(
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
+ :exit => false
28
+ )
29
+ end
30
+
31
+ def server options
32
+ options.on("-s", "--server=S",
30
33
  "Specifies the IP hostname of the server.") do |opt|
31
- options.server = opt
34
+ @options.server = opt
32
35
  end
36
+ end
33
37
 
34
- opts.on("-p", "--port=N",
35
- "This option specifies the port number N on which the web server is listening for HTTP requests.") do |opt|
36
- options.port = opt
38
+ def port options
39
+ options.on("-p", "--port=N",
40
+ "This option specifies the port number N on which the web server is listening for HTTP requests.") do |opt|
41
+ @options.port = opt
37
42
  end
43
+ end
38
44
 
39
- opts.on("-u", "--uri=S",
45
+ def uri options
46
+ options.on("-u", "--uri=S",
40
47
  "Specifies that URI S should be accessed on the server.") do |opt|
41
- options.uri = opt
48
+ @options.uri = opt
42
49
  end
50
+ end
43
51
 
44
- opts.on("-n", "--num_conns=N",
52
+ def connections options
53
+ options.on("-n", "--num_conns=N",
45
54
  "Specifies the total number of connections to create.") do |opt|
46
- options.num_conns = opt.to_i
55
+ @options.num_conns = opt
47
56
  end
57
+ end
48
58
 
49
- opts.on("-l", "--low_rate=S",
59
+ def low_rate options
60
+ options.on("-l", "--low_rate=S",
50
61
  "Specifies the starting fixed rate at which connections are created.") do |opt|
51
- options.low_rate = opt.to_i
62
+ @options.low_rate = opt
52
63
  end
64
+ end
53
65
 
54
- opts.on("-l", "--high_rate=S",
66
+ def high_rate options
67
+ options.on("-l", "--high_rate=S",
55
68
  "Specifies the ending fixed rate at which connections are created.") do |opt|
56
- options.high_rate = opt.to_i
69
+ @options.high_rate = opt
57
70
  end
71
+ end
58
72
 
59
- opts.on("-l", "--rate_step=S",
73
+ def rate_step options
74
+ options.on("-l", "--rate_step=S",
60
75
  "Specifies the fixed rate step at which connections are created.") do |opt|
61
- options.rate_step = opt.to_i
76
+ @options.rate_step = opt
62
77
  end
78
+ end
63
79
 
64
- opts.on("-c", "--cookie=C", "Specify a cookie.") do |opt|
65
- options.cookie = opt
80
+ def cookie options
81
+ options.on("-c", "--cookie=C", "Specify a cookie.") do |opt|
82
+ @options.cookie = opt
66
83
  end
84
+ end
67
85
 
68
- opts.on("-f", "--format=FILE [yaml|csv]", "Specify an output format.") do |opt|
69
- options.output_format = opt.to_sym
86
+ def format options
87
+ options.on("-f", "--format=FILE [yaml|csv]", "Specify an output format.") do |opt|
88
+ @options.output_format = opt.to_sym
70
89
  end
90
+ end
71
91
 
72
- opts.on("-o", "--output=FILE", "Specify an output file.") do |opt|
73
- options.output = opt
92
+ def output options
93
+ options.on("-o", "--output=FILE", "Specify an output file.") do |opt|
94
+ @options.output = opt
74
95
  end
96
+ end
75
97
 
76
- opts.on("-d", "--output_dir=PATH", "Specify an output directory.") do |opt|
77
- options.output_dir = opt
98
+ def output_dir options
99
+ options.on("-d", "--output_dir=PATH", "Specify an output directory.") do |opt|
100
+ @options.output_dir = opt
78
101
  end
102
+ end
79
103
 
80
- opts.separator "Common options:"
81
-
82
- # Boolean switch.
83
- opts.on("-v", "--[no-]verbose", "Run verbosely") do |opt|
84
- options.verbose = opt
104
+ def verbose options
105
+ options.on("-v", "--[no-]verbose", "Run verbosely") do |opt|
106
+ @options.verbose = opt
85
107
  end
108
+ end
86
109
 
87
- opts.on_tail("-h", "--help", "Show this message") do
88
- puts opts
89
- options.exit = true
110
+ def help options
111
+ options.on_tail("-h", "--help", "Show this message") do
112
+ puts options
113
+ @options.exit = true
90
114
  end
115
+ end
91
116
 
92
- opts.on_tail("--version", "Show version") do
117
+ def version options
118
+ options.on_tail("--version", "Show version") do
93
119
  puts "Hansel version #{IO.foreach('VERSION').first.strip}"
94
- options.exit = true
120
+ @options.exit = true
95
121
  end
96
122
  end
97
123
 
98
- opts.parse!(args)
99
- options
124
+ def parse_options options
125
+ options.banner = "Usage: hansel [options]"
126
+ options.separator "Options:"
127
+ %w(server port uri connections low_rate high_rate rate_step cookie
128
+ format output output_dir verbose help version).map(&:to_sym).each do |method|
129
+ self.send method, options
130
+ end
131
+ end
132
+
133
+ #
134
+ # Uses OptionParser to return an OpenStruct object describing the options.
135
+ #
136
+ def parse
137
+ # The options specified on the command line will be collected in *options*.
138
+ # We set default values here.
139
+ OptionParser.new { |options| parse_options options}.parse!(@args)
140
+ @options
141
+ end
142
+
100
143
  end
101
144
  end
data/lib/config.rb CHANGED
@@ -1,27 +1,60 @@
1
- module Config
2
- def config_path
3
- config_path ||= File.join [ENV['HOME'], '.hansel']
4
- end
1
+ module Hansel
2
+ #
3
+ # Loads and parses the configuration file
4
+ #
5
+ class Config
6
+ def initialize(argv)
7
+ @argv = argv
8
+ @args = []
9
+ end
5
10
 
6
- def options_path
7
- options_path ||= File.join config_path, 'options'
8
- end
11
+ #
12
+ # The main configuration directory: defaults to ~/.hansel
13
+ # Creates the configuration directory if it doesn't exist.
14
+ #
15
+ def config_path
16
+ @config_path ||= File.join [ENV['HOME'], '.hansel']
17
+ FileUtils.mkdir_p @config_path unless File.exists? @config_path
18
+ @config_path
19
+ end
9
20
 
10
- def read_config_file
11
- args = []
12
- FileUtils.mkdir_p config_path unless File.exists? config_path
13
- if File.exists? options_path
14
- File.open options_path do |file|
15
- file.read.split("\n").each do |line|
16
- next if line =~ /#+/
17
- args += line.split(' ')
18
- end
21
+ #
22
+ # The options file located in the configuration directory
23
+ #
24
+ def options_path
25
+ @options_path ||= File.join config_path, 'options'
26
+ end
27
+
28
+ def read_lines file
29
+ file.read.split("\n").each do |line|
30
+ next if line =~ /#+/
31
+ @args += line.split(' ')
19
32
  end
20
33
  end
21
- args
22
- end
23
34
 
24
- def options
25
- @opt ||= ArgParser.parse(read_config_file + ARGV)
35
+ def read_file path
36
+ File.open path do |file|
37
+ read_lines file
38
+ end
39
+ end
40
+
41
+ #
42
+ # Reads the options file and returns an Array of String objects.
43
+ # Line starting with '#' are skipped.
44
+ #
45
+ def read_config_file
46
+ path = options_path
47
+ if File.exists? path
48
+ read_file path
49
+ end
50
+ @args
51
+ end
52
+
53
+ #
54
+ # Returns an OpenStruct object with the options
55
+ #
56
+ def options
57
+ @options ||= ArgParser.new(read_config_file + @argv).parse
58
+ end
26
59
  end
27
60
  end
data/lib/csv_formatter.rb CHANGED
@@ -1,20 +1,41 @@
1
1
  require 'csv'
2
+ module Hansel
3
+ #
4
+ # Output to csv format
5
+ #
6
+ class CsvFormatter
7
+ def initialize(data)
8
+ return if data.empty?
9
+ @data = data
10
+ @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
+ end
2
21
 
3
- class CsvFormatter
4
- def initialize(data)
5
- @data = data
6
- end
22
+ def line text
23
+ @csv << text
24
+ @csv << "\n"
25
+ end
26
+
27
+ def header
28
+ @header ||= CSV.generate_line((@info_keys + @keys).map(&:to_s))
29
+ end
30
+
31
+ def format_line data_key
32
+ line CSV.generate_line(@info + @keys.collect{|key| @data[data_key][key]})
33
+ end
7
34
 
8
- def format
9
- result = ""
10
- return result if @data.empty?
11
- keys = @data[@data.keys.first].keys
12
- result << CSV.generate_line(keys.map(&:to_s))
13
- result << "\n"
14
- @data.each_pair do |key, value|
15
- result << CSV.generate_line(keys.collect{|k| value[k]})
16
- result << "\n"
35
+ def format
36
+ return result if @data.empty?
37
+ @data_keys.each { |data_key| format_line data_key }
38
+ @csv
17
39
  end
18
- result
19
40
  end
20
41
  end
data/lib/hansel.rb CHANGED
@@ -1,93 +1,178 @@
1
1
  require 'fileutils'
2
+ module Hansel
3
+ #
4
+ # Class wrapper over httperf.
5
+ #
6
+ class Hansel
7
+ def initialize(options = {})
8
+ @options = options
9
+ @results = {}
10
+ @current_rate = nil
11
+ end
2
12
 
3
- class Hansel
4
- def initialize(options = {})
5
- @options = options
6
- @results = {}
7
- end
13
+ def options
14
+ @options
15
+ end
8
16
 
9
- def options
10
- @options
11
- end
17
+ def parse_replies line
18
+ @result[:replies] = $1 if line =~ /^Total: .*replies (\d+)/
19
+ end
12
20
 
13
- def verbose?
14
- options.verbose
15
- end
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
16
36
 
17
- def benchmark(rate)
18
- result = {:output => ""}
19
- httperf_cmd = [
20
- "httperf --hog",
21
- "--server=#{options.server}",
22
- "--port=#{options.port}",
23
- "--uri=#{options.uri}",
24
- "--num-conns=#{options.num_conns}",
25
- "--rate=#{rate}",
26
- options.cookie && "--add-header='Cookie: #{options.cookie}\\n'"
27
- ].compact.join ' '
28
-
29
- IO.popen("#{httperf_cmd} 2>&1") do |pipe|
30
- puts "\n#{httperf_cmd}"
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 => ""}
31
64
  while line = pipe.gets
32
- case line
33
- when /^Total: .*replies (\d+)/ then result[:replies] = $1
34
- when /^Connection rate: (\d+\.\d)/ then result[:connection_rate] = $1
35
- when /^Request rate: (\d+\.\d)/ then result[:request_rate] = $1
36
- when /^Reply time .* response (\d+\.\d)/ then result[:reply_time] = $1
37
- when /^Net I\/O: (\d+\.\d)/ then result[:net_io] = $1
38
- when /^Errors: total (\d+)/ then result[:errors] = $1
39
- when /^Reply rate .*min (\d+\.\d) avg (\d+\.\d) max (\d+\.\d) stddev (\d+\.\d)/ then
40
- result[:reply_rate_min] = $1
41
- result[:reply_rate_avg] = $2
42
- result[:reply_rate_max] = $3
43
- result[:reply_rate_stddev] = $4
44
- when /^Reply status: 1xx=\d+ 2xx=\d+ 3xx=\d+ 4xx=\d+ 5xx=(\d+)/ then result[:status] = $1
45
- end
65
+ parse_line line
46
66
  end
47
67
  end
48
- result
49
- end
50
68
 
51
- def output
52
- if options.output
53
- FileUtils.mkdir_p options.output_dir
54
- output_file_name = [options.server, options.num_conns.to_s].join('.')
55
- output_file = File.join options.output_dir, output_file_name
56
- type = { :yaml => 'yml', :csv => 'csv', :octave => 'm' }[options.output_format]
57
- File.open([output_file, type].join('.'), "w+") do |f|
58
- formatter = case options.output_format
59
- when :yaml
60
- load File.here '/../lib/yaml_formatter.rb'
61
- YamlFormatter.new(@results)
62
- when :csv
63
- load File.here '/../lib/csv_formatter.rb'
64
- CsvFormatter.new(@results)
65
- when :octave
66
- load File.here '/../lib/octave_formatter.rb'
67
- OctaveFormatter.new(@results, {:output_file_name => output_file_name})
68
- end
69
- f.puts formatter.format
69
+ def build_httperf_cmd
70
+ cookie = @options.cookie
71
+ httperf_cmd = [
72
+ "httperf --hog",
73
+ "--server=#{@options.server}",
74
+ "--port=#{@options.port}",
75
+ "--uri=#{@options.uri}",
76
+ "--num-conns=#{@options.num_conns}",
77
+ "--rate=#{@current_rate}",
78
+ cookie && "--add-header='Cookie: #{cookie}\\n'"
79
+ ].compact.join ' '
80
+ end
81
+
82
+ #
83
+ # Runs httperf with a given request rate. Parses the output and returns
84
+ # a hash with the results.
85
+ #
86
+ def httperf
87
+ httperf_cmd = build_httperf_cmd
88
+ IO.popen("#{httperf_cmd} 2>&1") do |pipe|
89
+ puts "\n#{httperf_cmd}"
90
+ parse pipe
70
91
  end
92
+ @results[@current_rate] = @result
71
93
  end
72
- end
73
94
 
74
- def run
75
- puts "starting run..." if verbose?
76
- (options.low_rate..options.high_rate).step(options.rate_step) do |rate|
77
- puts "benchmarking at rate: #{rate}" if verbose?
78
- @results[:server] = options.server
79
- @results[:port] = options.port
80
- @results[:uri] = options.uri
81
- @results[:num_conns] = options.num_conns
82
- @results[rate] = benchmark(rate)
83
- end
84
- puts "ending run..." if verbose?
85
- output
86
- @results
87
- end
95
+ def yaml_formatter
96
+ load File.here '/../lib/yaml_formatter.rb'
97
+ YamlFormatter.new(@results)
98
+ end
99
+
100
+ def csv_formatter
101
+ load File.here '/../lib/csv_formatter.rb'
102
+ CsvFormatter.new(@results)
103
+ end
104
+
105
+ def octave_formatter
106
+ load File.here '/../lib/octave_formatter.rb'
107
+ puts @output_file_name
108
+ OctaveFormatter.new(@results, {:output_file_name => @output_file_name})
109
+ end
110
+
111
+ def make_formatter format
112
+ case format
113
+ when :yaml
114
+ yaml_formatter
115
+ when :csv
116
+ csv_formatter
117
+ when :octave
118
+ octave_formatter
119
+ end
120
+ end
121
+
122
+ def formatted_output
123
+ @output_file_name = [@options.server, @options.num_conns.to_s].join('.')
124
+ output_file = File.join @options.output_dir, @output_file_name
125
+ output_format = @options.output_format
126
+ type = { :yaml => 'yml', :csv => 'csv', :octave => 'm' }[output_format]
127
+ File.open([output_file, type].join('.'), "w+") do |file|
128
+ file.puts make_formatter(output_format).format
129
+ end
130
+ end
88
131
 
89
- trap("INT") {
90
- puts "Terminating tests."
91
- Process.exit
92
- }
132
+ #
133
+ # Output the results based on the requested output format
134
+ #
135
+ def output
136
+ if @options.output
137
+ FileUtils.mkdir_p @options.output_dir
138
+ formatted_output
139
+ end
140
+ end
141
+
142
+ def status text
143
+ puts text if @options.verbose
144
+ end
145
+
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
+ def run_all
155
+ (@options.low_rate.to_i..@options.high_rate.to_i).step(@options.rate_step.to_i) do |rate|
156
+ status "running httperf at rate: #{rate}"
157
+ @current_rate = rate
158
+ one_run
159
+ end
160
+ end
161
+
162
+ #
163
+ # Run httperf from low_rate to high_rate, stepping by rate_step
164
+ #
165
+ def run
166
+ status "starting run..."
167
+ run_all
168
+ status "ending run..."
169
+ output
170
+ @results
171
+ end
172
+
173
+ trap("INT") {
174
+ puts "Terminating."
175
+ Process.exit
176
+ }
177
+ end
93
178
  end
@@ -1,53 +1,69 @@
1
- class OctaveFormatter
2
- def initialize(data, options = {})
3
- @data = data
4
- @options = options
5
- @png_output = [(options[:output_file_name] || 'stats'), 'png'].join('.')
6
- end
1
+ module Hansel
2
+ #
3
+ # Output to a Octave script.
4
+ #
5
+ class OctaveFormatter
6
+ def initialize(data, options = {})
7
+ @data = data
8
+ @options = options
9
+ @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
7
22
 
8
- def format
9
- rate = @data.keys.reject{|x| x.instance_of? Symbol}.map(&:to_i).sort
10
- request_rate = rate.collect{|x| @data[x][:request_rate]}
11
- connection_rate = rate.collect{|x| @data[x][:connection_rate]}
12
- reply_rate_avg = rate.collect{|x| @data[x][:reply_rate_avg]}
13
- reply_rate_max = rate.collect{|x| @data[x][:reply_rate_max]}
14
- reply_time = rate.collect{|x| @data[x][:reply_time]}
15
- reply_rate_stddev = rate.collect{|x| @data[x][:reply_rate_stddev]}
16
- errors = rate.collect{|x| @data[x][:errors]}
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
+ end
17
29
 
18
- result = <<-EOS
19
- rate = [#{rate.join(',')}];
20
- request_rate = [#{request_rate.join(',')}];
21
- connection_rate = [#{connection_rate.join(',')}];
22
- reply_rate_avg = [#{reply_rate_avg.join(',')}];
23
- reply_rate_max = [#{reply_rate_max.join(',')}];
24
- reply_time = [#{reply_time.join(',')}];
25
- reply_rate_stddev = [#{reply_rate_stddev.join(',')}];
26
- errors = [#{errors.join(',')}];
30
+ def format
31
+ # TODO: render an erb template instead.
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(',')}];
27
42
 
28
- plot(rate, request_rate, '-k*');
29
- hold on;
30
- plot(rate, connection_rate, '-kd');
31
- hold on;
32
- plot(rate, reply_rate_max, '-kp');
33
- hold on;
34
- plot(rate, reply_rate_max, '-k+');
35
- hold on;
36
- plot(rate, reply_rate_stddev, '-kh');
37
- hold on;
38
- plot(rate, reply_time, '-g*');
39
- hold on;
40
- plot(rate, errors, '-r*');
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*');
41
56
 
42
- grid on;
57
+ grid on;
43
58
 
44
- axis([0 #{rate.last} 0 #{rate.last}]);
45
- title('Hansel report for #{@data[:server]}:#{@data[:port]}#{@data[:uri]} (#{@data[:num_conns]} connections per run)')
46
- xlabel('Demanded Request Rate');
47
- legend('Request Rate', 'Connection Rate', 'Avg. reply rate', 'Max. reply rate', 'Reply rate StdDev', 'Reply time', 'Errors');
48
- print('#{@png_output}', '-dpng')
49
- EOS
50
- result = result.gsub ' ', ''
51
- result
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
67
+ end
52
68
  end
53
69
  end
@@ -1,9 +1,14 @@
1
- class YamlFormatter
2
- def initialize(data)
3
- @data = data
4
- end
1
+ module Hansel
2
+ #
3
+ # Output to yaml format
4
+ #
5
+ class YamlFormatter
6
+ def initialize(data)
7
+ @data = data
8
+ end
5
9
 
6
- def format
7
- @data.to_yaml
10
+ def format
11
+ @data.to_yaml
12
+ end
8
13
  end
9
- end
14
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hansel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 4
9
+ version: 0.1.4
5
10
  platform: ruby
6
11
  authors:
7
12
  - Paul Mylchreest
@@ -9,19 +14,10 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-04-20 00:00:00 -04:00
17
+ date: 2010-04-27 00:00:00 -04:00
13
18
  default_executable: hansel
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: mutter
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 0.5.2
24
- version:
19
+ dependencies: []
20
+
25
21
  description: Ruby driver for httperf - automated load and performance testing
26
22
  email: paul.mylchreest@mac.com
27
23
  executables:
@@ -40,12 +36,10 @@ files:
40
36
  - VERSION
41
37
  - bin/hansel
42
38
  - hansel.gemspec
43
- - hansel.rb
44
39
  - lib/arg_parser.rb
45
40
  - lib/config.rb
46
41
  - lib/csv_formatter.rb
47
42
  - lib/hansel.rb
48
- - lib/mutter.rb
49
43
  - lib/octave_formatter.rb
50
44
  - lib/yaml_formatter.rb
51
45
  has_rdoc: true
@@ -61,18 +55,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
61
55
  requirements:
62
56
  - - ">="
63
57
  - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
64
60
  version: "0"
65
- version:
66
61
  required_rubygems_version: !ruby/object:Gem::Requirement
67
62
  requirements:
68
63
  - - ">="
69
64
  - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
70
67
  version: "0"
71
- version:
72
68
  requirements: []
73
69
 
74
70
  rubyforge_project:
75
- rubygems_version: 1.3.5
71
+ rubygems_version: 1.3.6
76
72
  signing_key:
77
73
  specification_version: 3
78
74
  summary: Ruby driver for httperf - automated load and performance testing
data/hansel.rb DELETED
File without changes
data/lib/mutter.rb DELETED
@@ -1,16 +0,0 @@
1
- module Mutter
2
- begin
3
- require 'mutter'
4
- rescue LoadError
5
- STDERR.puts "mutter gem wasn't found, using default output."
6
- end
7
-
8
- def mutter
9
- mutter ||= Mutter.new({
10
- :underline => %w'( )', :yellow => %w'[ ]',
11
- :bold => %w'< >'
12
- }).clear(:default)
13
- rescue
14
- nil
15
- end
16
- end