hansel 0.1.3 → 0.1.4

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/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