stella 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|