stella 0.7.3.002 → 0.7.4.001

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  STELLA, CHANGES
2
2
 
3
+ #### 0.7.4 (2009-11-11) ###############################
4
+
5
+ * FIXED: Proper handling for timeout errors
6
+ * CHANGE: Log directory is now YYYYMMDD-HH-mm-ss-SHA1
7
+ * ADDED: Logging to .stella/log
8
+ * ADDED: Global variables via --var
9
+ * ADDED: Using naive CSV parsing via quickcsv (CSV lib is slooow for large files)
10
+ * ADDED: Testplan file cache (load a file only once)
11
+
3
12
 
4
13
  #### 0.7.3 (2009-10-30) ###############################
5
14
 
data/bin/stella CHANGED
@@ -13,8 +13,8 @@
13
13
  #
14
14
  # $ stella -h
15
15
  # $ stella verify -p plans/basic.rb http://test.example.com/
16
- # $ stella load -u 10 -t 60 http://test.example.com/
17
- # $ stella load -u 10 -r 40 -p plans/basic.rb http://test.example.com/
16
+ # $ stella generate -u 10 -t 60 http://test.example.com/
17
+ # $ stella generate -u 10 -r 40 -p plans/basic.rb http://test.example.com/
18
18
  #
19
19
  #--
20
20
 
@@ -38,6 +38,15 @@ class Stella::CLI::Definition
38
38
 
39
39
  #global :A, :apikey, String, "API Key"
40
40
  #global :S, :secret, String, "Secret Key"
41
+ global :o, :output, String, "Write output to the given file" do |v|
42
+ String.disable_color
43
+ Stella.log.output = v
44
+ end
45
+ global :var, String, 'Set an arbitrary variable (--var "name=v")' do |var|
46
+ n, v = *var.split('=')
47
+ raise "Bad variable format: #{var}" if n.nil? || !n.match(/[a-z]+/i)
48
+ eval "$#{n} = '#{v}'"
49
+ end
41
50
  global :p, :pause, Integer, "Seconds to pause before starting test"
42
51
  global :E, :engine, String, "Specify a load engine (experimental)"
43
52
  global :n, :nocolor, "Disable output colors" do
@@ -51,8 +60,13 @@ class Stella::CLI::Definition
51
60
  Stella.enable_debug
52
61
  end
53
62
  global :v, :verbose, "Increase verbosity of output (e.g. -v or -vv or -vvv)" do
54
- Stella.loglev += 1
63
+ Stella.stdout.lev += 1
55
64
  end
65
+ global :'disable-stats', "Disable stat collection"
66
+ global :'disable-logging', "Disable all logging" do
67
+ Stella::Logger.disable!
68
+ end
69
+ global :'disable-templates', "Disable template parsing"
56
70
  global :V, :version, "Display version number" do
57
71
  puts "Stella version: #{Stella::VERSION} (#{Stella::VERSION::PATCH})"
58
72
  exit 0
@@ -65,6 +79,10 @@ class Stella::CLI::Definition
65
79
  usage "stella example"
66
80
  command :example => Stella::CLI
67
81
 
82
+ about "View Stella configuration"
83
+ usage "stella config"
84
+ command :config => Stella::CLI
85
+
68
86
  about "Preview a test plan"
69
87
  usage "stella preview [-p path/2/testplan.rb] "
70
88
  option :c, :clients, Integer, "Maximum number of virtual clients (ignored)"
@@ -103,9 +121,7 @@ class Stella::CLI::Definition
103
121
  option :w, :wait, Float, "Wait time (in seconds) between client requests (ignored if testplan supplied)"
104
122
  option :p, :testplan, String, "Path to testplan"
105
123
  option :a, :arrival, Float, "Arrival rate (new clients per second)"
106
- option :'disable-templates', "Disable template parsing"
107
124
  command :generate => Stella::CLI
108
-
109
125
  about "Initialize Stella configuration"
110
126
  command :init do
111
127
  Stella::Config.init
@@ -135,11 +151,9 @@ class Stella::CLI::Definition
135
151
  end
136
152
 
137
153
  after do |obj|
138
- Stella.lflush
139
154
  @elapsed = Time.now - @start
140
- if Stella.loglev > 1 && @elapsed > 0.1
141
- puts
142
- puts "Elapsed: %.2f seconds" % @elapsed.to_f
155
+ if @elapsed > 0.1
156
+ Stella.stdout.puts 2, "#{$/}Elapsed: %.2f seconds" % @elapsed.to_f
143
157
  end
144
158
  code = obj.exit_code if obj.respond_to? :exit_code
145
159
  exit code ||= 0
@@ -158,11 +172,11 @@ rescue Drydock::UnknownCommand => ex
158
172
  STDERR.puts "Unknown command: %s" % ex.name
159
173
  rescue Stella::Error => ex
160
174
  STDERR.puts ex.message
161
- STDERR.puts ex.backtrace if Stella.loglev > 2 || Drydock.debug?
175
+ STDERR.puts ex.backtrace if Stella.stdout.lev > 2 || Stella.debug?
162
176
  rescue Interrupt
163
- puts "#{$/}Exiting... "
177
+ puts $/, "Exiting... "
164
178
  exit 1
165
179
  rescue => ex
166
180
  STDERR.puts "ERROR (#{ex.class.to_s}): #{ex.message}"
167
- STDERR.puts ex.backtrace if Stella.loglev > 2 || Drydock.debug?
181
+ STDERR.puts ex.backtrace if Stella.stdout.lev > 2 || Stella.debug?
168
182
  end
@@ -7,7 +7,6 @@
7
7
  desc "Maintain Your Cookies"
8
8
 
9
9
  usecase 65, "Simple search" do
10
-
11
10
  get "/", "Homepage"
12
11
 
13
12
  get "/search", "Search Results" do
@@ -156,7 +156,7 @@ usecase 65, "Simple search" do
156
156
  set :lid, listing['id'].match(/(\d+)/)[0]
157
157
  end
158
158
  response 404 do
159
- quit "No results"
159
+ fail "No results"
160
160
  end
161
161
  end
162
162
 
data/lib/stella.rb CHANGED
@@ -10,53 +10,62 @@ autoload :Drydock, 'drydock'
10
10
  autoload :URI, 'uri'
11
11
  autoload :OpenStruct, 'ostruct'
12
12
  autoload :Storable, 'storable'
13
- autoload :Gibbler, 'gibbler/aliases'
14
13
  autoload :Attic, 'attic'
15
14
  autoload :ERB, 'erb'
16
15
 
16
+ require 'gibbler/aliases' # important for run time digests and freezes
17
17
  require 'benelux'
18
18
 
19
+ module Stella
20
+ module VERSION
21
+ unless defined?(MAJOR)
22
+ MAJOR = 0.freeze
23
+ MINOR = 7.freeze
24
+ TINY = 4.freeze
25
+ PATCH = '001'.freeze
26
+ end
27
+ def self.to_s; [MAJOR, MINOR, TINY].join('.'); end
28
+ def self.to_f; self.to_s.to_f; end
29
+ def self.patch; PATCH; end
30
+ end
31
+ end
32
+
33
+
34
+ module Stella
35
+ class Error < RuntimeError
36
+ def initialize(obj=nil); @obj = obj; end
37
+ def message; @obj; end
38
+ end
39
+ class WackyRatio < Stella::Error; end
40
+ class WackyDuration < Stella::Error; end
41
+ class InvalidOption < Stella::Error; end
42
+ class NoHostDefined < Stella::Error; end
43
+ end
44
+
45
+
19
46
  module Stella
20
47
  extend self
21
48
 
22
- SLEEP_METRICS = {
23
- :create_thread => 0.001,
24
- :check_threads => 0.0005
25
- }.freeze unless defined?(SLEEP_METRICS)
26
-
49
+ require 'stella/logger'
50
+
51
+ START_TIME = Time.now.freeze
52
+
53
+ @globals = {}
27
54
  @sysinfo = nil
28
- @logger = Drydock::Screen
29
- @loglev = 1
30
55
  @debug = false
31
56
  @abort = false
32
-
57
+ @quiet = false
58
+ @log = Stella::SyncLogger.new
59
+ @stdout = Stella::Logger.new STDOUT
60
+
33
61
  class << self
34
- attr_accessor :loglev, :logger
35
- end
36
-
37
- def sleep(metric)
38
- unless SLEEP_METRICS.has_key? metric
39
- raise "unknown sleep metric: #{metric}"
40
- end
41
- Kernel.sleep SLEEP_METRICS[metric]
62
+ attr_accessor :log, :stdout
42
63
  end
43
-
44
- # Puts +msg+ to +@logger+
45
- def lflush; @logger.flush if @logger.respond_to? :flush; end
46
- def li(*msg); msg.each { |m| @logger.puts m } if !quiet? end
47
- def li1(*msg); li *msg if @loglev >= 1 end
48
- def li2(*msg); li *msg if @loglev >= 2 end
49
- def li3(*msg); li *msg if @loglev >= 3 end
50
- def li4(*msg); li *msg if @loglev >= 4 end
51
-
52
- # Puts +msg+ to +@logger+ with "ERROR: " prepended
53
- def le(*msg); @logger.puts " " << msg.join("#{$/} ").color(:red); end
54
- # Puts +msg+ to +@logger+ if +Rudy.debug?+ returns true
64
+
65
+ def le(*msg); stdout.info " " << msg.join("#{$/} ").color(:red); end
55
66
  def ld(*msg)
56
- if debug?
57
- @logger.puts "D(#{Thread.current.object_id}): " << msg.join("#{$/}D: ")
58
- Stella.lflush
59
- end
67
+ return unless Stella.debug?
68
+ Stella.stdout.info "D(#{Thread.current.object_id}): " << msg.join("#{$/}D: ")
60
69
  end
61
70
 
62
71
  def sysinfo
@@ -64,10 +73,6 @@ module Stella
64
73
  @sysinfo
65
74
  end
66
75
 
67
- def quiet?() @loglev == 0 end
68
- def enable_quiet() @loglev = 0 end
69
- def disable_quiet() @loglev = 1 end
70
-
71
76
  def debug?() @debug == true end
72
77
  def enable_debug() @debug = true end
73
78
  def disable_debug() @debug = false end
@@ -75,16 +80,24 @@ module Stella
75
80
  def abort?() @abort == true end
76
81
  def abort!() @abort = true end
77
82
 
83
+ def quiet?() @quiet == true end
84
+ def enable_quiet() @quiet = true end
85
+ def disable_quiet() @quiet = false end
86
+
87
+ def add_global(n,v)
88
+ Stella.ld "SETGLOBAL: #{n}=#{v}"
89
+ @globals[n.strip] = v.strip
90
+ end
91
+
78
92
  def rescue(&blk)
79
93
  blk.call
80
94
  rescue => ex
81
- Stella.le "ERROR: #{ex.message}"
82
- Stella.li3 ex.backtrace
95
+ Stella.stdout.info "ERROR: #{ex.message}"
96
+ Stella.stdout.info ex.backtrace
83
97
  end
84
98
 
85
- require 'stella/exceptions'
99
+ require 'stella/common'
86
100
 
87
- autoload :VERSION, 'stella/version'
88
101
  autoload :Utils, 'stella/utils'
89
102
  autoload :Config, 'stella/config'
90
103
  autoload :Data, 'stella/data'
@@ -92,9 +105,12 @@ module Stella
92
105
  autoload :Engine, 'stella/engine'
93
106
  autoload :Client, 'stella/client'
94
107
 
95
- require 'stella/mixins'
96
108
  end
97
109
 
110
+ Stella.stdout.lev = Stella.quiet? ? 0 : 1
111
+ Stella.stdout.autoflush!
112
+
113
+
98
114
 
99
115
 
100
116
 
data/lib/stella/cli.rb CHANGED
@@ -7,6 +7,10 @@ class Stella::CLI < Drydock::Command
7
7
  @exit_code = 0
8
8
  end
9
9
 
10
+ def config
11
+ puts @conf.to_yaml
12
+ end
13
+
10
14
  def verify_valid?
11
15
  create_testplan
12
16
  end
@@ -26,15 +30,19 @@ class Stella::CLI < Drydock::Command
26
30
  def generate
27
31
  opts = {}
28
32
  opts[:hosts] = @hosts
29
- [:nowait, :clients, :repetitions, :duration, :arrival, :'disable-templates'].each do |opt|
33
+ [:nowait, :clients, :repetitions, :duration, :arrival].each do |opt|
30
34
  opts[opt] = @option.send(opt) unless @option.send(opt).nil?
31
35
  end
32
-
36
+ [:'disable-templates', :'disable-stats'].each do |opt|
37
+ opts[opt] = @global.send(opt) unless @global.send(opt).nil?
38
+ end
33
39
  case @global.engine
34
40
  when "package"
35
41
  ret = Stella::Engine::LoadPackage.run @testplan, opts
36
42
  when "create"
37
43
  ret = Stella::Engine::LoadCreate.run @testplan, opts
44
+ when "redis"
45
+ ret = Stella::Engine::LoadRedis.run @testplan, opts
38
46
  else
39
47
  ret = Stella::Engine::LoadQueue.run @testplan, opts
40
48
  end
@@ -68,7 +76,7 @@ class Stella::CLI < Drydock::Command
68
76
 
69
77
  def preview
70
78
  create_testplan
71
- Stella.li @testplan.pretty(Stella.loglev > 1)
79
+ Stella.stdout.info @testplan.pretty(Stella.stdout.lev > 1)
72
80
  end
73
81
 
74
82
  private
@@ -89,7 +97,7 @@ class Stella::CLI < Drydock::Command
89
97
  end
90
98
  @testplan.check! # raise errors, update usecase ratios
91
99
  @testplan.freeze # cascades through usecases and requests
92
- Stella.li2 " #{@option.testplan || @testplan.desc} (#{@testplan.digest})"
100
+ Stella.stdout.info2 " #{@option.testplan || @testplan.desc} (#{@testplan.digest})"
93
101
  true
94
102
  end
95
103
 
data/lib/stella/client.rb CHANGED
@@ -5,7 +5,7 @@ Stella::Utils.require_vendor "httpclient", '2.1.5.2'
5
5
 
6
6
  module Stella
7
7
  class Client
8
- require 'stella/client/modifiers'
8
+
9
9
  require 'stella/client/container'
10
10
 
11
11
  include Gibbler::Complex
@@ -58,18 +58,19 @@ module Stella
58
58
  user, pass = http_auth.user, http_auth.pass
59
59
  user = container.instance_eval &user if Proc === user
60
60
  pass = container.instance_eval &pass if Proc === pass
61
- Stella.li3 " AUTH (#{http_auth.kind}) #{domain} (#{user}/#{pass})"
61
+ update(:authenticate, usecase, req, http_auth.kind, domain, user, pass)
62
62
  http_client.set_auth(domain, user, pass)
63
63
  end
64
64
 
65
65
  raise NoHostDefined, req.uri if uri.host.nil? || uri.host.empty?
66
- stella_id = [Time.now, self.digest_cache, req.digest_cache, params, headers, counter].gibbler
66
+ stella_id = [Time.now.to_f, self.digest_cache, req.digest_cache, params, headers, counter].gibbler
67
67
 
68
68
  Benelux.add_thread_tags :request => req.digest_cache
69
69
  Benelux.add_thread_tags :retry => counter
70
70
  Benelux.add_thread_tags :stella_id => stella_id
71
71
 
72
- params['__stella'] = headers['X-Stella-ID']= stella_id[0..10]
72
+ container.unique_id = stella_id
73
+ params['__stella'] = headers['X-Stella-ID'] = container.unique_id[0..10]
73
74
 
74
75
  meth = req.http_method.to_s.downcase
75
76
  Stella.ld "#{req.http_method}: " << "#{req.uri} " << params.inspect
@@ -77,6 +78,7 @@ module Stella
77
78
  ret, asset_duration = nil, 0
78
79
  begin
79
80
  send_request http_client, usecase, meth, uri, req, params, headers, container, counter
81
+ update(:receive_response, usecase, uri, req, params, headers, counter, container)
80
82
  Benelux.add_thread_tags :status => container.status
81
83
  res = container.response
82
84
  [
@@ -93,35 +95,35 @@ module Stella
93
95
  container.assets.each do |uri|
94
96
  Benelux.add_thread_tags :asset => uri
95
97
  a = http_client.get uri
96
- Stella.li3 " FETCH ASSET: #{uri} #{a.status}"
98
+ Stella.stdout.info3 " FETCH ASSET: #{uri} #{a.status}"
97
99
  Benelux.remove_thread_tags :asset
98
100
  end
99
101
  asset_duration = Time.now - asset_start
100
-
102
+ rescue HTTPClient::ConnectTimeoutError => ex
103
+ update(:request_timeout, usecase, uri, req, params, headers, counter, container)
101
104
  rescue => ex
102
- Benelux.thread_timeline.add_count :failed, 1
103
- update(:request_error, usecase, uri, req, params, ex)
105
+ #p "111111111111111111111111#{ex.class}: #{ex.message}"
106
+ update(:request_unhandled_exception, usecase, uri, req, params, ex)
104
107
  Benelux.remove_thread_tags :status, :retry, :request, :stella_id
105
108
  next
106
109
  end
107
110
 
108
- Stella.lflush
109
-
110
111
  run_sleeper(req.wait, asset_duration) if req.wait != 0 && !nowait?
111
112
 
112
113
  # TODO: consider throw/catch
113
114
  case ret.class.to_s
114
115
  when "Stella::Client::Repeat"
116
+ update(:request_repeat, counter, ret.times+1, uri, container)
115
117
  Benelux.remove_thread_tags :status
116
- update(:repeat_request, counter, ret.times+1)
117
118
  redo if counter <= ret.times
118
119
  when "Stella::Client::Quit"
120
+ update(:usecase_quit, ret.message, uri, container)
119
121
  Benelux.remove_thread_tags :status
120
- update(:quit_usecase, ret.message)
121
122
  break
122
123
  when "Stella::Client::Fail"
123
- Benelux.thread_timeline.add_count :failed, 1
124
- update(:fail_request, ret.message)
124
+ update(:request_fail, ret.message, uri, container)
125
+ when "Stella::Client::Error"
126
+ update(:request_error, ret.message, uri, container)
125
127
  end
126
128
 
127
129
  Benelux.remove_thread_tags :status
@@ -137,9 +139,9 @@ module Stella
137
139
  def nowait?; @nowait == true; end
138
140
 
139
141
  private
142
+ # We use a method so we can time it with Benelux
140
143
  def send_request(http_client, usecase, meth, uri, req, params, headers, container, counter)
141
144
  container.response = http_client.send(meth, uri, params, headers) # booya!
142
- update(:receive_response, usecase, uri, req, params, counter, container)
143
145
  end
144
146
 
145
147
  def update(kind, *args)
@@ -168,7 +170,7 @@ module Stella
168
170
  }
169
171
  http_client = HTTPClient.new opts
170
172
  http_client.set_proxy_auth(@proxy.user, @proxy.pass) if @proxy.user
171
- http_client.debug_dev = STDOUT if Stella.debug? && Stella.loglev > 3
173
+ http_client.debug_dev = STDOUT if Stella.debug? && Stella.stdout.lev > 3
172
174
  http_client.protocol_version = "HTTP/1.1"
173
175
  http_client.ssl_config.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
174
176
  http_client
@@ -268,7 +270,9 @@ module Stella
268
270
  ret = nil
269
271
  handler = find_response_handler container, req
270
272
  if handler.nil?
271
- Benelux.thread_timeline.add_count :failed, 1 if container.status >= 400
273
+ if container.status >= 400
274
+ update(:request_fail, "No handler", req.uri, container)
275
+ end
272
276
  return
273
277
  end
274
278
  begin
@@ -293,4 +297,25 @@ module Stella
293
297
  end
294
298
 
295
299
  end
296
- end
300
+ end
301
+
302
+
303
+ class Stella::Client
304
+
305
+ class ResponseModifier
306
+ attr_accessor :message
307
+ def initialize(msg=nil)
308
+ @message = msg
309
+ end
310
+ end
311
+ class Repeat < ResponseModifier;
312
+ attr_accessor :times
313
+ def initialize(times)
314
+ @times = times
315
+ end
316
+ end
317
+ class Quit < ResponseModifier; end
318
+ class Fail < Quit; end
319
+ class Error < Quit; end
320
+
321
+ end