stella 0.5.3 → 0.5.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/{README.txt → README.textile} +63 -40
- data/Rakefile +7 -5
- data/bin/stella +1 -1
- data/bin/stella.bat +12 -0
- data/lib/pcaplet.rb +180 -0
- data/lib/stella/adapter/ab.rb +57 -33
- data/lib/stella/adapter/base.rb +11 -1
- data/lib/stella/adapter/httperf.rb +13 -10
- data/lib/stella/adapter/pcap_watcher.rb +221 -0
- data/lib/stella/adapter/proxy_watcher.rb +76 -0
- data/lib/stella/adapter/siege.rb +28 -11
- data/lib/stella/cli/agents.rb +2 -2
- data/lib/stella/cli/base.rb +37 -1
- data/lib/stella/cli/localtest.rb +1 -2
- data/lib/stella/cli/sysinfo.rb +17 -0
- data/lib/stella/cli/watch.rb +278 -0
- data/lib/stella/cli.rb +23 -11
- data/lib/stella/command/base.rb +1 -10
- data/lib/stella/command/localtest.rb +43 -23
- data/lib/stella/data/domain.rb +75 -0
- data/lib/stella/data/http.rb +124 -0
- data/lib/stella/logger.rb +16 -5
- data/lib/stella/storable.rb +4 -2
- data/lib/stella/support.rb +71 -0
- data/lib/stella/sysinfo.rb +247 -0
- data/lib/stella/test/base.rb +5 -1
- data/lib/stella/test/definition.rb +1 -1
- data/lib/stella/test/run/summary.rb +14 -4
- data/lib/stella/text/resource.rb +0 -1
- data/lib/stella.rb +28 -10
- data/lib/utils/domainutil.rb +47 -0
- data/lib/utils/fileutil.rb +22 -3
- data/lib/utils/httputil.rb +184 -128
- data/lib/utils/mathutil.rb +20 -7
- data/lib/win32/Console/ANSI.rb +305 -0
- data/lib/win32/Console.rb +970 -0
- data/spec/show-agents_spec.rb +0 -0
- data/support/kvm.h +91 -0
- data/support/ruby-pcap-takuma-notes.txt +19 -0
- data/support/ruby-pcap-takuma-patch.txt +30 -0
- data/support/text/en.yaml +26 -3
- data/vendor/frylock/README.textile +72 -0
- data/vendor/frylock/bin/example +170 -0
- data/vendor/frylock/frylock.gemspec +18 -0
- data/vendor/frylock/lib/frylock/exceptions.rb +24 -0
- data/vendor/frylock/lib/frylock.rb +232 -0
- data/vendor/frylock/test/command_test.rb +33 -0
- data/vendor/hitimes-0.4.0/HISTORY +28 -0
- data/vendor/hitimes-0.4.0/LICENSE.txt +19 -0
- data/vendor/hitimes-0.4.0/README +80 -0
- data/vendor/hitimes-0.4.0/Rakefile +63 -0
- data/vendor/hitimes-0.4.0/examples/benchmarks.rb +86 -0
- data/vendor/hitimes-0.4.0/examples/stats.rb +29 -0
- data/vendor/hitimes-0.4.0/ext/extconf.rb +15 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_ext.c +21 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_clock_gettime.c +20 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_osx.c +16 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_instant_windows.c +27 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.c +340 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_interval.h +73 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.c +242 -0
- data/vendor/hitimes-0.4.0/ext/hitimes_stats.h +30 -0
- data/vendor/hitimes-0.4.0/ext/rbconfig-mingw.rb +178 -0
- data/vendor/hitimes-0.4.0/ext/rbconfig.rb +178 -0
- data/vendor/hitimes-0.4.0/gemspec.rb +54 -0
- data/vendor/hitimes-0.4.0/lib/hitimes/mutexed_stats.rb +23 -0
- data/vendor/hitimes-0.4.0/lib/hitimes/paths.rb +54 -0
- data/vendor/hitimes-0.4.0/lib/hitimes/stats.rb +29 -0
- data/vendor/hitimes-0.4.0/lib/hitimes/timer.rb +223 -0
- data/vendor/hitimes-0.4.0/lib/hitimes/version.rb +42 -0
- data/vendor/hitimes-0.4.0/lib/hitimes.rb +24 -0
- data/vendor/hitimes-0.4.0/spec/interval_spec.rb +115 -0
- data/vendor/hitimes-0.4.0/spec/mutex_stats_spec.rb +34 -0
- data/vendor/hitimes-0.4.0/spec/paths_spec.rb +14 -0
- data/vendor/hitimes-0.4.0/spec/spec_helper.rb +6 -0
- data/vendor/hitimes-0.4.0/spec/stats_spec.rb +72 -0
- data/vendor/hitimes-0.4.0/spec/timer_spec.rb +105 -0
- data/vendor/hitimes-0.4.0/spec/version_spec.rb +27 -0
- data/vendor/hitimes-0.4.0/tasks/announce.rake +39 -0
- data/vendor/hitimes-0.4.0/tasks/config.rb +107 -0
- data/vendor/hitimes-0.4.0/tasks/distribution.rake +53 -0
- data/vendor/hitimes-0.4.0/tasks/documentation.rake +33 -0
- data/vendor/hitimes-0.4.0/tasks/extension.rake +64 -0
- data/vendor/hitimes-0.4.0/tasks/rspec.rake +31 -0
- data/vendor/hitimes-0.4.0/tasks/rubyforge.rake +52 -0
- data/vendor/hitimes-0.4.0/tasks/utils.rb +80 -0
- data/vendor/useragent/lib/user_agent.rb +1 -1
- metadata +87 -8
@@ -0,0 +1,124 @@
|
|
1
|
+
|
2
|
+
require 'utils/httputil'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Stella::Data
|
6
|
+
|
7
|
+
# TODO: Implement HTTPHeaders. We should be printing untouched headers.
|
8
|
+
# HTTPUtil should split the HTTP event lines and that's it. Replace
|
9
|
+
# parse_header_body with split_header_body
|
10
|
+
class HTTPHeaders < Stella::Storable
|
11
|
+
attr_reader :raw_data
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
@raw_data
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class HTTPRequest < Stella::Storable
|
20
|
+
attr_accessor :time, :client_ip, :server_ip, :header, :body, :method, :http_version
|
21
|
+
attr_reader :raw_data
|
22
|
+
attr_writer :uri, :body
|
23
|
+
attr_accessor :response
|
24
|
+
|
25
|
+
def has_body?
|
26
|
+
@body && !@body.nil & !@body.empty?
|
27
|
+
end
|
28
|
+
def has_request?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
def has_response?
|
32
|
+
(@response && @response.status && !@response.status.nil?)
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(raw_data=nil)
|
36
|
+
@raw_data = raw_data
|
37
|
+
if @raw_data
|
38
|
+
@method, @http_version, @uri, @header, @body = HTTPUtil::parse_http_request(raw_data)
|
39
|
+
end
|
40
|
+
@response = Stella::Data::HTTPResponse.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def uri
|
44
|
+
@uri.host = @server_ip.to_s if @uri && (@uri.host == 'unknown' || @uri.host.empty?)
|
45
|
+
@uri
|
46
|
+
end
|
47
|
+
|
48
|
+
def body
|
49
|
+
return nil unless @body
|
50
|
+
@body
|
51
|
+
#(!header || header[:Content_Type] || header[:Content_Type] !~ /text/) ? Base64.encode64(@body) : @body
|
52
|
+
end
|
53
|
+
|
54
|
+
def field_names
|
55
|
+
[ :time, :client_ip, :server_ip, :header, :uri, :body, :method, :http_version ]
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
headers = []
|
60
|
+
header.each_pair do |n,v|
|
61
|
+
headers << "#{n.to_s.gsub('_', '-')}: #{v[0]}"
|
62
|
+
end
|
63
|
+
str = "%s %s HTTP/%s" % [method, uri.to_s, http_version]
|
64
|
+
str << $/ + headers.join($/)
|
65
|
+
str << $/ + $/ + body if body
|
66
|
+
str
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
str = "%s: %s %s HTTP/%s" % [time.strftime(NICE_TIME_FORMAT), method, uri.to_s, http_version]
|
71
|
+
str
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class HTTPResponse < Stella::Storable
|
77
|
+
attr_accessor :time, :client_ip, :server_ip, :header, :status, :message, :http_version
|
78
|
+
attr_reader :raw_data
|
79
|
+
attr_writer :body
|
80
|
+
|
81
|
+
def initialize(raw_data=nil)
|
82
|
+
@raw_data = raw_data
|
83
|
+
if @raw_data
|
84
|
+
@status, @http_version, @message, @header, @body = HTTPUtil::parse_http_response(@raw_data)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def has_body?
|
89
|
+
@body && !@body.nil & !@body.empty?
|
90
|
+
end
|
91
|
+
def has_request?
|
92
|
+
false
|
93
|
+
end
|
94
|
+
def has_response?
|
95
|
+
false
|
96
|
+
end
|
97
|
+
|
98
|
+
def body
|
99
|
+
return nil unless @body
|
100
|
+
#Base64.encode64(@body)
|
101
|
+
(!header || !header[:Content_Type] || header[:Content_Type] !~ /text/) ? '' : @body
|
102
|
+
end
|
103
|
+
|
104
|
+
def field_names
|
105
|
+
[ :time, :client_ip, :server_ip, :header, :body, :status, :message, :http_version ]
|
106
|
+
end
|
107
|
+
|
108
|
+
def inspect
|
109
|
+
headers = []
|
110
|
+
header.each_pair do |n,v|
|
111
|
+
headers << "#{n.to_s.gsub('_', '-')}: #{v[0]}"
|
112
|
+
end
|
113
|
+
str = "HTTP/%s %s (%s)" % [@http_version, @status, @message]
|
114
|
+
str << $/ + headers.join($/)
|
115
|
+
str << $/ + $/ + body if body
|
116
|
+
str
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_s
|
120
|
+
str = "%s: HTTP/%s %s (%s)" % [time.strftime(NICE_TIME_FORMAT), @http_version, @status, @message]
|
121
|
+
str
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/stella/logger.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Stella
|
4
4
|
class Logger
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :debug_level
|
6
6
|
|
7
7
|
# +args+ is a hash of initialization arguments
|
8
8
|
# * <tt>:info_logger</tt> The IO class for info level logging. Default: STDOUT
|
@@ -10,7 +10,7 @@ module Stella
|
|
10
10
|
# * <tt>:debug_logger</tt> The IO class for error level logging. Default: STDERR
|
11
11
|
# * <tt>:debug</tt> Log debugging output, true or false (default)
|
12
12
|
def initialize(args={})
|
13
|
-
@
|
13
|
+
@debug_level = args[:debug] || false
|
14
14
|
@info_logger = args[:info_logger] || STDOUT
|
15
15
|
@error_logger = args[:error_logger] || STDERR
|
16
16
|
@debug_logger = args[:debug_logger] || STDERR
|
@@ -31,6 +31,12 @@ module Stella
|
|
31
31
|
@info_logger.flush
|
32
32
|
end
|
33
33
|
|
34
|
+
def flush
|
35
|
+
@info_logger.flush
|
36
|
+
@error_logger.flush
|
37
|
+
@debug_logger.flush
|
38
|
+
end
|
39
|
+
|
34
40
|
# Print all messages on a single line.
|
35
41
|
def info_print(*msgs)
|
36
42
|
msgs.each do |m|
|
@@ -46,15 +52,20 @@ module Stella
|
|
46
52
|
end
|
47
53
|
|
48
54
|
def debug(*msgs)
|
49
|
-
return unless @
|
55
|
+
return unless @debug_level
|
50
56
|
msgs.each do |m|
|
51
57
|
@debug_logger.puts "DEBUG: #{m}"
|
52
58
|
end
|
53
59
|
@debug_logger.flush
|
54
60
|
end
|
61
|
+
def warn(ex, prefix="WARN: ")
|
62
|
+
error(ex, prefix)
|
63
|
+
end
|
64
|
+
|
55
65
|
def error(ex, prefix="ERR: ")
|
56
|
-
|
57
|
-
|
66
|
+
msg = (ex.kind_of? String) ? ex : ex.message
|
67
|
+
@error_logger.puts "#{prefix}#{msg}"
|
68
|
+
return unless @debug_level && ex.kind_of?(Exception)
|
58
69
|
@error_logger.puts("#{prefix}------------------------------------------")
|
59
70
|
@error_logger.puts("#{prefix}#{ex.backtrace.join("\n")}")
|
60
71
|
@error_logger.puts("#{prefix}------------------------------------------")
|
data/lib/stella/storable.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
|
2
|
+
# TODO: Handle nested hashes and arrays.
|
2
3
|
|
3
4
|
module Stella
|
4
5
|
class Storable
|
5
|
-
|
6
|
+
NICE_TIME_FORMAT = "%Y-%m-%d@%H:%M:%S".freeze unless defined? NICE_TIME_FORMAT
|
7
|
+
|
6
8
|
SupportedFormats= {
|
7
9
|
'yaml' => 'yml', # format name => file extension
|
8
10
|
'yml' => 'yml',
|
@@ -96,7 +98,7 @@ module Stella
|
|
96
98
|
end
|
97
99
|
|
98
100
|
def self.from_hash(from={})
|
99
|
-
return if from.empty?
|
101
|
+
return if !from || from.empty?
|
100
102
|
me = self.new
|
101
103
|
fnames = me.to_hash.keys
|
102
104
|
fnames.each do |key|
|
data/lib/stella/support.rb
CHANGED
@@ -11,6 +11,7 @@ module Stella
|
|
11
11
|
def message
|
12
12
|
Stella::TEXT.err(:error_invalid_argument, @name)
|
13
13
|
end
|
14
|
+
|
14
15
|
end
|
15
16
|
|
16
17
|
class UnavailableAdapter < RuntimeError
|
@@ -36,6 +37,27 @@ module Stella
|
|
36
37
|
class UnsupportedLanguage < RuntimeError
|
37
38
|
end
|
38
39
|
|
40
|
+
class MissingDependency < RuntimeError
|
41
|
+
attr_accessor :dependency, :reason
|
42
|
+
def initialize(dependency, reason=:error_generic)
|
43
|
+
@dependency = dependency
|
44
|
+
@reason = (reason.kind_of? Symbol) ? Stella::TEXT.err(reason) : reason
|
45
|
+
end
|
46
|
+
def message
|
47
|
+
Stella::TEXT.err(:error_missing_dependency, @dependency, @reason)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class AdapterError < MissingDependency
|
52
|
+
def initialize(adapter, reason=:error_generic)
|
53
|
+
@adapter = adapter
|
54
|
+
@reason = (reason.kind_of? Symbol) ? Stella::TEXT.err(reason) : reason
|
55
|
+
end
|
56
|
+
def message
|
57
|
+
Stella::TEXT.err(:error_adapter_runtime, @adapter, @reason)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
39
61
|
class Util
|
40
62
|
|
41
63
|
# process_useragents
|
@@ -101,6 +123,55 @@ module Stella
|
|
101
123
|
str.split(/\s*[,\-]\s*/) # remove extra spaces at the same time.
|
102
124
|
end
|
103
125
|
|
126
|
+
|
127
|
+
# capture_output
|
128
|
+
#
|
129
|
+
# +cmd+ is a shell command to run with Kernel.` It will be appended with
|
130
|
+
# redirects to send STDOUT and STDERR to temp files. If the command already
|
131
|
+
# contains redirects they will be removed and replaced.
|
132
|
+
# The tempfiles are sent to yield as arrays of lines (using file_sout.readlines)
|
133
|
+
# and deleted before returning.
|
134
|
+
#
|
135
|
+
# We use files because popen and open3 are not implemented on Windows.
|
136
|
+
def self.capture_output(cmd)
|
137
|
+
return unless cmd
|
138
|
+
file_sout = Tempfile.new("stdout" << strand(6)) # We add a strand to be super sure it doesn't exist
|
139
|
+
file_serr = Tempfile.new("stderr" << strand(6))
|
140
|
+
cmd.gsub!(/1>.+/, '')
|
141
|
+
cmd.gsub!(/2>.+/, '')
|
142
|
+
cmd = "#{cmd} 1> \"#{file_sout.path}\" 2> \"#{file_serr.path}\""
|
143
|
+
begin
|
144
|
+
# Windows will have a conniption because the tempfiles are already open.
|
145
|
+
# We close them here and then open them to read them.
|
146
|
+
file_sout.close
|
147
|
+
file_serr.close
|
148
|
+
|
149
|
+
system(cmd)
|
150
|
+
|
151
|
+
file_sout.open
|
152
|
+
file_serr.open
|
153
|
+
sout, serr = file_sout.readlines, file_serr.readlines
|
154
|
+
file_sout.close
|
155
|
+
file_serr.close
|
156
|
+
|
157
|
+
yield(sout, serr)
|
158
|
+
|
159
|
+
ensure
|
160
|
+
file_sout.delete
|
161
|
+
file_serr.delete
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Generates a string of random alphanumeric characters
|
167
|
+
# These are used as IDs throughout the system
|
168
|
+
def self.strand( len )
|
169
|
+
chars = ("a".."z").to_a + ("0".."9").to_a
|
170
|
+
newpass = ""
|
171
|
+
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
|
172
|
+
return newpass
|
173
|
+
end
|
174
|
+
|
104
175
|
end
|
105
176
|
|
106
177
|
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Stella
|
4
|
+
# Stella::SystemInfo
|
5
|
+
#
|
6
|
+
# A container for the system platform information.
|
7
|
+
# Portions of this code is from Amazon's EC2 AMI tools, lib/platform.rb.
|
8
|
+
class SystemInfo < Stella::Storable
|
9
|
+
IMPLEMENTATIONS = [
|
10
|
+
# These are for JRuby, System.getproperty('os.name').
|
11
|
+
# For a list of all values, see: http://lopica.sourceforge.net/os.html
|
12
|
+
[/mac\s*os\s*x/i, :unix, :osx ],
|
13
|
+
[/sunos/i, :unix, :solaris ],
|
14
|
+
[/windows\s*ce/i, :win32, :windows ],
|
15
|
+
[/windows/i, :win32, :windows ],
|
16
|
+
[/osx/i, :unix, :osx ],
|
17
|
+
|
18
|
+
# These are for RUBY_PLATFORM and JRuby
|
19
|
+
[/java/i, :java, :java ],
|
20
|
+
[/darwin/i, :unix, :osx ],
|
21
|
+
[/linux/i, :unix, :linux ],
|
22
|
+
[/freebsd/i, :unix, :freebsd ],
|
23
|
+
[/netbsd/i, :unix, :netbsd ],
|
24
|
+
[/solaris/i, :unix, :solaris ],
|
25
|
+
[/irix/i, :unix, :irix ],
|
26
|
+
[/cygwin/i, :unix, :cygwin ],
|
27
|
+
[/mswin/i, :win32, :windows ],
|
28
|
+
[/mingw/i, :win32, :mingw ],
|
29
|
+
[/bccwin/i, :win32, :bccwin ],
|
30
|
+
[/wince/i, :win32, :wince ],
|
31
|
+
[/vms/i, :vms, :vms ],
|
32
|
+
[/os2/i, :os2, :os2 ],
|
33
|
+
[nil, :unknown, :unknown ],
|
34
|
+
]
|
35
|
+
|
36
|
+
ARCHITECTURES = [
|
37
|
+
[/(i\d86)/i, :i386 ],
|
38
|
+
[/x86_64/i, :x86_64 ],
|
39
|
+
[/x86/i, :i386 ], # JRuby
|
40
|
+
[/ia64/i, :ia64 ],
|
41
|
+
[/alpha/i, :alpha ],
|
42
|
+
[/sparc/i, :sparc ],
|
43
|
+
[/mips/i, :mips ],
|
44
|
+
[/powerpc/i, :powerpc ],
|
45
|
+
[/universal/i,:universal ],
|
46
|
+
[nil, :unknown ],
|
47
|
+
]
|
48
|
+
|
49
|
+
attr_reader :os
|
50
|
+
attr_reader :implementation
|
51
|
+
attr_reader :architecture
|
52
|
+
attr_reader :hostname
|
53
|
+
attr_reader :ipaddress
|
54
|
+
attr_reader :uptime
|
55
|
+
|
56
|
+
def field_names
|
57
|
+
[
|
58
|
+
:os, :implementation, :architecture, :hostname, :ipaddress, :uptime
|
59
|
+
]
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize
|
63
|
+
@os, @implementation, @architecture = guess
|
64
|
+
@hostname, @ipaddress, @uptime = get_info
|
65
|
+
end
|
66
|
+
|
67
|
+
# guess
|
68
|
+
#
|
69
|
+
# This is called at require-time in stella.rb. It guesses
|
70
|
+
# the current operating system, implementation, architecture.
|
71
|
+
# Returns [os, impl, arch]
|
72
|
+
def guess
|
73
|
+
os = :unknown
|
74
|
+
impl = :unknown
|
75
|
+
arch = :unknown
|
76
|
+
IMPLEMENTATIONS.each do |r, o, i|
|
77
|
+
if r and RUBY_PLATFORM =~ r
|
78
|
+
os, impl = [o, i]
|
79
|
+
break
|
80
|
+
end
|
81
|
+
end
|
82
|
+
ARCHITECTURES.each do |r, a|
|
83
|
+
if r and RUBY_PLATFORM =~ r
|
84
|
+
arch = a
|
85
|
+
break
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
if os == :win32
|
91
|
+
require 'Win32API'
|
92
|
+
|
93
|
+
# If we're running in java, we'll need to look elsewhere
|
94
|
+
# for the implementation and architecture.
|
95
|
+
# We'll replace IMPL and ARCH with what we find.
|
96
|
+
elsif os == :java
|
97
|
+
require 'java'
|
98
|
+
include_class java.lang.System
|
99
|
+
|
100
|
+
osname = System.getProperty("os.name")
|
101
|
+
IMPLEMENTATIONS.each do |r, o, i|
|
102
|
+
if r and osname =~ r
|
103
|
+
impl = i
|
104
|
+
break
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
osarch = System.getProperty("os.arch")
|
109
|
+
ARCHITECTURES.each do |r, a|
|
110
|
+
if r and osarch =~ r
|
111
|
+
arch = a
|
112
|
+
break
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
[os, impl, arch]
|
119
|
+
end
|
120
|
+
|
121
|
+
# get_info
|
122
|
+
#
|
123
|
+
# Returns [hostname, ipaddr, uptime] for the local machine
|
124
|
+
def get_info
|
125
|
+
hostname = :unknown
|
126
|
+
ipaddr = :unknown
|
127
|
+
uptime = :unknown
|
128
|
+
|
129
|
+
begin
|
130
|
+
hostname = Socket.gethostname
|
131
|
+
ipaddr = local_ip_address
|
132
|
+
uptime = local_uptime
|
133
|
+
rescue => ex
|
134
|
+
end
|
135
|
+
|
136
|
+
[hostname, ipaddr, uptime]
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# local_uptime
|
141
|
+
#
|
142
|
+
#
|
143
|
+
# Returns the local uptime in hours. Use Win32API in Windows,
|
144
|
+
# 'sysctl -b kern.boottime' os osx, and 'who -b' on unix.
|
145
|
+
# Based on Ruby Quiz solutions by: Matthias Reitinger
|
146
|
+
# On Windows, see also: net statistics server
|
147
|
+
def local_uptime
|
148
|
+
|
149
|
+
# Each method must return uptime in seconds
|
150
|
+
methods = {
|
151
|
+
|
152
|
+
:win32_windows => lambda {
|
153
|
+
# Win32API is required in self.guess
|
154
|
+
getTickCount = Win32API.new("kernel32", "GetTickCount", nil, 'L')
|
155
|
+
((getTickCount.call()).to_f / 1000).to_f
|
156
|
+
},
|
157
|
+
|
158
|
+
# Ya, this is kinda wack. Ruby -> Java -> Kernel32. See:
|
159
|
+
# http://www.oreillynet.com/ruby/blog/2008/01/jruby_meets_the_windows_api_1.html
|
160
|
+
# http://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx
|
161
|
+
# Ruby 1.9.1: Win32API is now deprecated in favor of using the DL library.
|
162
|
+
:java_windows => lambda {
|
163
|
+
kernel32 = com.sun.jna.NativeLibrary.getInstance('kernel32')
|
164
|
+
buf = java.nio.ByteBuffer.allocate(256)
|
165
|
+
(kernel32.getFunction('GetTickCount').invokeInt([256, buf].to_java).to_f / 1000).to_f
|
166
|
+
},
|
167
|
+
|
168
|
+
:unix_osx => lambda {
|
169
|
+
# This is faster than who and could work on BSD also.
|
170
|
+
(Time.now.to_f - Time.at(`sysctl -b kern.boottime 2>/dev/null`.unpack('L').first).to_f).to_f
|
171
|
+
|
172
|
+
},
|
173
|
+
# This should work for most unix flavours.
|
174
|
+
:unix => lambda {
|
175
|
+
# who is sloooooow. Use File.read('/proc/uptime')
|
176
|
+
(Time.now.to_f - Time.parse(`who -b 2>/dev/null`).to_f)
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
hours = 0
|
181
|
+
|
182
|
+
begin
|
183
|
+
key = platform
|
184
|
+
method = (methods.has_key? key) ? methods[key] : methods[:unix]
|
185
|
+
hours = (method.call) / 3600 # seconds to hours
|
186
|
+
rescue => ex
|
187
|
+
end
|
188
|
+
hours
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
# local_ip_address
|
193
|
+
#
|
194
|
+
# Return the local IP address which receives external traffic
|
195
|
+
# from: http://coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
|
196
|
+
# NOTE: This <em>does not</em> open a connection to the IP address.
|
197
|
+
def local_ip_address
|
198
|
+
# turn off reverse DNS resolution temporarily
|
199
|
+
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
|
200
|
+
UDPSocket.open {|s| s.connect('75.101.137.7', 1); s.addr.last } # Solutious IP
|
201
|
+
ensure
|
202
|
+
Socket.do_not_reverse_lookup = orig
|
203
|
+
end
|
204
|
+
|
205
|
+
# local_ip_address_alt
|
206
|
+
#
|
207
|
+
# Returns the local IP address based on the hostname.
|
208
|
+
# According to coderrr (see comments on blog link above), this implementation
|
209
|
+
# doesn't guarantee that it will return the address for the interface external
|
210
|
+
# traffic goes through. It's also possible the hostname isn't resolvable to the
|
211
|
+
# local IP.
|
212
|
+
def local_ip_address_alt
|
213
|
+
ipaddr = :unknown
|
214
|
+
begin
|
215
|
+
saddr = Socket.getaddrinfo( Socket.gethostname, nil, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
|
216
|
+
ipaddr = saddr.select{|type| type[0] == 'AF_INET' }[0][3]
|
217
|
+
rescue => ex
|
218
|
+
end
|
219
|
+
ipaddr
|
220
|
+
end
|
221
|
+
|
222
|
+
# platform
|
223
|
+
#
|
224
|
+
# returns a symbol in the form: os_implementation. This is used throughout Stella
|
225
|
+
# for platform specific support.
|
226
|
+
def platform
|
227
|
+
"#{@os}_#{@implementation}".to_sym
|
228
|
+
end
|
229
|
+
|
230
|
+
# ruby
|
231
|
+
#
|
232
|
+
# Returns Ruby version as an array
|
233
|
+
def ruby
|
234
|
+
RUBY_VERSION.split('.').map { |v| v.to_i }
|
235
|
+
end
|
236
|
+
|
237
|
+
# to_s
|
238
|
+
#
|
239
|
+
# Print friendly system information.
|
240
|
+
def to_s
|
241
|
+
sprintf("Hostname: %s#{$/}IP Address: %s#{$/}System: %s#{$/}Uptime: %.2f (hours)#{$/}Ruby: #{ruby.join('.')}",
|
242
|
+
@hostname, @ipaddress, "#{@os}-#{@implementation}-#{@architecture}", @uptime)
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
data/lib/stella/test/base.rb
CHANGED
@@ -45,7 +45,7 @@ module Stella
|
|
45
45
|
attr_accessor :warmup
|
46
46
|
# Contains an interval and maximum threshold to increase virtual users.
|
47
47
|
# Rampup object, [R,M] where R is the interval and M is the maximum.
|
48
|
-
|
48
|
+
attr_reader :rampup
|
49
49
|
# An array of string appropriate for a User-Agent HTTP header
|
50
50
|
attr_accessor :agents
|
51
51
|
# A short reminder to yourself what you're testing
|
@@ -25,15 +25,21 @@ module Stella::Test::Run
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def availability
|
28
|
-
|
29
|
-
|
28
|
+
begin
|
29
|
+
(@transactions / @successful).to_f * 100
|
30
|
+
rescue => ex
|
31
|
+
return 0.0
|
32
|
+
end
|
30
33
|
end
|
31
34
|
|
32
35
|
# We calculate the throughput because Apache Bench does not provide this
|
33
36
|
# value in the output.
|
34
37
|
def throughput
|
35
|
-
|
36
|
-
|
38
|
+
begin
|
39
|
+
return (@data_transferred / @elapsed_time).to_f
|
40
|
+
rescue => ex
|
41
|
+
return 0.0
|
42
|
+
end
|
37
43
|
end
|
38
44
|
|
39
45
|
def field_names
|
@@ -44,6 +50,10 @@ module Stella::Test::Run
|
|
44
50
|
]
|
45
51
|
end
|
46
52
|
|
53
|
+
def available?
|
54
|
+
@successful && @transactions && @elapsed_time && @vusers && @response_time
|
55
|
+
end
|
56
|
+
|
47
57
|
end
|
48
58
|
|
49
59
|
|
data/lib/stella/text/resource.rb
CHANGED
data/lib/stella.rb
CHANGED
@@ -1,26 +1,35 @@
|
|
1
1
|
|
2
|
-
$: << File.join(STELLA_HOME, 'vendor', 'useragent', 'lib')
|
3
|
-
|
4
2
|
|
5
3
|
require 'date'
|
6
|
-
require '
|
4
|
+
require 'time'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'socket'
|
7
7
|
|
8
8
|
# Common utilities
|
9
|
+
require 'utils/domainutil'
|
9
10
|
require 'utils/httputil'
|
10
|
-
require 'utils/crypto-key'
|
11
11
|
require 'utils/fileutil'
|
12
12
|
require 'utils/mathutil'
|
13
13
|
require 'utils/escape'
|
14
14
|
|
15
15
|
# Common dependencies
|
16
|
+
$: << File.join(STELLA_HOME, 'vendor', 'useragent', 'lib')
|
17
|
+
require 'user_agent'
|
18
|
+
|
19
|
+
# Common Stella dependencies
|
16
20
|
require 'stella/support'
|
17
21
|
require 'stella/storable'
|
18
|
-
require 'user_agent'
|
19
22
|
|
20
|
-
# Common
|
23
|
+
# Common Stella Data Objects
|
24
|
+
require 'stella/data/http'
|
25
|
+
require 'stella/data/domain'
|
26
|
+
|
27
|
+
# Common Stella objects
|
21
28
|
require 'stella/text'
|
29
|
+
|
22
30
|
require 'stella/logger'
|
23
31
|
require 'stella/response'
|
32
|
+
require 'stella/sysinfo'
|
24
33
|
require 'stella/test/definition'
|
25
34
|
require 'stella/test/run/summary'
|
26
35
|
require 'stella/test/summary'
|
@@ -38,14 +47,23 @@ require 'stella/adapter/httperf'
|
|
38
47
|
# = Stella
|
39
48
|
# A friend in performance testing.
|
40
49
|
#
|
50
|
+
# This class ties Stella together. It must be required because it defines
|
51
|
+
# several constants which are used througout the other classes. +SYSINFO+
|
52
|
+
# is particularly important because it detects the platform and requires
|
53
|
+
# platform specific modules.
|
41
54
|
module Stella
|
42
|
-
|
43
|
-
|
55
|
+
# Autodetecets information about the local system,
|
56
|
+
# including OS (unix), implementation (freebsd), and architecture (x64)
|
57
|
+
SYSINFO = Stella::SystemInfo.new unless defined? SYSINFO
|
58
|
+
# A global logger for info, error, and debug messages.
|
59
|
+
LOGGER = Stella::Logger.new(:debug=>true) unless defined? LOGGER
|
60
|
+
# A global resource for all interface text.
|
61
|
+
TEXT = Stella::Text.new('en') unless defined? TEXT
|
44
62
|
|
45
63
|
module VERSION #:nodoc:
|
46
64
|
MAJOR = 0.freeze unless defined? MAJOR
|
47
65
|
MINOR = 5.freeze unless defined? MINOR
|
48
|
-
TINY =
|
66
|
+
TINY = 4.freeze unless defined? TINY
|
49
67
|
def self.to_s
|
50
68
|
[MAJOR, MINOR, TINY].join('.')
|
51
69
|
end
|
@@ -53,6 +71,6 @@ module Stella
|
|
53
71
|
self.to_s.to_f
|
54
72
|
end
|
55
73
|
end
|
56
|
-
|
74
|
+
|
57
75
|
end
|
58
76
|
|