stella 0.5.4 → 0.5.5
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/README.textile +14 -10
- data/Rakefile +22 -36
- data/lib/daemonize.rb +56 -0
- data/lib/stella/adapter/ab.rb +49 -39
- data/lib/stella/adapter/base.rb +17 -8
- data/lib/stella/adapter/httperf.rb +24 -18
- data/lib/stella/adapter/pcap_watcher.rb +1 -1
- data/lib/stella/adapter/siege.rb +15 -12
- data/lib/stella/cli/localtest.rb +2 -3
- data/lib/stella/cli/sysinfo.rb +0 -1
- data/lib/stella/cli.rb +10 -55
- data/lib/stella/command/base.rb +0 -62
- data/lib/stella/command/localtest.rb +35 -36
- data/lib/stella/data/domain.rb +18 -11
- data/lib/stella/data/http.rb +23 -16
- data/lib/stella/logger.rb +29 -19
- data/lib/stella/response.rb +5 -2
- data/lib/stella/storable.rb +138 -52
- data/lib/stella/support.rb +107 -8
- data/lib/stella/sysinfo.rb +26 -16
- data/lib/stella/test/definition.rb +1 -1
- data/lib/stella/test/run/summary.rb +23 -13
- data/lib/stella/test/stats.rb +114 -0
- data/lib/stella/text/resource.rb +1 -1
- data/lib/stella.rb +29 -4
- data/lib/utils/mathutil.rb +0 -76
- data/lib/utils/stats.rb +88 -0
- data/lib/win32/Console/ANSI.rb +305 -305
- data/lib/win32/Console.rb +970 -970
- data/support/ruby-pcap-takuma-patch.txt +13 -13
- data/support/text/en.yaml +11 -8
- data/support/text/nl.yaml +7 -1
- data/{spec/show-agents_spec.rb → tests/01-util_test.rb} +0 -0
- data/tests/02-stella-util_test.rb +42 -0
- data/tests/10-stella_test.rb +104 -0
- data/tests/11-stella-storable_test.rb +68 -0
- data/tests/60-stella-command_test.rb +248 -0
- data/tests/80-stella-cli_test.rb +45 -0
- data/tests/spec-helper.rb +31 -0
- data/vendor/{frylock/README.textile → drydock/LICENSE.txt} +2 -52
- data/vendor/drydock/README.textile +57 -0
- data/vendor/{frylock → drydock}/bin/example +14 -14
- data/vendor/{frylock/frylock.gemspec → drydock/drydock.gemspec} +1 -1
- data/vendor/{frylock/lib/frylock → drydock/lib/drydock}/exceptions.rb +1 -1
- data/vendor/{frylock/lib/frylock.rb → drydock/lib/drydock.rb} +8 -8
- data/vendor/{frylock → drydock}/test/command_test.rb +0 -0
- metadata +34 -61
- data/lib/stella/test/base.rb +0 -38
- data/lib/stella/test/summary.rb +0 -82
- data/vendor/hitimes-0.4.0/HISTORY +0 -28
- data/vendor/hitimes-0.4.0/LICENSE.txt +0 -19
- data/vendor/hitimes-0.4.0/README +0 -80
- data/vendor/hitimes-0.4.0/Rakefile +0 -63
- data/vendor/hitimes-0.4.0/examples/benchmarks.rb +0 -86
- data/vendor/hitimes-0.4.0/examples/stats.rb +0 -29
- data/vendor/hitimes-0.4.0/ext/extconf.rb +0 -15
- data/vendor/hitimes-0.4.0/ext/hitimes_ext.c +0 -21
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_clock_gettime.c +0 -20
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_osx.c +0 -16
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_windows.c +0 -27
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.c +0 -340
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.h +0 -73
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.c +0 -242
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.h +0 -30
- data/vendor/hitimes-0.4.0/ext/rbconfig-mingw.rb +0 -178
- data/vendor/hitimes-0.4.0/ext/rbconfig.rb +0 -178
- data/vendor/hitimes-0.4.0/gemspec.rb +0 -54
- data/vendor/hitimes-0.4.0/lib/hitimes/mutexed_stats.rb +0 -23
- data/vendor/hitimes-0.4.0/lib/hitimes/paths.rb +0 -54
- data/vendor/hitimes-0.4.0/lib/hitimes/stats.rb +0 -29
- data/vendor/hitimes-0.4.0/lib/hitimes/timer.rb +0 -223
- data/vendor/hitimes-0.4.0/lib/hitimes/version.rb +0 -42
- data/vendor/hitimes-0.4.0/lib/hitimes.rb +0 -24
- data/vendor/hitimes-0.4.0/spec/interval_spec.rb +0 -115
- data/vendor/hitimes-0.4.0/spec/mutex_stats_spec.rb +0 -34
- data/vendor/hitimes-0.4.0/spec/paths_spec.rb +0 -14
- data/vendor/hitimes-0.4.0/spec/spec_helper.rb +0 -6
- data/vendor/hitimes-0.4.0/spec/stats_spec.rb +0 -72
- data/vendor/hitimes-0.4.0/spec/timer_spec.rb +0 -105
- data/vendor/hitimes-0.4.0/spec/version_spec.rb +0 -27
- data/vendor/hitimes-0.4.0/tasks/announce.rake +0 -39
- data/vendor/hitimes-0.4.0/tasks/config.rb +0 -107
- data/vendor/hitimes-0.4.0/tasks/distribution.rake +0 -53
- data/vendor/hitimes-0.4.0/tasks/documentation.rake +0 -33
- data/vendor/hitimes-0.4.0/tasks/extension.rake +0 -64
- data/vendor/hitimes-0.4.0/tasks/rspec.rake +0 -31
- data/vendor/hitimes-0.4.0/tasks/rubyforge.rake +0 -52
- data/vendor/hitimes-0.4.0/tasks/utils.rb +0 -80
data/README.textile
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
h1. Stella - Your Performance Testing Friend
|
|
2
2
|
|
|
3
|
-
Release: 0.5.
|
|
3
|
+
Release: 0.5.5 (2009-01-14)
|
|
4
4
|
|
|
5
5
|
This is a BETA release. Proceed in double verify mode!
|
|
6
6
|
|
|
7
|
+
h2. Overview
|
|
8
|
+
|
|
9
|
+
Stella is a command-line tool for running, reporting, and analyzing performance tests.
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
h2. Prerequisites
|
|
9
13
|
|
|
@@ -17,9 +21,10 @@ h2. Prerequisites
|
|
|
17
21
|
** Ruby-Pcap (optional, for packet sniffing)
|
|
18
22
|
|
|
19
23
|
* One of:
|
|
20
|
-
** "Apache Bench":http://httpd.apache.org/docs/2.
|
|
24
|
+
** "Apache Bench":http://httpd.apache.org/docs/2.2/programs/ab.html
|
|
21
25
|
** "Siege":http://www.joedog.org/index/siege-home
|
|
22
26
|
** "Httperf":http://www.hpl.hp.com/research/linux/httperf/
|
|
27
|
+
*** _Note: Argument handling for Httperf is incomplete_
|
|
23
28
|
|
|
24
29
|
|
|
25
30
|
h2. Installation
|
|
@@ -59,14 +64,14 @@ On Ruby, 1.8.6, Ruby-Pcap produces the following warnings at runtime: "pcap.bund
|
|
|
59
64
|
|
|
60
65
|
h2. Usage Examples
|
|
61
66
|
|
|
62
|
-
Run Apache Bench with a warmup and rampup from
|
|
63
|
-
$ stella --warmup=0.5 --rampup=
|
|
67
|
+
Run Apache Bench with a warmup and rampup from 10 to 20 virtual users in increments of 5
|
|
68
|
+
$ stella --warmup=0.5 --rampup=5,20 ab -c 10 -n 50 http://stellaaahhhh.com/search?term=trooper
|
|
64
69
|
|
|
65
70
|
Run Siege, repeat the test 5 times. Automatically creates a summary averages and standard deviations.
|
|
66
|
-
$ stella --agent=ff-3-osx --testruns=5 siege -c
|
|
71
|
+
$ stella --agent=ff-3-osx --testruns=5 siege -c 10 -r 5 -b http://stellaaahhhh.com/search?term=flock+of+seagulls
|
|
67
72
|
|
|
68
73
|
Run Httperf like you normally would (but all the test data will be collected for you)
|
|
69
|
-
$ stella httperf --hog --client=0/1 --server=127.0.0.1 --port=5600 --uri=/ --rate=50 --num-conns=
|
|
74
|
+
$ stella httperf --hog --client=0/1 --server=127.0.0.1 --port=5600 --uri=/ --rate=50 --num-conns=100 --timeout=5
|
|
70
75
|
|
|
71
76
|
Monitor DNS traffic using Pcap
|
|
72
77
|
$ stella watch -C dns
|
|
@@ -81,7 +86,7 @@ h2. Usage Examples
|
|
|
81
86
|
h3. Sample Output
|
|
82
87
|
|
|
83
88
|
<pre><code>
|
|
84
|
-
$ stella -f csv -x 5 -w 0.75 -r 25,125 -m "httpd 2.2.9-prefork" siege -c 75 -r 10 -b http://
|
|
89
|
+
$ stella -f csv -x 5 -w 0.75 -r 25,125 -m "httpd 2.2.9-prefork" siege -c 75 -r 10 -b http://testapp:5600/
|
|
85
90
|
Writing test data to: stella/testruns/2008-12-23/test-054
|
|
86
91
|
|
|
87
92
|
Warmup: 3750@37/1 100% 264.29/s 0.140s 0.024MB/s 0.340MB 14.000s .
|
|
@@ -137,10 +142,9 @@ h2. Known Issues
|
|
|
137
142
|
|
|
138
143
|
* The output for the REQ@VU/s columns is a work in progress. It's not aligned across tools and it will likely change in the next release.
|
|
139
144
|
* The summary data has not been audited. Don't trust and double verify!
|
|
140
|
-
* httperf is functional but
|
|
145
|
+
* httperf is functional but not all parameters are supported.
|
|
141
146
|
* The Ruby API has not been finalized. It's functional but there's no example because it is subject to change.
|
|
142
|
-
* There
|
|
143
|
-
* There is an issue with parsing ipv6 ip addresses with Ruby-Pcap or Net-DNS. This affects only dns sniffing with pcap. Reproduce by running "stella watch -P dns" and requesting "apple.com"
|
|
147
|
+
* There is an issue with parsing ipv6 ip addresses with Ruby-Pcap or Net-DNS. This affects only dns sniffing with pcap. Reproduce by running "stella watch -C dns" and requesting "apple.com"
|
|
144
148
|
|
|
145
149
|
|
|
146
150
|
h2. Report an issue
|
data/Rakefile
CHANGED
|
@@ -1,42 +1,29 @@
|
|
|
1
|
-
require 'rake'
|
|
2
|
-
require 'spec/rake/spectask'
|
|
3
1
|
|
|
4
|
-
|
|
5
|
-
Spec::Rake::SpecTask.new('spec') do |t|
|
|
6
|
-
t.spec_files = FileList['spec/*_spec.rb']
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
desc "Print specdocs"
|
|
10
|
-
Spec::Rake::SpecTask.new(:doc) do |t|
|
|
11
|
-
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
|
12
|
-
t.spec_files = FileList['spec/*_spec.rb']
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
desc "Run all examples with RCov"
|
|
16
|
-
Spec::Rake::SpecTask.new('rcov') do |t|
|
|
17
|
-
t.spec_files = FileList['spec/*_spec.rb']
|
|
18
|
-
t.rcov = true
|
|
19
|
-
t.rcov_opts = ['--exclude', 'examples']
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
task :default => :spec
|
|
23
|
-
|
|
24
|
-
######################################################
|
|
25
|
-
|
|
26
|
-
require 'rake'
|
|
27
|
-
require 'rake/testtask'
|
|
2
|
+
require 'rubygems'
|
|
28
3
|
require 'rake/clean'
|
|
29
4
|
require 'rake/gempackagetask'
|
|
30
5
|
require 'rake/rdoctask'
|
|
31
6
|
require 'fileutils'
|
|
32
7
|
include FileUtils
|
|
8
|
+
|
|
9
|
+
task :default => :test
|
|
10
|
+
|
|
11
|
+
# SPECS ===============================================================
|
|
12
|
+
|
|
13
|
+
desc 'Run specs with unit test style output'
|
|
14
|
+
task :test do |t|
|
|
15
|
+
# sh "specrb -s tests/*_test.rb"
|
|
16
|
+
sh "specrb -s tests/*_test.rb"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# PACKAGE =============================================================
|
|
20
|
+
|
|
33
21
|
|
|
34
22
|
STELLA_HOME = File.expand_path(File.join(File.dirname(__FILE__)))
|
|
35
23
|
$: << File.join(STELLA_HOME, 'lib')
|
|
36
24
|
|
|
37
25
|
require 'stella'
|
|
38
26
|
version = Stella::VERSION.to_s
|
|
39
|
-
|
|
40
27
|
name = "stella"
|
|
41
28
|
|
|
42
29
|
spec = Gem::Specification.new do |s|
|
|
@@ -52,15 +39,14 @@ spec = Gem::Specification.new do |s|
|
|
|
52
39
|
s.extra_rdoc_files = ['README.textile']
|
|
53
40
|
|
|
54
41
|
# NOTE: how to make optional dependencies?
|
|
55
|
-
|
|
42
|
+
s.add_dependency 'mongrel'
|
|
56
43
|
s.add_dependency 'rspec'
|
|
57
44
|
s.add_dependency 'net-dns'
|
|
58
|
-
#s.add_dependency 'session'
|
|
59
45
|
|
|
60
46
|
s.platform = Gem::Platform::RUBY
|
|
61
47
|
s.has_rdoc = true
|
|
62
48
|
|
|
63
|
-
s.files = %w(Rakefile) + Dir.glob("{bin,doc,lib,
|
|
49
|
+
s.files = %w(Rakefile) + Dir.glob("{bin,doc,lib,tests,support,vendor}/**/**/*")
|
|
64
50
|
|
|
65
51
|
s.require_path = "lib"
|
|
66
52
|
s.bindir = "bin"
|
|
@@ -71,6 +57,7 @@ Rake::GemPackageTask.new(spec) do |p|
|
|
|
71
57
|
end
|
|
72
58
|
|
|
73
59
|
|
|
60
|
+
|
|
74
61
|
task :install => [ :rdoc, :package ] do
|
|
75
62
|
sh %{sudo gem install pkg/#{name}-#{version}.gem}
|
|
76
63
|
end
|
|
@@ -79,11 +66,7 @@ task :uninstall => [ :clean ] do
|
|
|
79
66
|
sh %{sudo gem uninstall #{name}}
|
|
80
67
|
end
|
|
81
68
|
|
|
82
|
-
|
|
83
|
-
t.libs << "spec"
|
|
84
|
-
t.test_files = FileList['spec/*_spec.rb']
|
|
85
|
-
t.verbose = true
|
|
86
|
-
end
|
|
69
|
+
|
|
87
70
|
|
|
88
71
|
Rake::RDocTask.new do |t|
|
|
89
72
|
t.rdoc_dir = 'doc'
|
|
@@ -91,7 +74,8 @@ Rake::RDocTask.new do |t|
|
|
|
91
74
|
t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
|
92
75
|
t.options << '--charset' << 'utf-8'
|
|
93
76
|
t.rdoc_files.include('LICENSE.txt')
|
|
94
|
-
t.rdoc_files.include('README.
|
|
77
|
+
t.rdoc_files.include('README.textile')
|
|
78
|
+
t.rdoc_files.include('CHANGES.txt')
|
|
95
79
|
t.rdoc_files.include('lib/utils/*.rb')
|
|
96
80
|
t.rdoc_files.include('lib/stella.rb')
|
|
97
81
|
t.rdoc_files.include('lib/stella/*.rb')
|
|
@@ -100,3 +84,5 @@ end
|
|
|
100
84
|
|
|
101
85
|
CLEAN.include [ 'pkg', '*.gem', '.config', 'doc' ]
|
|
102
86
|
|
|
87
|
+
|
|
88
|
+
|
data/lib/daemonize.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
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/stella/adapter/ab.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
require 'fileutils'
|
|
3
3
|
|
|
4
4
|
module Stella
|
|
5
5
|
module Adapter
|
|
@@ -45,12 +45,14 @@ module Stella
|
|
|
45
45
|
attr_accessor :C, :H, :A, :P, :X, :V, :k, :d, :S, :e, :g, :r, :h, :Z, :f
|
|
46
46
|
|
|
47
47
|
def initialize(options={}, arguments=[])
|
|
48
|
-
super(options, arguments)
|
|
49
48
|
@private_variables = ['private_variables', 'name', 'arguments', 'load_factor', 'working_directory']
|
|
50
49
|
@c = 1
|
|
51
50
|
@n = 1
|
|
52
51
|
@name = 'ab'
|
|
53
52
|
@load_factor = 1
|
|
53
|
+
|
|
54
|
+
super(options, arguments)
|
|
55
|
+
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def error
|
|
@@ -65,14 +67,17 @@ module Stella
|
|
|
65
67
|
vsn
|
|
66
68
|
end
|
|
67
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
|
+
|
|
68
78
|
def before
|
|
69
|
-
|
|
70
|
-
@
|
|
71
|
-
@e = File.expand_path(@e)
|
|
72
|
-
|
|
73
|
-
@g = @working_directory + "/ab-requests.log"
|
|
74
|
-
@g = File.expand_path(@g)
|
|
75
|
-
|
|
79
|
+
@e = percentiles_file if @e.nil?
|
|
80
|
+
@g = requests_file if @g.nil?
|
|
76
81
|
end
|
|
77
82
|
|
|
78
83
|
def command
|
|
@@ -83,12 +88,12 @@ module Stella
|
|
|
83
88
|
instance_variables.each do |name|
|
|
84
89
|
canon = name.to_s.tr('@', '') # instance_variables returns '@name'
|
|
85
90
|
next if @private_variables.member?(canon)
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
# It's important that we take the value from the getter method
|
|
88
93
|
# because it applies the load factor.
|
|
89
94
|
value = self.send(canon)
|
|
90
95
|
if (value.is_a? Array)
|
|
91
|
-
value.each { |el| command << "-#{canon} #{EscapeUtil.shell_single_word(
|
|
96
|
+
value.each { |el| command << "-#{canon} #{EscapeUtil.shell_single_word(value.to_s)} " }
|
|
92
97
|
else
|
|
93
98
|
command << "-#{canon} #{EscapeUtil.shell_single_word(value.to_s)} "
|
|
94
99
|
end
|
|
@@ -96,6 +101,7 @@ module Stella
|
|
|
96
101
|
end
|
|
97
102
|
|
|
98
103
|
command << (@arguments.map { |uri| "#{uri}" }).join(' ') unless @arguments.empty?
|
|
104
|
+
|
|
99
105
|
command
|
|
100
106
|
end
|
|
101
107
|
# loadtest
|
|
@@ -111,32 +117,34 @@ module Stella
|
|
|
111
117
|
end
|
|
112
118
|
|
|
113
119
|
|
|
114
|
-
def
|
|
115
|
-
options = OpenStruct.new
|
|
120
|
+
def process_arguments(arguments)
|
|
116
121
|
opts = OptionParser.new
|
|
117
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
|
+
|
|
118
126
|
# TODO: Print a note for w that we don't parse the HTML results
|
|
119
127
|
%w{v w i V k d S r h}.each do |n|
|
|
120
|
-
opts.on("-#{n}") do |v|
|
|
128
|
+
opts.on("-#{n}") do |v| instance_variable_set("@#{n}", true) end
|
|
121
129
|
end
|
|
122
130
|
|
|
123
131
|
%w{e g p T x y z P Z f A}.each do |n|
|
|
124
|
-
opts.on("-#{n} S", String) do |v|
|
|
132
|
+
opts.on("-#{n} S", String) do |v| instance_variable_set("@#{n}", v) end
|
|
125
133
|
end
|
|
126
134
|
|
|
127
135
|
%w{c n t b}.each do |n|
|
|
128
|
-
opts.on("-#{n} S", Integer) do |v|
|
|
136
|
+
opts.on("-#{n} S", Integer) do |v| instance_variable_set("@#{n}", v) end
|
|
129
137
|
end
|
|
130
138
|
|
|
131
|
-
opts.on('-H S', String) do |v|
|
|
132
|
-
opts.on('-C S', String) do |v|
|
|
139
|
+
opts.on('-H S', String) do |v| @H ||= []; @H << v; end
|
|
140
|
+
opts.on('-C S', String) do |v| @C ||= []; @C << v; end
|
|
133
141
|
|
|
134
142
|
opts.on('-b') do |v|
|
|
135
|
-
Stella
|
|
143
|
+
Stella.warn("-b is not an ab option. I'll pretend it's not there.")
|
|
136
144
|
end
|
|
137
145
|
|
|
138
146
|
opts.on('-r N',Integer) do |v|
|
|
139
|
-
Stella
|
|
147
|
+
Stella.error("-r is not an ab parameter. You probably want -n.")
|
|
140
148
|
exit 1
|
|
141
149
|
end
|
|
142
150
|
|
|
@@ -145,10 +153,10 @@ module Stella
|
|
|
145
153
|
opts.parse!(arguments)
|
|
146
154
|
|
|
147
155
|
if arguments.empty?
|
|
148
|
-
Stella
|
|
156
|
+
Stella.error("You need to provide a URI")
|
|
149
157
|
exit 1
|
|
150
158
|
elsif arguments.size > 1
|
|
151
|
-
Stella
|
|
159
|
+
Stella.warn("ab can handle only one URI. The others will be ignored.")
|
|
152
160
|
arguments = arguments.first
|
|
153
161
|
else
|
|
154
162
|
# Let's make sure the URI has a path (at least a trailing slash). Otherwise
|
|
@@ -156,17 +164,17 @@ module Stella
|
|
|
156
164
|
begin
|
|
157
165
|
uri = URI.parse(arguments.first)
|
|
158
166
|
if !uri || uri.path.empty?
|
|
159
|
-
Stella
|
|
167
|
+
Stella.error("ab requires a trailing slash for #{uri.to_s}")
|
|
160
168
|
exit 1
|
|
161
169
|
end
|
|
162
170
|
rescue => ex
|
|
163
|
-
Stella
|
|
171
|
+
Stella.error("Bad URI: #{arguments.first}")
|
|
164
172
|
exit 1
|
|
165
173
|
end
|
|
166
174
|
end
|
|
167
175
|
|
|
176
|
+
self.arguments = arguments
|
|
168
177
|
|
|
169
|
-
options
|
|
170
178
|
rescue OptionParser::InvalidOption => ex
|
|
171
179
|
# We want to replace this text so we grab just the name of the argument
|
|
172
180
|
badarg = ex.message.gsub('invalid option: ', '')
|
|
@@ -176,17 +184,19 @@ module Stella
|
|
|
176
184
|
def after
|
|
177
185
|
# We want to maintain copies of all test output, even when the user has
|
|
178
186
|
# supplied other path names so we'll copy the files from the testrun directory
|
|
179
|
-
# to the location specified by the user
|
|
180
|
-
|
|
181
|
-
|
|
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)
|
|
182
192
|
from = tuple[0]
|
|
183
|
-
to = @
|
|
193
|
+
to = @working_directory + "/ab-#{tuple[1]}.log"
|
|
184
194
|
next unless File.exists?(from)
|
|
185
|
-
|
|
195
|
+
FileUtils.cp(from, to)
|
|
186
196
|
end
|
|
187
197
|
end
|
|
188
198
|
|
|
189
|
-
|
|
199
|
+
|
|
190
200
|
end
|
|
191
201
|
|
|
192
202
|
|
|
@@ -257,14 +267,14 @@ module Stella
|
|
|
257
267
|
|
|
258
268
|
|
|
259
269
|
# Apache bench writes the summary to STDOUT
|
|
260
|
-
def
|
|
270
|
+
def summary_file
|
|
261
271
|
File.new(stdout_path) if File.exists?(stdout_path)
|
|
262
272
|
end
|
|
263
273
|
|
|
264
|
-
def
|
|
265
|
-
return unless
|
|
274
|
+
def summary
|
|
275
|
+
return unless summary_file
|
|
266
276
|
raw = {}
|
|
267
|
-
|
|
277
|
+
summary_file.each_line { |l|
|
|
268
278
|
l.chomp!
|
|
269
279
|
nvpair = l.split(':')
|
|
270
280
|
next unless nvpair && nvpair.size == 2
|
|
@@ -292,8 +302,8 @@ module Stella
|
|
|
292
302
|
# Transfer rate: 84.90 [Kbytes/sec] received
|
|
293
303
|
|
|
294
304
|
stats = Stella::Test::Run::Summary.new
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
|
|
306
|
+
if !raw.empty? && raw.has_key?(:time_taken_for_tests)
|
|
297
307
|
|
|
298
308
|
stats.elapsed_time = raw[:time_taken_for_tests]
|
|
299
309
|
|
|
@@ -312,10 +322,10 @@ module Stella
|
|
|
312
322
|
stats.failed = raw[:failed_requests].to_i
|
|
313
323
|
|
|
314
324
|
stats.transactions = stats.successful + stats.failed
|
|
315
|
-
|
|
325
|
+
|
|
316
326
|
#stats.raw = raw if @global_options.debug
|
|
317
327
|
end
|
|
318
|
-
|
|
328
|
+
|
|
319
329
|
stats
|
|
320
330
|
end
|
|
321
331
|
|
data/lib/stella/adapter/base.rb
CHANGED
|
@@ -10,12 +10,16 @@ module Stella::Adapter
|
|
|
10
10
|
class Base
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
attr_accessor :working_directory
|
|
13
|
+
attr_accessor :working_directory
|
|
14
14
|
attr_reader :load_factor, :arguments
|
|
15
15
|
|
|
16
16
|
def initialize(options={}, arguments=[])
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
if options.is_a? Array
|
|
18
|
+
self.process_arguments(options)
|
|
19
|
+
else
|
|
20
|
+
self.options = options
|
|
21
|
+
self.arguments = arguments
|
|
22
|
+
end
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
def load_factor=(load_factor)
|
|
@@ -33,22 +37,23 @@ module Stella::Adapter
|
|
|
33
37
|
File.join(@working_directory, "SUMMARY.#{ext}")
|
|
34
38
|
end
|
|
35
39
|
|
|
36
|
-
#
|
|
40
|
+
# process_arguments
|
|
37
41
|
#
|
|
38
42
|
# This method must be overridden by the implementing class. This is intended
|
|
39
43
|
# for processing the command-specific command-line arguments
|
|
40
|
-
|
|
41
|
-
def process_options
|
|
44
|
+
def process_arguments
|
|
42
45
|
raise Stella::TEXT.msg(:error_class_must_override, 'process_options')
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
# options=
|
|
46
49
|
#
|
|
47
|
-
# Takes a hash
|
|
50
|
+
# Takes a hash, OpenStruct and applies the values to the instance variables.
|
|
48
51
|
# The keys should conincide with with the command line argument names.
|
|
52
|
+
# by process_options first and
|
|
49
53
|
# i.e. The key for --help should be :help
|
|
50
54
|
def options=(options={})
|
|
51
55
|
options = options.marshal_dump if options.is_a? OpenStruct
|
|
56
|
+
|
|
52
57
|
unless options.nil? || options.empty?
|
|
53
58
|
options.each_pair do |name,value|
|
|
54
59
|
next if @private_variables.member?(name)
|
|
@@ -71,7 +76,7 @@ module Stella::Adapter
|
|
|
71
76
|
end
|
|
72
77
|
|
|
73
78
|
def rate
|
|
74
|
-
|
|
79
|
+
@rate || 0
|
|
75
80
|
end
|
|
76
81
|
def vuser_rate
|
|
77
82
|
"#{vusers}/#{rate}"
|
|
@@ -81,6 +86,10 @@ module Stella::Adapter
|
|
|
81
86
|
raise Stella::TEXT.msg(:error_class_must_override, 'command')
|
|
82
87
|
end
|
|
83
88
|
|
|
89
|
+
def summary
|
|
90
|
+
raise Stella::TEXT.msg(:error_class_must_override, 'summary')
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
def add_header
|
|
85
94
|
raise Stella::TEXT.msg(:error_class_must_override, 'add_header')
|
|
86
95
|
end
|
|
@@ -29,11 +29,12 @@ module Stella
|
|
|
29
29
|
attr_writer :version, :add_header, :wlog, :wsess, :wsesslog, :wset
|
|
30
30
|
|
|
31
31
|
def initialize(options={}, arguments=[])
|
|
32
|
-
super(options, arguments)
|
|
33
|
-
@name = 'httperf'
|
|
34
32
|
|
|
33
|
+
@name = 'httperf'
|
|
35
34
|
@private_variables = ['private_variables', 'name', 'arguments', 'load_factor', 'working_directory']
|
|
36
35
|
@load_factor = 1
|
|
36
|
+
|
|
37
|
+
super(options, arguments)
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
|
|
@@ -75,13 +76,10 @@ module Stella
|
|
|
75
76
|
def after
|
|
76
77
|
|
|
77
78
|
|
|
78
|
-
save_stats
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
def process_options(arguments)
|
|
81
|
+
def process_arguments(arguments)
|
|
83
82
|
|
|
84
|
-
options = OpenStruct.new
|
|
85
83
|
opts = OptionParser.new
|
|
86
84
|
opts.on('--hog') do @hog = true end
|
|
87
85
|
opts.on('--server=S', String) do |v| @server = v end
|
|
@@ -126,17 +124,21 @@ module Stella
|
|
|
126
124
|
|
|
127
125
|
|
|
128
126
|
opts.on('--wlog=S', String) do |v| @wlog = Stella::Util::expand_str(v) end
|
|
129
|
-
opts.on('--wsess=S', String) do |v| @wsess = Stella::Util::expand_str(v) end
|
|
127
|
+
opts.on('--wsess=S', String) do |v| @wsess = Stella::Util::expand_str(v, Integer) end
|
|
130
128
|
opts.on('--wsesslog=S', String) do |v| @wsesslog = Stella::Util::expand_str(v) end
|
|
131
129
|
opts.on('--wset=S', String) do |v| @wset = Stella::Util::expand_str(v) end
|
|
130
|
+
|
|
131
|
+
if @wsess
|
|
132
132
|
|
|
133
|
+
end
|
|
134
|
+
|
|
133
135
|
# parse! removes the options it finds.
|
|
134
136
|
# It also fails when it finds unknown switches (i.e. -X)
|
|
135
137
|
# Which should leave only the remaining arguments (URIs in this case)
|
|
136
138
|
opts.parse!(arguments)
|
|
137
|
-
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
self.arguments = arguments
|
|
141
|
+
|
|
140
142
|
rescue OptionParser::InvalidOption => ex
|
|
141
143
|
# We want to replace this text so we grab just the name of the argument
|
|
142
144
|
badarg = ex.message.gsub('invalid option: ', '')
|
|
@@ -181,13 +183,17 @@ module Stella
|
|
|
181
183
|
end
|
|
182
184
|
end
|
|
183
185
|
def vusers
|
|
184
|
-
@
|
|
186
|
+
@wsess[1]
|
|
185
187
|
end
|
|
188
|
+
def vuser_rate
|
|
189
|
+
"#{vusers}/#{rate}"
|
|
190
|
+
end
|
|
191
|
+
|
|
186
192
|
def vusers=(v)
|
|
187
193
|
0
|
|
188
194
|
end
|
|
189
195
|
def requests
|
|
190
|
-
@num_conns
|
|
196
|
+
@num_conns || (@wsess[0] * @wsess[1])
|
|
191
197
|
end
|
|
192
198
|
def requests=(v)
|
|
193
199
|
0
|
|
@@ -224,7 +230,7 @@ module Stella
|
|
|
224
230
|
|
|
225
231
|
|
|
226
232
|
# Siege writes the summary to STDERR
|
|
227
|
-
def
|
|
233
|
+
def summary_file
|
|
228
234
|
File.new(stdout_path) if File.exists?(stdout_path)
|
|
229
235
|
end
|
|
230
236
|
|
|
@@ -265,10 +271,10 @@ module Stella
|
|
|
265
271
|
# Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
|
|
266
272
|
# Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
|
|
267
273
|
|
|
268
|
-
def
|
|
269
|
-
return unless
|
|
274
|
+
def summary
|
|
275
|
+
return unless summary_file
|
|
270
276
|
|
|
271
|
-
raw =
|
|
277
|
+
raw = summary_file.readlines.join
|
|
272
278
|
stats = Stella::Test::Run::Summary.new
|
|
273
279
|
|
|
274
280
|
raw.scan(/Request rate: (\d+?\.\d+?) req.s .(\d+?\.\d+?) ms.req./) do |rate,time|
|
|
@@ -283,12 +289,12 @@ module Stella
|
|
|
283
289
|
stats.transactions = conn.to_i
|
|
284
290
|
end
|
|
285
291
|
|
|
286
|
-
raw.scan(/
|
|
287
|
-
stats.data_transferred = ((t.to_f || 0 ) / 1_048_576).to_f
|
|
292
|
+
raw.scan(/header (\d+\.\d+?)\s+.+?\s+.total (\d+\.\d+?)./) do |h,t|
|
|
293
|
+
stats.data_transferred = ((t.to_f || 0 ) / 1_048_576).to_f
|
|
294
|
+
stats.headers_transferred = ((h.to_f || 0 ) / 1_048_576).to_f
|
|
288
295
|
end
|
|
289
296
|
stats.vusers = self.vusers
|
|
290
297
|
|
|
291
|
-
|
|
292
298
|
stats
|
|
293
299
|
end
|
|
294
300
|
|
|
@@ -61,7 +61,7 @@ module Stella
|
|
|
61
61
|
@sport = options[:port] || @dport
|
|
62
62
|
|
|
63
63
|
@device = options[:device] || guess_device
|
|
64
|
-
@snaplen = options[:snaplen] ||
|
|
64
|
+
@snaplen = options[:snaplen] || 10000 # 10KB
|
|
65
65
|
@maxpacks = options[:maxpacks] || 100_000
|
|
66
66
|
|
|
67
67
|
Stella::LOGGER.info("Watching interface #{@device} for #{@service} activity on #{@protocol} port #{@dport}")
|