stella 0.7.1 → 0.7.2
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/CHANGES.txt +16 -0
- data/Rudyfile +63 -27
- data/bin/stella +1 -0
- data/examples/essentials/plan.rb +1 -1
- data/examples/exceptions/plan.rb +1 -1
- data/lib/stella.rb +5 -1
- data/lib/stella/cli.rb +1 -1
- data/lib/stella/client.rb +119 -53
- data/lib/stella/client/container.rb +264 -14
- data/lib/stella/client/modifiers.rb +1 -0
- data/lib/stella/data.rb +182 -61
- data/lib/stella/data/http/request.rb +20 -2
- data/lib/stella/engine.rb +6 -2
- data/lib/stella/engine/functional.rb +35 -20
- data/lib/stella/engine/load_create.rb +2 -0
- data/lib/stella/engine/load_queue.rb +27 -7
- data/lib/stella/engine/loadbase.rb +22 -12
- data/lib/stella/testplan.rb +8 -1
- data/lib/stella/testplan/usecase.rb +14 -1
- data/lib/stella/version.rb +2 -2
- data/stella.gemspec +3 -1
- data/support/sample_webapp/app.rb +0 -1
- data/tryouts/configs/failed_requests.rb +31 -0
- data/tryouts/configs/global_sequential.rb +18 -0
- data/vendor/httpclient-2.1.5.2/httpclient.rb +2 -2
- metadata +5 -3
@@ -32,6 +32,7 @@ module Stella::Data::HTTP
|
|
32
32
|
@uri = uri_str
|
33
33
|
@http_method, @http_version = method, version
|
34
34
|
@headers, @params, @response_handler = {}, {}, {}
|
35
|
+
@resources = {}
|
35
36
|
@wait = 0
|
36
37
|
@desc = "Request"
|
37
38
|
@body = Stella::Data::HTTP::Body.new
|
@@ -55,13 +56,30 @@ module Stella::Data::HTTP
|
|
55
56
|
alias_method :sleep, :wait
|
56
57
|
|
57
58
|
def headers(*args)
|
58
|
-
|
59
|
+
unless args.empty?
|
60
|
+
h = Hash === args[0] ? args[0] : {args[0]=> args[1]}
|
61
|
+
@headers.merge! h unless h.empty?
|
62
|
+
end
|
59
63
|
@headers
|
60
64
|
end
|
61
65
|
alias_method :header, :headers
|
62
66
|
|
67
|
+
# Set a resource key value pair in the get, post block.
|
68
|
+
# These will be process later in Stella::Client
|
69
|
+
def set(*args)
|
70
|
+
unless args.empty?
|
71
|
+
h = Hash === args[0] ? args[0] : {args[0]=> args[1]}
|
72
|
+
@resources.merge! h unless h.empty?
|
73
|
+
end
|
74
|
+
@resources
|
75
|
+
end
|
76
|
+
alias_method :resources, :set
|
77
|
+
|
63
78
|
def params(*args)
|
64
|
-
|
79
|
+
unless args.empty?
|
80
|
+
h = Hash === args[0] ? args[0] : {args[0]=> args[1]}
|
81
|
+
@params.merge! h unless h.empty?
|
82
|
+
end
|
65
83
|
@params
|
66
84
|
end
|
67
85
|
alias_method :param, :params
|
data/lib/stella/engine.rb
CHANGED
@@ -10,13 +10,17 @@ module Stella::Engine
|
|
10
10
|
def update(*args)
|
11
11
|
what, *args = args
|
12
12
|
if respond_to?("update_#{what}")
|
13
|
-
Stella.ld "OBSERVER UPDATE: #{what}"
|
13
|
+
#Stella.ld "OBSERVER UPDATE: #{what}"
|
14
14
|
Stella.rescue { self.send("update_#{what}", *args) }
|
15
15
|
else
|
16
16
|
Stella.ld "NO UPDATE HANDLER FOR: #{what}"
|
17
17
|
end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
|
+
def runid
|
21
|
+
|
22
|
+
end
|
23
|
+
|
20
24
|
def process_options!(plan, opts={})
|
21
25
|
opts = {
|
22
26
|
:hosts => [],
|
@@ -19,6 +19,9 @@ module Stella::Engine
|
|
19
19
|
Stella.lflush
|
20
20
|
sleep 0.3
|
21
21
|
|
22
|
+
# Identify this thread to Benelux
|
23
|
+
Benelux.current_track :functional
|
24
|
+
|
22
25
|
dig = Stella.loglev > 1 ? plan.digest_cache : plan.digest_cache.shorter
|
23
26
|
Stella.li " %-65s ".att(:reverse) % ["#{plan.desc} (#{dig})"]
|
24
27
|
plan.usecases.each_with_index do |uc,i|
|
@@ -28,11 +31,8 @@ module Stella::Engine
|
|
28
31
|
Stella.rescue { client.execute uc }
|
29
32
|
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
# errors?
|
35
|
-
|
34
|
+
tl = Benelux.thread_timeline
|
35
|
+
tl.stats.group(:failed).merge.n == 0
|
36
36
|
end
|
37
37
|
|
38
38
|
|
@@ -44,30 +44,42 @@ module Stella::Engine
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def update_receive_response(client_id, usecase, uri, req, params, counter, container)
|
47
|
-
msg = '
|
47
|
+
msg = ' %-6s %-53s ' % [req.http_method, uri]
|
48
48
|
msg << container.status.to_s if Stella.loglev == 1
|
49
49
|
Stella.li msg
|
50
50
|
|
51
|
-
Stella.li2
|
52
|
-
|
53
|
-
Stella.li2 $/, " Request-Params:"
|
51
|
+
Stella.li2 $/, " Params:"
|
54
52
|
params.each do |pair|
|
55
53
|
Stella.li2 " %s: %s" % pair
|
56
54
|
end
|
57
55
|
|
58
|
-
Stella.li2 $/,
|
56
|
+
Stella.li2 $/, ' ' << container.response.request.header.send(:request_line)
|
57
|
+
|
59
58
|
container.response.request.header.all.each do |pair|
|
60
|
-
Stella.li2 "
|
59
|
+
Stella.li2 " %s: %s" % pair
|
61
60
|
end
|
62
61
|
|
63
|
-
|
62
|
+
if req.http_method == 'POST'
|
63
|
+
cont = container.response.request.body.content
|
64
|
+
if String === cont
|
65
|
+
Stella.li2 (' ' << cont.split($/).join("#{$/} "))
|
66
|
+
elsif HTTP::Message::Body::Parts === cont
|
67
|
+
cont.parts.each do |part|
|
68
|
+
if File === part
|
69
|
+
Stella.li2 "<#{part.path}>"
|
70
|
+
else
|
71
|
+
Stella.li2 part
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
64
76
|
|
65
|
-
|
77
|
+
resh = container.response.header
|
78
|
+
Stella.li2 $/, ' HTTP/%s %3d %s' % [resh.http_version, resh.status_code, resh.reason_phrase]
|
66
79
|
container.headers.all.each do |pair|
|
67
|
-
Stella.li2 "
|
80
|
+
Stella.li2 " %s: %s" % pair
|
68
81
|
end
|
69
|
-
Stella.
|
70
|
-
Stella.li3 container.body.empty? ? ' [empty]' : container.body
|
82
|
+
Stella.li4 container.body.empty? ? ' [empty]' : container.body
|
71
83
|
Stella.li2 $/
|
72
84
|
end
|
73
85
|
|
@@ -76,22 +88,25 @@ module Stella::Engine
|
|
76
88
|
|
77
89
|
def update_error_execute_response_handler(client_id, ex, req, container)
|
78
90
|
Stella.le ex.message
|
79
|
-
Stella.
|
91
|
+
Stella.ld ex.backtrace
|
80
92
|
end
|
81
93
|
|
82
94
|
def update_request_error(client_id, usecase, uri, req, params, ex)
|
83
95
|
desc = "#{usecase.desc} > #{req.desc}"
|
84
96
|
Stella.le ' Client-%s %-45s %s' % [client_id.short, desc, ex.message]
|
85
|
-
Stella.
|
97
|
+
Stella.ld ex.backtrace
|
86
98
|
end
|
87
99
|
|
88
100
|
def update_quit_usecase client_id, msg
|
89
|
-
Stella.
|
101
|
+
Stella.li " QUIT %s" % [msg]
|
90
102
|
end
|
91
103
|
|
104
|
+
def update_fail_request client_id, msg
|
105
|
+
Stella.li " FAILED %s" % [msg]
|
106
|
+
end
|
92
107
|
|
93
108
|
def update_repeat_request client_id, counter, total
|
94
|
-
Stella.
|
109
|
+
Stella.li3 " Client-%s REPEAT %d of %d" % [client_id.shorter, counter, total]
|
95
110
|
end
|
96
111
|
|
97
112
|
end
|
@@ -4,7 +4,7 @@ module Stella::Engine
|
|
4
4
|
extend Stella::Engine::Base
|
5
5
|
extend Stella::Engine::Load
|
6
6
|
extend self
|
7
|
-
|
7
|
+
ROTATE_TIMELINE = 15
|
8
8
|
def execute_test_plan(packages, reps=1,duration=0)
|
9
9
|
time_started = Time.now
|
10
10
|
|
@@ -46,13 +46,15 @@ module Stella::Engine
|
|
46
46
|
Thread.current[:real_uctime].tick
|
47
47
|
time_elapsed = (Time.now - time_started).to_i
|
48
48
|
|
49
|
-
if
|
50
|
-
Thread.current == @threads.first &&
|
51
|
-
(Time.now - prev_ptime).to_i >= 5
|
49
|
+
if (Time.now - prev_ptime).to_i >= ROTATE_TIMELINE
|
52
50
|
prev_ptime, ruct = Time.now, Thread.current[:real_uctime]
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
if Stella.loglev >= 2 && Thread.current == @threads.first
|
52
|
+
args = [time_elapsed.to_i, ruct.n, ruct.mean, ruct.sd]
|
53
|
+
Stella.li2 $/, "REAL UC TIME: %ds (reps: %d): %.4fs %.4f(SD)" % args
|
54
|
+
Stella.lflush
|
55
|
+
end
|
56
|
+
|
57
|
+
Thread.current.rotate_timeline
|
56
58
|
end
|
57
59
|
|
58
60
|
# If a duration was given, we make sure
|
@@ -69,6 +71,24 @@ module Stella::Engine
|
|
69
71
|
end
|
70
72
|
}
|
71
73
|
|
74
|
+
data_dumper = Thread.new do
|
75
|
+
prev_ptime = Time.now
|
76
|
+
loop do
|
77
|
+
break if Stella.abort?
|
78
|
+
break if @threads.select { |t| (!t.nil? && t.status) }.empty?
|
79
|
+
if (Time.now - prev_ptime).to_i >= (ROTATE_TIMELINE * 4)
|
80
|
+
Benelux.update_global_timeline
|
81
|
+
Stella.li $/, [:logger, (Time.now - prev_ptime).to_i, Benelux.timeline.size].inspect
|
82
|
+
prev_ptime = Time.now
|
83
|
+
##TODO: Dump to file
|
84
|
+
##Benelux.timeline.clear
|
85
|
+
end
|
86
|
+
sleep 5
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
data_dumper.join
|
91
|
+
|
72
92
|
repscalc = Benelux::Stats::Calculator.new
|
73
93
|
@threads.each { |t| t.join } # wait
|
74
94
|
@threads.each { |t| repscalc.sample(t[:real_reps]) }
|
@@ -36,7 +36,7 @@ module Stella::Engine
|
|
36
36
|
Stella.li "Generating requests #{msg}...", $/
|
37
37
|
Stella.lflush
|
38
38
|
|
39
|
-
|
39
|
+
bt = Benelux.timeline
|
40
40
|
|
41
41
|
begin
|
42
42
|
execute_test_plan packages, opts[:repetitions], opts[:duration]
|
@@ -49,8 +49,7 @@ module Stella::Engine
|
|
49
49
|
Stella.lflush
|
50
50
|
|
51
51
|
Benelux.update_global_timeline
|
52
|
-
|
53
|
-
bt = Benelux.timeline
|
52
|
+
|
54
53
|
tt = Benelux.thread_timeline
|
55
54
|
|
56
55
|
test_time = tt.stats.group(:execute_test_plan).mean
|
@@ -71,7 +70,7 @@ module Stella::Engine
|
|
71
70
|
Stella.li $/
|
72
71
|
end
|
73
72
|
|
74
|
-
|
73
|
+
bt.stats.group(:failed).merge.n == 0
|
75
74
|
end
|
76
75
|
|
77
76
|
protected
|
@@ -111,7 +110,9 @@ module Stella::Engine
|
|
111
110
|
Stella.ld "THREAD PACKAGE: #{usecase.desc} (#{pointer} + #{count})"
|
112
111
|
# Fill the thread_package with the contents of the block
|
113
112
|
packages.fill(pointer, count) do |index|
|
114
|
-
|
113
|
+
copts = {}
|
114
|
+
copts[:parse_templates] = false if opts[:'disable-templates']
|
115
|
+
client = Stella::Client.new opts[:hosts].first, index+1, copts
|
115
116
|
client.add_observer(self)
|
116
117
|
client.enable_nowait_mode if opts[:nowait]
|
117
118
|
Stella.li4 "Created client #{client.digest.short}"
|
@@ -132,6 +133,11 @@ module Stella::Engine
|
|
132
133
|
def generate_report(plan,test_time)
|
133
134
|
#Benelux.update_all_track_timelines
|
134
135
|
global_timeline = Benelux.timeline
|
136
|
+
global_stats = global_timeline.stats.group(:do_request).merge
|
137
|
+
if global_stats.n == 0
|
138
|
+
Stella.ld "No stats"
|
139
|
+
return
|
140
|
+
end
|
135
141
|
|
136
142
|
Stella.li $/, " %-72s ".att(:reverse) % ["#{plan.desc} (#{plan.digest_cache.shorter})"]
|
137
143
|
plan.usecases.uniq.each_with_index do |uc,i|
|
@@ -191,7 +197,7 @@ module Stella::Engine
|
|
191
197
|
end
|
192
198
|
|
193
199
|
Stella.li ' ' << " %-66s ".att(:reverse) % 'Total:'
|
194
|
-
|
200
|
+
|
195
201
|
failed = global_timeline.stats.group(:failed)
|
196
202
|
respgrp = global_timeline.stats.group(:execute_response_handler)
|
197
203
|
resst = respgrp.tag_values(:status)
|
@@ -200,8 +206,8 @@ module Stella::Engine
|
|
200
206
|
size = respgrp[:status => status].size
|
201
207
|
statusi << [status, size]
|
202
208
|
end
|
203
|
-
Stella.li ' %-30s %d' % ['Total requests',
|
204
|
-
success =
|
209
|
+
Stella.li ' %-30s %d' % ['Total requests', global_stats.n]
|
210
|
+
success = global_stats.n - failed.n
|
205
211
|
Stella.li ' %-29s %d (req/s: %.2f)' % [:success, success, success/test_time]
|
206
212
|
statusi.each do |pair|
|
207
213
|
Stella.li2 ' %-28s %s: %d' % ['', *pair]
|
@@ -229,7 +235,9 @@ module Stella::Engine
|
|
229
235
|
|
230
236
|
def update_receive_response(client_id, usecase, uri, req, params, counter, container)
|
231
237
|
desc = "#{usecase.desc} > #{req.desc}"
|
232
|
-
|
238
|
+
args = [client_id.shorter, container.status, req.http_method, uri, params.inspect]
|
239
|
+
Stella.li3 ' Client-%s %3d %-6s %s %s' % args
|
240
|
+
Stella.ld ' Client-%s %3d %s' % [client_id.shorter, container.status, container.body]
|
233
241
|
end
|
234
242
|
|
235
243
|
def update_execute_response_handler(client_id, req, container)
|
@@ -239,20 +247,23 @@ module Stella::Engine
|
|
239
247
|
desc = "#{container.usecase.desc} > #{req.desc}"
|
240
248
|
Stella.li $/ if Stella.loglev == 1
|
241
249
|
Stella.le ' Client-%s %-45s %s' % [client_id.shorter, desc, ex.message]
|
242
|
-
Stella.
|
250
|
+
Stella.li ex.backtrace
|
243
251
|
end
|
244
252
|
|
245
253
|
def update_request_error(client_id, usecase, uri, req, params, ex)
|
246
254
|
desc = "#{usecase.desc} > #{req.desc}"
|
247
255
|
Stella.li $/ if Stella.loglev == 1
|
248
256
|
Stella.le ' Client-%s %-45s %s' % [client_id.shorter, desc, ex.message]
|
249
|
-
Stella.
|
257
|
+
Stella.li ex.backtrace
|
250
258
|
end
|
251
259
|
|
252
260
|
def update_quit_usecase client_id, msg
|
253
261
|
Stella.li3 " Client-%s QUIT %s" % [client_id.shorter, msg]
|
254
262
|
end
|
255
263
|
|
264
|
+
def update_fail_request client_id, msg
|
265
|
+
Stella.li3 " Client-%s FAILED %s" % [client_id.shorter, msg]
|
266
|
+
end
|
256
267
|
|
257
268
|
def update_repeat_request client_id, counter, total
|
258
269
|
Stella.li3 " Client-%s REPEAT %d of %d" % [client_id.shorter, counter, total]
|
@@ -262,7 +273,6 @@ module Stella::Engine
|
|
262
273
|
blk.call
|
263
274
|
rescue => ex
|
264
275
|
Stella.le ' Error in Client-%s: %s' % [client_id.shorter, ex.message]
|
265
|
-
Stella.li3 ex.backtrace
|
266
276
|
end
|
267
277
|
|
268
278
|
Benelux.add_timer Stella::Engine::Load, :build_thread_package
|
data/lib/stella/testplan.rb
CHANGED
@@ -7,6 +7,7 @@ class Testplan
|
|
7
7
|
extend Attic
|
8
8
|
|
9
9
|
attic :base_path
|
10
|
+
attic :plan_path
|
10
11
|
|
11
12
|
attr_accessor :usecases
|
12
13
|
attr_accessor :desc
|
@@ -36,8 +37,9 @@ class Testplan
|
|
36
37
|
conf = File.read path
|
37
38
|
plan = Stella::Testplan.new
|
38
39
|
plan.base_path = File.dirname path
|
40
|
+
plan.plan_path = path
|
39
41
|
# eval so the DSL code can be executed in this namespace.
|
40
|
-
plan.instance_eval conf
|
42
|
+
plan.instance_eval conf, path
|
41
43
|
plan
|
42
44
|
end
|
43
45
|
|
@@ -58,6 +60,7 @@ class Testplan
|
|
58
60
|
|
59
61
|
# make sure all clients share identical test plans
|
60
62
|
def freeze
|
63
|
+
Stella.ld "FREEZE TESTPLAN: #{desc}"
|
61
64
|
@usecases.each { |uc| uc.freeze }
|
62
65
|
super
|
63
66
|
self
|
@@ -70,6 +73,7 @@ class Testplan
|
|
70
73
|
ratio, name = args[1], args[0] if args[0].is_a?(String)
|
71
74
|
uc = Stella::Testplan::Usecase.new
|
72
75
|
uc.base_path = self.base_path
|
76
|
+
uc.plan_path = self.plan_path
|
73
77
|
uc.instance_eval &blk
|
74
78
|
uc.ratio, uc.desc = (ratio || -1).to_f, name
|
75
79
|
@testplan_current_ratio += uc.ratio if uc.ratio > 0
|
@@ -97,6 +101,9 @@ class Testplan
|
|
97
101
|
desc = uc.desc || "Usecase ##{i+1}"
|
98
102
|
desc += " (#{dig}) "
|
99
103
|
str << (' ' << " %-61s %s%% ".att(:reverse).bright) % [desc, uc.ratio_pretty]
|
104
|
+
unless uc.http_auth.nil?
|
105
|
+
str << ' Auth: %s (%s/%s)' % uc.http_auth.values
|
106
|
+
end
|
100
107
|
requests = uc.requests.each do |r|
|
101
108
|
dig = long ? r.digest_cache : r.digest_cache.shorter
|
102
109
|
str << " %-62s".bright % ["#{r.desc} (#{dig})"]
|
@@ -21,10 +21,16 @@ class Testplan
|
|
21
21
|
include Gibbler::Complex
|
22
22
|
extend Attic
|
23
23
|
|
24
|
+
class Auth < Struct.new(:kind, :user, :pass)
|
25
|
+
include Gibbler::Complex
|
26
|
+
end
|
27
|
+
|
24
28
|
attic :base_path # we don't want gibbler to see this
|
29
|
+
attic :plan_path
|
25
30
|
|
26
31
|
attr_accessor :desc
|
27
32
|
attr_writer :ratio
|
33
|
+
attr_reader :http_auth
|
28
34
|
|
29
35
|
attr_accessor :requests
|
30
36
|
attr_accessor :resources
|
@@ -63,15 +69,17 @@ class Testplan
|
|
63
69
|
# directory is assumed to be the same directory containing the test plan).
|
64
70
|
def read(path)
|
65
71
|
path = File.join(base_path, path) if base_path
|
72
|
+
Stella.ld "READING FILE: #{path}"
|
66
73
|
File.read(path)
|
67
74
|
end
|
68
|
-
|
75
|
+
|
69
76
|
def list(path)
|
70
77
|
read(path).split $/
|
71
78
|
end
|
72
79
|
|
73
80
|
def csv(path)
|
74
81
|
path = File.join(base_path, path) if base_path
|
82
|
+
Stella.ld "READING CSV: #{path}"
|
75
83
|
CSV.read(path)
|
76
84
|
end
|
77
85
|
|
@@ -81,6 +89,11 @@ class Testplan
|
|
81
89
|
self
|
82
90
|
end
|
83
91
|
|
92
|
+
def auth(user, pass=nil, kind=:basic)
|
93
|
+
@http_auth ||= Auth.new
|
94
|
+
@http_auth.user, @http_auth.pass, @http_auth.kind = user, pass, kind
|
95
|
+
end
|
96
|
+
|
84
97
|
def add_request(meth, *args, &blk)
|
85
98
|
req = Stella::Data::HTTP::Request.new meth.to_s.upcase, args[0], &blk
|
86
99
|
req.desc = args[1] if args.size > 1 # Description is optional
|
data/lib/stella/version.rb
CHANGED
@@ -5,10 +5,10 @@ module Stella
|
|
5
5
|
unless defined?(MAJOR)
|
6
6
|
MAJOR = 0.freeze
|
7
7
|
MINOR = 7.freeze
|
8
|
-
TINY =
|
8
|
+
TINY = 2.freeze
|
9
9
|
PATCH = '001'.freeze
|
10
10
|
end
|
11
|
-
def self.to_s; [MAJOR, MINOR, TINY
|
11
|
+
def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
|
12
12
|
def self.to_f; self.to_s.to_f; end
|
13
13
|
def self.patch; PATCH; end
|
14
14
|
end
|