stella 0.7.3.002 → 0.7.4.001

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