solutious-stella 0.5.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/CHANGES.txt +39 -2
  2. data/LICENSE.txt +19 -0
  3. data/README.rdoc +85 -0
  4. data/Rakefile +54 -59
  5. data/bin/example_test.rb +82 -0
  6. data/bin/example_webapp.rb +63 -0
  7. data/lib/{stella/logger.rb → logger.rb} +6 -11
  8. data/lib/stella.rb +76 -58
  9. data/lib/stella/clients.rb +161 -0
  10. data/lib/stella/command/base.rb +4 -24
  11. data/lib/stella/command/form.rb +36 -0
  12. data/lib/stella/command/get.rb +44 -0
  13. data/lib/stella/common.rb +53 -0
  14. data/lib/stella/crypto.rb +88 -0
  15. data/lib/stella/data/domain.rb +2 -2
  16. data/lib/stella/data/http.rb +164 -36
  17. data/lib/stella/environment.rb +66 -0
  18. data/lib/stella/functest.rb +105 -0
  19. data/lib/stella/loadtest.rb +186 -0
  20. data/lib/{utils → stella}/stats.rb +16 -20
  21. data/lib/stella/testplan.rb +237 -0
  22. data/lib/stella/testrunner.rb +64 -0
  23. data/lib/storable.rb +280 -0
  24. data/lib/threadify.rb +171 -0
  25. data/lib/timeunits.rb +65 -0
  26. data/lib/util/httputil.rb +266 -0
  27. data/stella.gemspec +69 -0
  28. data/tryouts/drb/drb_test.rb +65 -0
  29. data/tryouts/drb/open4.rb +19 -0
  30. data/tryouts/drb/slave.rb +27 -0
  31. data/tryouts/oo_tryout.rb +30 -0
  32. metadata +39 -107
  33. data/README.textile +0 -162
  34. data/bin/stella +0 -12
  35. data/bin/stella.bat +0 -12
  36. data/lib/daemonize.rb +0 -56
  37. data/lib/pcaplet.rb +0 -180
  38. data/lib/stella/adapter/ab.rb +0 -337
  39. data/lib/stella/adapter/base.rb +0 -106
  40. data/lib/stella/adapter/httperf.rb +0 -305
  41. data/lib/stella/adapter/pcap_watcher.rb +0 -221
  42. data/lib/stella/adapter/proxy_watcher.rb +0 -76
  43. data/lib/stella/adapter/siege.rb +0 -341
  44. data/lib/stella/cli.rb +0 -258
  45. data/lib/stella/cli/agents.rb +0 -73
  46. data/lib/stella/cli/base.rb +0 -55
  47. data/lib/stella/cli/language.rb +0 -18
  48. data/lib/stella/cli/localtest.rb +0 -78
  49. data/lib/stella/cli/sysinfo.rb +0 -16
  50. data/lib/stella/cli/watch.rb +0 -278
  51. data/lib/stella/command/localtest.rb +0 -358
  52. data/lib/stella/response.rb +0 -85
  53. data/lib/stella/storable.rb +0 -201
  54. data/lib/stella/support.rb +0 -276
  55. data/lib/stella/sysinfo.rb +0 -257
  56. data/lib/stella/test/definition.rb +0 -79
  57. data/lib/stella/test/run/summary.rb +0 -70
  58. data/lib/stella/test/stats.rb +0 -114
  59. data/lib/stella/text.rb +0 -64
  60. data/lib/stella/text/resource.rb +0 -38
  61. data/lib/utils/crypto-key.rb +0 -84
  62. data/lib/utils/domainutil.rb +0 -47
  63. data/lib/utils/escape.rb +0 -302
  64. data/lib/utils/fileutil.rb +0 -78
  65. data/lib/utils/httputil.rb +0 -266
  66. data/lib/utils/mathutil.rb +0 -15
  67. data/lib/utils/textgraph.rb +0 -267
  68. data/lib/utils/timerutil.rb +0 -58
  69. data/lib/win32/Console.rb +0 -970
  70. data/lib/win32/Console/ANSI.rb +0 -305
  71. data/support/kvm.h +0 -91
  72. data/support/ruby-pcap-takuma-notes.txt +0 -19
  73. data/support/ruby-pcap-takuma-patch.txt +0 -30
  74. data/support/text/en.yaml +0 -80
  75. data/support/text/nl.yaml +0 -7
  76. data/support/useragents.txt +0 -75
  77. data/tests/01-util_test.rb +0 -0
  78. data/tests/02-stella-util_test.rb +0 -42
  79. data/tests/10-stella_test.rb +0 -104
  80. data/tests/11-stella-storable_test.rb +0 -68
  81. data/tests/60-stella-command_test.rb +0 -248
  82. data/tests/80-stella-cli_test.rb +0 -45
  83. data/tests/spec-helper.rb +0 -31
data/bin/stella.bat DELETED
@@ -1,12 +0,0 @@
1
- @echo off
2
-
3
- rem Check for funkiness when called from another batch script.
4
- rem We want FULL_PATH to contain the full path to the stella bin directory.
5
- IF EXIST "%~dp0stella.bat" (set FULL_PATH=%~dp0) ELSE (set FULL_PATH=%~dp$PATH:0)
6
-
7
- rem Check for JRuby, otherwise use Ruby.
8
- rem We want EXECUTABLE to contain either "jruby" or "ruby"
9
- IF EXIST "%JRUBY_HOME%" (set EXECUTABLE=jruby) ELSE (set EXECUTABLE=ruby)
10
-
11
- rem Call the Ruby script, passing it all the arguments.
12
- @%EXECUTABLE% %FULL_PATH%stella %*
data/lib/daemonize.rb DELETED
@@ -1,56 +0,0 @@
1
- module Daemonize
2
- VERSION = "0.1.2"
3
-
4
- # Try to fork if at all possible retrying every 5 sec if the
5
- # maximum process limit for the system has been reached
6
- def safefork
7
- tryagain = true
8
-
9
- while tryagain
10
- tryagain = false
11
- begin
12
- if pid = fork
13
- return pid
14
- end
15
- rescue Errno::EWOULDBLOCK
16
- sleep 5
17
- tryagain = true
18
- end
19
- end
20
- end
21
-
22
- # This method causes the current running process to become a daemon
23
- # If closefd is true, all existing file descriptors are closed
24
- def daemonize(oldmode=0, closefd=false)
25
- srand # Split rand streams between spawning and daemonized process
26
- safefork and exit # Fork and exit from the parent
27
-
28
- # Detach from the controlling terminal
29
- unless sess_id = Process.setsid
30
- raise 'Cannot detach from controlled terminal'
31
- end
32
-
33
- # Prevent the possibility of acquiring a controlling terminal
34
- if oldmode.zero?
35
- trap 'SIGHUP', 'IGNORE'
36
- exit if pid = safefork
37
- end
38
-
39
- Dir.chdir "/" # Release old working directory
40
- File.umask 0000 # Insure sensible umask
41
-
42
- if closefd
43
- # Make sure all file descriptors are closed
44
- ObjectSpace.each_object(IO) do |io|
45
- unless [STDIN, STDOUT, STDERR].include?(io)
46
- io.close rescue nil
47
- end
48
- end
49
- end
50
-
51
- STDIN.reopen "/dev/null" # Free file descriptors and
52
- STDOUT.reopen "/dev/null", "a" # point them somewhere sensible
53
- STDERR.reopen STDOUT # STDOUT/STDERR should go to a logfile
54
- return oldmode ? sess_id : 0 # Return value is mostly irrelevant
55
- end
56
- end
data/lib/pcaplet.rb DELETED
@@ -1,180 +0,0 @@
1
- require 'pcap'
2
-
3
-
4
- # Pcaplet
5
- #
6
- # Adapted from Ruby portion of Ruby-Pcap:
7
- # http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap-e.html
8
- # The lib/pcaplet.rb and lib/pcap_misc.rb files are in merge into this file
9
- # and cleaned up. The Ruby-Pcap C extension was modified to apply several fixes
10
- # so it would compile on OS X and to remove several warning messages. With
11
- # help from: http://d.hatena.ne.jp/takuma104/20080210/1202638583
12
- # We specifically removed the dependency on ARGV and OptParse. It was messy
13
- # and required ARGV to be specifically modified before requiring this package.
14
- # Manual: http://www.goto.info.waseda.ac.jp/~fukusima/ruby/pcap/doc/index.html
15
- class Pcaplet
16
-
17
- attr_accessor :debug, :verbose
18
- # do not convert address to name
19
- attr_accessor :convert
20
- attr_accessor :device, :rfile, :count, :snaplen, :filter
21
-
22
- def initialize(args = {})
23
-
24
- @debug = args[:debug] || false
25
- @verbose = args[:verbose] || false
26
- @device = args[:device] || guess_device
27
- @rfile = args[:rfile]
28
- @convert = args[:convert] || false
29
- @count = args[:count].to_i || 1000
30
- @snaplen = args[:snaplen].to_i > 0 ? args[:snaplen] : 1500
31
- @filter = args[:filter] || ''
32
-
33
- Pcap.convert = @convert
34
-
35
- # check option consistency
36
- usage(1) if @device && @rfile
37
- if !@device and !@rfile
38
- @device = Pcap.lookupdev
39
- end
40
-
41
- # open
42
- begin
43
- if @device
44
- @capture = Pcap::Capture.open_live(@device, @snaplen)
45
- elsif @rfile
46
- if @rfile !~ /\.gz$/
47
- @capture = Capture.open_offline(@rfile)
48
- else
49
- $stdin = IO.popen("gzip -dc < #@rfile", 'r')
50
- @capture = Capture.open_offline('-')
51
- end
52
- end
53
- @capture.setfilter(@filter) if @filter
54
- rescue Pcap::PcapError, ArgumentError
55
- $stdout.flush
56
- $stderr.puts $!
57
- exit(1)
58
- end
59
- end
60
-
61
- attr('capture')
62
-
63
-
64
- def add_filter(f)
65
- if @filter == nil || @filter =~ /^\s*$/ # if empty
66
- #puts "filter is nil or empty"
67
- @filter = f
68
- else
69
- #puts "filter is #{@filter}"
70
- f = f.source if f.is_a? Filter
71
- @filter = "( #{@filter} ) and ( #{f} )"
72
- end
73
- #puts "filter being set #{@filter}"
74
- @capture.setfilter(@filter)
75
- end
76
-
77
- def each_packet(&block)
78
-
79
- begin
80
- duplicated = (RUBY_PLATFORM =~ /linux/ && @device == "lo")
81
- unless duplicated
82
- @capture.loop(@count, &block)
83
- else
84
- flip = true
85
- @capture.loop(@count) do |pkt|
86
- flip = (! flip)
87
- next if flip
88
- block.call pkt
89
- end
90
- end
91
- end
92
- end
93
-
94
- alias each each_packet
95
-
96
- def close
97
- @capture.close
98
- end
99
- end
100
-
101
-
102
-
103
- module Pcap
104
- class Packet
105
- def to_s
106
- 'Some packet'
107
- end
108
-
109
- def inspect
110
- "#<#{type}: #{self}>"
111
- end
112
- end
113
-
114
- class IPPacket
115
- def to_s
116
- "#{ip_src} > #{ip_dst}"
117
- end
118
- end
119
-
120
- class TCPPacket
121
- def tcp_data_len
122
- ip_len - 4 * (ip_hlen + tcp_hlen)
123
- end
124
-
125
- # The 3-way handshake that initiates a request
126
- # ....S. --->
127
- # .A..S. <---
128
- # .A.... --->
129
- #
130
- # The teardown procedure at the end of the request
131
- # .A...F --->
132
- # .A.... <---
133
- # .A...F --->
134
- # .A.... <...
135
- def tcp_flags_s
136
- return \
137
- (tcp_urg? ? 'U' : '.') + # Urgent
138
- (tcp_ack? ? 'A' : '.') + # ACKnowledgement: Successful transfer
139
- (tcp_psh? ? 'P' : '.') + # Push
140
- (tcp_rst? ? 'R' : '.') + # Reset
141
- (tcp_syn? ? 'S' : '.') + # SYNchronization: this is the first segment in a new transaction
142
- (tcp_fin? ? 'F' : '.') # FINal: final transaction
143
- end
144
-
145
- def to_s
146
- "#{src}:#{sport} > #{dst}:#{dport} #{tcp_flags_s}"
147
- end
148
- end
149
-
150
- class UDPPacket
151
- def to_s
152
- "#{src}:#{sport} > #{dst}:#{dport} len #{udp_len} sum #{udp_sum}"
153
- end
154
- end
155
-
156
- class ICMPPacket
157
- def to_s
158
- "#{src} > #{dst}: icmp: #{icmp_typestr}"
159
- end
160
- end
161
-
162
- #
163
- # Backword compatibility
164
- #
165
- IpPacket = IPPacket unless defined? IpPacket
166
- IpAddress = IPAddress unless defined? IpAddress
167
- TcpPacket = TCPPacket unless defined? TcpPacket
168
- UdpPacket = UDPPacket unless defined? UdpPacket
169
-
170
- end
171
-
172
- class Time
173
- # tcpdump style format
174
- def tcpdump
175
- sprintf "%0.2d:%0.2d:%0.2d.%0.6d", hour, min, sec, tv_usec
176
- end
177
- end
178
-
179
-
180
-
@@ -1,337 +0,0 @@
1
-
2
- require 'fileutils'
3
-
4
- module Stella
5
- module Adapter
6
-
7
- #Usage: ab [options] [http[s]://]hostname[:port]/path
8
- #Options are:
9
- # -n requests Number of requests to perform
10
- # -c concurrency Number of multiple requests to make
11
- # -t timelimit Seconds to max. wait for responses
12
- # -b windowsize Size of TCP send/receive buffer, in bytes
13
- # -p postfile File containing data to POST. Remember also to set -T
14
- # -T content-type Content-type header for POSTing, eg.
15
- # 'application/x-www-form-urlencoded'
16
- # Default is 'text/plain'
17
- # -v verbosity How much troubleshooting info to print
18
- # -w Print out results in HTML tables
19
- # -i Use HEAD instead of GET
20
- # -x attributes String to insert as table attributes
21
- # -y attributes String to insert as tr attributes
22
- # -z attributes String to insert as td or th attributes
23
- # -C attribute Add cookie, eg. 'Apache=1234. (repeatable)
24
- # -H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
25
- # Inserted after all normal header lines. (repeatable)
26
- # -A attribute Add Basic WWW Authentication, the attributes
27
- # are a colon separated username and password.
28
- # -P attribute Add Basic Proxy Authentication, the attributes
29
- # are a colon separated username and password.
30
- # -X proxy:port Proxyserver and port number to use
31
- # -V Print version number and exit
32
- # -k Use HTTP KeepAlive feature
33
- # -d Do not show percentiles served table.
34
- # -S Do not show confidence estimators and warnings.
35
- # -g filename Output collected data to gnuplot format file.
36
- # -e filename Output CSV file with percentages served
37
- # -r Don't exit on socket receive errors.
38
- # -h Display usage information (this message)
39
- # -Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)
40
- # -f protocol Specify SSL/TLS protocol (SSL2, SSL3, TLS1, or ALL)
41
- class ApacheBench < Stella::Adapter::Base
42
-
43
- attr_writer :n, :c
44
- attr_accessor :t, :b, :p, :T, :v, :w, :i, :x, :z, :y
45
- attr_accessor :C, :H, :A, :P, :X, :V, :k, :d, :S, :e, :g, :r, :h, :Z, :f
46
-
47
- def initialize(options={}, arguments=[])
48
- @private_variables = ['private_variables', 'name', 'arguments', 'load_factor', 'working_directory']
49
- @c = 1
50
- @n = 1
51
- @name = 'ab'
52
- @load_factor = 1
53
-
54
- super(options, arguments)
55
-
56
- end
57
-
58
- def error
59
- (File.exists? stderr_path) ? FileUtil.read_file(stderr_path) : "Unknown error"
60
- end
61
-
62
- def version
63
- vsn = 0
64
- Stella::Util.capture_output("#{@name} -V") do |stdout, stderr|
65
- stdout.join.scan(/Version (\d+?\.\d+)/) { |v| vsn = v[0] }
66
- end
67
- vsn
68
- end
69
-
70
- def percentiles_file
71
- @working_directory + "/ab-percentiles.log"
72
- end
73
-
74
- def requests_file
75
- @working_directory + "/ab-requests.log"
76
- end
77
-
78
- def before
79
- @e = percentiles_file if @e.nil?
80
- @g = requests_file if @g.nil?
81
- end
82
-
83
- def command
84
- raise CommandNotReady.new(self.class.to_s) unless ready?
85
-
86
- command = "#{@name} "
87
-
88
- instance_variables.each do |name|
89
- canon = name.to_s.tr('@', '') # instance_variables returns '@name'
90
- next if @private_variables.member?(canon)
91
-
92
- # It's important that we take the value from the getter method
93
- # because it applies the load factor.
94
- value = self.send(canon)
95
- if (value.is_a? Array)
96
- value.each { |el| command << "-#{canon} #{EscapeUtil.shell_single_word(value.to_s)} " }
97
- else
98
- command << "-#{canon} #{EscapeUtil.shell_single_word(value.to_s)} "
99
- end
100
-
101
- end
102
-
103
- command << (@arguments.map { |uri| "#{uri}" }).join(' ') unless @arguments.empty?
104
-
105
- command
106
- end
107
- # loadtest
108
- #
109
- # True or false: is the call to ab a load test? If it's a call to help or version or
110
- # to display the config this with return false. It's no reason for someone to make this
111
- # call through Stella but it's here for goodness sake.
112
- def loadtest?
113
- !@arguments.empty? # The argument is a URI
114
- end
115
- def ready?
116
- (!self.loadtest?) || (@name && !instance_variables.empty? && !@arguments.empty?)
117
- end
118
-
119
-
120
- def process_arguments(arguments)
121
- opts = OptionParser.new
122
-
123
- # TODO: there's no need to use an OpenStruct here. It's confusing b/c we can
124
- # use the instance var methods here instead of in Base::options=.
125
-
126
- # TODO: Print a note for w that we don't parse the HTML results
127
- %w{v w i V k d S r h}.each do |n|
128
- opts.on("-#{n}") do |v| instance_variable_set("@#{n}", true) end
129
- end
130
-
131
- %w{e g p T x y z P Z f A}.each do |n|
132
- opts.on("-#{n} S", String) do |v| instance_variable_set("@#{n}", v) end
133
- end
134
-
135
- %w{c n t b}.each do |n|
136
- opts.on("-#{n} S", Integer) do |v| instance_variable_set("@#{n}", v) end
137
- end
138
-
139
- opts.on('-H S', String) do |v| @H ||= []; @H << v; end
140
- opts.on('-C S', String) do |v| @C ||= []; @C << v; end
141
-
142
- opts.on('-b') do |v|
143
- Stella.warn("-b is not an ab option. I'll pretend it's not there.")
144
- end
145
-
146
- opts.on('-r N',Integer) do |v|
147
- Stella.error("-r is not an ab parameter. You probably want -n.")
148
- exit 1
149
- end
150
-
151
- # NOTE: parse! removes the options it finds in @arguments. It will leave
152
- # all unnamed arguments and throw a fit about unknown ones.
153
- opts.parse!(arguments)
154
-
155
- if arguments.empty?
156
- Stella.error("You need to provide a URI")
157
- exit 1
158
- elsif arguments.size > 1
159
- Stella.warn("ab can handle only one URI. The others will be ignored.")
160
- arguments = arguments.first
161
- else
162
- # Let's make sure the URI has a path (at least a trailing slash). Otherwise
163
- # ab gives a cryptic error.
164
- begin
165
- uri = URI.parse(arguments.first)
166
- if !uri || uri.path.empty?
167
- Stella.error("ab requires a trailing slash for #{uri.to_s}")
168
- exit 1
169
- end
170
- rescue => ex
171
- Stella.error("Bad URI: #{arguments.first}")
172
- exit 1
173
- end
174
- end
175
-
176
- self.arguments = arguments
177
-
178
- rescue OptionParser::InvalidOption => ex
179
- # We want to replace this text so we grab just the name of the argument
180
- badarg = ex.message.gsub('invalid option: ', '')
181
- raise InvalidArgument.new(badarg)
182
- end
183
-
184
- def after
185
- # We want to maintain copies of all test output, even when the user has
186
- # supplied other path names so we'll copy the files from the testrun directory
187
- # to the location specified by the user.
188
- # NOTE: For tests with more than one test run, the specified files will be
189
- # overwritten after each run. Should we force append the run number?
190
- [[@e, 'percentiles'], [@g, 'requests']].each do |tuple|
191
- if File.expand_path(File.dirname(tuple[0])) != File.expand_path(@working_directory)
192
- from = tuple[0]
193
- to = @working_directory + "/ab-#{tuple[1]}.log"
194
- next unless File.exists?(from)
195
- FileUtils.cp(from, to)
196
- end
197
- end
198
-
199
-
200
- end
201
-
202
-
203
-
204
-
205
- def add_header(name, value)
206
- @H ||= []
207
- @H << "#{name}: #{value}"
208
- end
209
-
210
- def user_agent=(list=[])
211
- return unless list && !list.empty?
212
- list = list.to_ary
213
- list.each do |agent|
214
- add_header("User-Agent", agent)
215
- end
216
- end
217
-
218
- def vusers
219
- c || 0
220
- end
221
- def vusers=(v)
222
- ratio = vuser_requests
223
- @c = v
224
- @n = ratio * @c
225
- end
226
- def requests
227
- n || 0
228
- end
229
- def requests=(v)
230
- @n = v
231
- end
232
- def vuser_requests
233
- ratio = 1
234
- # The request ratio tells us how many requests will be
235
- # generated per vuser. It helps us later when we need to
236
- # warmp up and ramp up.
237
- if @n > 0 && @c > 0
238
- ratio = (@n.to_f / @c.to_f).to_f
239
- # If concurrency isn't set, we'll assume the total number of requests
240
- # is intended to be per request
241
- elsif @n > 0
242
- ratio = @n
243
- end
244
- ratio
245
- end
246
- def c
247
- (@c * @load_factor).to_i
248
- end
249
- def n
250
- (@n * @load_factor).to_i
251
- end
252
-
253
- def hosts
254
- hosts = @arguments || []
255
- #hosts << get_hosts_from_file
256
- hosts = hosts.map{ |h| tmp = URI.parse(h.strip); "#{tmp.host}:#{tmp.port}" }
257
- hosts
258
- end
259
-
260
- def paths
261
- paths = @arguments || []
262
- #hosts << get_hosts_from_file
263
- paths = paths.map{ |h| tmp = URI.parse(h.strip); "#{tmp.path}?#{tmp.query}" }
264
- paths
265
- end
266
-
267
-
268
-
269
- # Apache bench writes the summary to STDOUT
270
- def summary_file
271
- File.new(stdout_path) if File.exists?(stdout_path)
272
- end
273
-
274
- def summary
275
- return unless summary_file
276
- raw = {}
277
- summary_file.each_line { |l|
278
- l.chomp!
279
- nvpair = l.split(':')
280
- next unless nvpair && nvpair.size == 2
281
- n = nvpair[0].strip.tr(' ', '_').downcase[/\w+/]
282
- v = nvpair[1].strip[/[\.\d]+/]
283
-
284
- # Apache Bench outputs two fields with the name "Time per request".
285
- # We want only the first one so we don't overwrite values.
286
- raw[n.to_sym] = v.to_f unless raw.has_key? n.to_sym
287
- }
288
-
289
- # Document Path: /
290
- # Document Length: 96 bytes
291
- #
292
- # Concurrency Level: 75
293
- # Time taken for tests: 2.001 seconds
294
- # Complete requests: 750
295
- # Failed requests: 0
296
- # Write errors: 0
297
- # Total transferred: 174000 bytes
298
- # HTML transferred: 72000 bytes
299
- # Requests per second: 374.74 [#/sec] (mean)
300
- # Time per request: 200.138 [ms] (mean)
301
- # Time per request: 2.669 [ms] (mean, across all concurrent requests)
302
- # Transfer rate: 84.90 [Kbytes/sec] received
303
-
304
- stats = Stella::Test::Run::Summary.new
305
-
306
- if !raw.empty? && raw.has_key?(:time_taken_for_tests)
307
-
308
- stats.elapsed_time = raw[:time_taken_for_tests]
309
-
310
- # We want this in MB, Apache Bench gives Bytes.
311
- stats.data_transferred = ((raw[:html_transferred] || 0) / 1_048_576)
312
-
313
- # total_transferred is header data + response data (html_transfered)
314
- stats.headers_transferred = ((raw[:total_transferred] || 0) / 1_048_576) - stats.data_transferred
315
-
316
- # Apache Bench returns ms
317
- stats.response_time = (raw[:time_per_request] || 0) / 1000
318
- stats.transaction_rate = raw[:requests_per_second]
319
-
320
- stats.vusers = raw[:concurrency_level].to_i
321
- stats.successful = raw[:complete_requests].to_i
322
- stats.failed = raw[:failed_requests].to_i
323
-
324
- stats.transactions = stats.successful + stats.failed
325
-
326
- #stats.raw = raw if @global_options.debug
327
- end
328
-
329
- stats
330
- end
331
-
332
-
333
-
334
- end
335
-
336
- end
337
- end