Class Stella::Adapter::Siege
In: lib/stella/adapter/siege.rb
Parent: Stella::Adapter::Base

SIEGE Usage: siege [options]

       siege [options] URL
       siege -g URL

Options:

  -V, --version           VERSION, prints version number to screen.
  -h, --help              HELP, prints this section.
  -C, --config            CONFIGURATION, show the current configuration.
  -v, --verbose           VERBOSE, prints notification to screen.
  -g, --get               GET, pull down headers from the server and display HTTP
                          transaction. Great for web application debugging.
  -c, --concurrent=NUM    CONCURRENT users, default is 10
  -u, --url="URL"         Deprecated. Set URL as the last argument.
  -i, --internet          INTERNET user simulation, hits the URLs randomly.
  -b, --benchmark         BENCHMARK, signifies no delay for time testing.
  -t, --time=NUMm         TIME based testing where "m" is the modifier S, M, or H
                          no space between NUM and "m", ex: --time=1H, one hour test.
  -r, --reps=NUM          REPS, number of times to run the test, default is 25
  -f, --file=FILE         FILE, change the configuration file to file.
  -R, --rc=FILE           RC, change the siegerc file to file.  Overrides
                          the SIEGERC environmental variable.
  -l, --log               LOG, logs the transaction to PREFIX/var/siege.log
  -m, --mark="text"       MARK, mark the log file with a string separator.
  -d, --delay=NUM         Time DELAY, random delay between 1 and num designed
                          to simulate human activity. Default value is 3
  -H, --header="text"     Add a header to request (can be many)
  -A, --user-agent="text" Sets User-Agent in request

Methods

Attributes

benchmark  [RW] 
concurrent  [RW] 
config  [RW] 
delay  [RW] 
file  [RW] 
get  [RW] 
header  [RW] 
help  [RW] 
internet  [RW] 
log  [RW] 
mark  [RW] 
rc  [RW] 
reps  [RW] 
time  [RW] 
user_agent  [RW] 
verbose  [RW] 
version  [RW] 

Public Class methods

[Source]

    # File lib/stella/adapter/siege.rb, line 39
39:       def initialize(options={}, arguments=[])
40:         super(options, arguments)
41:         @name = 'siege'
42:         @reps = 1
43:         @concurrent = 1
44:         @rc = File.join(ENV['HOME'], '.siegerc')
45:         @private_variables = ['private_variables', 'name', 'arguments', 'load_factor', 'working_directory', 'orig_logfile']
46:         @load_factor = 1
47:       end

Public Instance methods

After calling run

[Source]

     # File lib/stella/adapter/siege.rb, line 110
110:       def after
111: 
112:         update_orig_logfile if @orig_logfile
113: 
114:         save_stats
115:       end

Before calling run

[Source]

    # File lib/stella/adapter/siege.rb, line 75
75:       def before
76: 
77:         # Keep a copy of the configuration file. 
78:         copy_siegerc
79: 
80:         # Keep a copy of the URLs file.
81:         copy_urls_file if @file
82:         
83:         # TODO: Print message about neither --benchmark or --internet
84:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 85
 85:       def command
 86:         raise CommandNotReady.new(self.class.to_s) unless ready?
 87: 
 88:         command = "#{@name} "
 89: 
 90:         instance_variables.each do |name|
 91:           canon = name.tr('@', '')        # instance_variables returns '@name'
 92:           next if @private_variables.member?(canon)
 93: 
 94:           # It's important that we take the value from the getter method
 95:           # because it applies the load factor. 
 96:           value = self.send(canon)
 97:           if (value.is_a? Array)
 98:             value.each { |el| command << "--#{cannon.tr('_', '-')} '#{el}' " }
 99:           else
100:             command << "--#{canon.tr('_', '-')} '#{value}' "
101:           end
102: 
103:         end
104: 
105:         command << (@arguments.map { |uri| "'#{uri}'" }).join(' ') unless @arguments.empty?
106:         command
107:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 170
170:       def concurrent
171:         (@concurrent * @load_factor).to_i
172:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 173
173:       def concurrent_f
174:         (@concurrent * @load_factor).to_f
175:       end

We want to keep a copy of the configuration file and also modify it a little bit to make sure we get all the mad info from siege

[Source]

     # File lib/stella/adapter/siege.rb, line 200
200:       def copy_siegerc
201: 
202:         # Read in the siegerc file so we can manipulate it
203:         siegerc_str = FileUtil.read_file(File.expand_path(@rc))
204: 
205:         siegerc_vars = {
206:           :verbose => [false, true],    # We want to maximize the data output by siege
207:           :logging => [false, true], 
208:           :csv => [false, true]
209:         }
210: 
211:         #if (@agent)
212:         #  siegerc_vars['user-agent'] = ['.*', 'dogs2']
213:         #end
214: 
215:         # We'll set the variables in the siegerc file
216:         siegerc_vars.each_pair do |var,value|
217:           siegerc_str.gsub!(/#{var}\s*=\s*#{value[0]}/, "#{var} = #{value[1]}")  # make true
218:           siegerc_str.gsub!(/^\#+\s*#{var}/, "#{var}")              # remove comment
219:         end
220: 
221:         # Look for the enabled logile path
222:         # We will use this later to update it from the last line in our copy
223:         siegerc_str =~ /^\s*logfile\s*=\s*(.+?)$/
224:         @orig_logfile = $1 || nil
225: 
226:         # Replace all environment variables with literal values
227:         @orig_logfile.gsub!(/\$\{#{$1}\}/, ENV[$1]) while (@orig_logfile =~ /\$\{(.+?)\}/ && ENV.has_key?($1))
228: 
229:         @orig_logfile = File.expand_path(@orig_logfile) if @orig_logfile
230:         
231: 
232:         siegerc_str.gsub!(/^\#*\s*logfile\s*=\s*.*?$/, "logfile = " + log_file)
233:         
234:         FileUtil.write_file(rc_file, siegerc_str, true)
235:         @rc = rc_file
236:       end

We want to keep a copy of the URLs file too

[Source]

     # File lib/stella/adapter/siege.rb, line 239
239:       def copy_urls_file
240:         if @file
241:           File.copy(File.expand_path(@file), uris_file) 
242:           @file = uris_file
243:         end
244:       end

loadtest

True or false: is the call to siege a load test? If it‘s a call to help or version or to display the config this with return false. It‘s no reason for someone to make this call through Stella but it‘s here for goodness sake.

[Source]

    # File lib/stella/adapter/siege.rb, line 65
65:       def loadtest?
66:         !@arguments.empty?  # The argument is a URI
67:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 255
255:       def log_file
256:         File.join(@working_directory, "siege.log")
257:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 118
118:       def process_options(arguments)
119:         options = OpenStruct.new
120:         opts = OptionParser.new 
121:         opts.on('-V', '--version') do |v| options.version = v end
122:         opts.on('-h', '--help') do |v| options.help = v end
123:         opts.on('-C', '--config') do |v| options.config = v end
124:         opts.on('-v', '--verbose') do |v| options.verbose = v end
125:         opts.on('-g', '--get') do |v| options.get = v end
126:         opts.on('-l', '--log') do |v| options.log = v end
127:         opts.on('-m S', '--mark=S', String) do |v| options.mark = v end
128:         opts.on('-d N', '--delay=N', Float) do |v| options.delay = v end
129:         opts.on('-H S', '--header=S', String) do |v| options.header ||= []; options.header << v end
130:           
131:         opts.on('-r N', '--reps=N', Integer) do |v| options.reps = v.to_i end
132:         opts.on('-c N', '--concurrent=N', Integer) do |v| options.concurrent = v.to_i end
133:         opts.on('-R S', '--rc=S', String) do |v| options.rc = v end
134:         opts.on('-f S', '--file=S', String) do |v| options.file = v end
135:         opts.on('-t S', '--time=S', String) do |v| options.time = v end
136:         opts.on('-b', '--benchmark') do |v| options.benchmark = true;  end
137:         opts.on('-i', '--internet') do |v| options.internet = true; end
138:         opts.on('-A S', '--user-agent=S', String) do |v| options.user_agent = v end
139: 
140:         raise "You cannot select both --internet and --benchmark" if options.internet && options.benchmark
141: 
142:         # parse! removes the options it finds.
143:         # It also fails when it finds unknown switches (i.e. -X)
144:         # Which should leave only the remaining arguments (URIs in this case)
145:         opts.parse!(arguments)
146:         options
147:       rescue OptionParser::InvalidOption => ex
148:         # We want to replace this text so we grab just the name of the argument
149:         badarg = ex.message.gsub('invalid option: ', '')
150:         raise InvalidArgument.new(badarg)
151:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 251
251:       def rc_file
252:         File.join(@working_directory, "siegerc")
253:       end

[Source]

    # File lib/stella/adapter/siege.rb, line 69
69:       def ready?
70:         @name && !instance_variables.empty? 
71:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 176
176:       def reps
177:         @reps
178:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 160
160:       def requests
161:         (@reps * concurrent_f).to_i
162:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 163
163:       def requests=(v)
164:         @reps = (v / concurrent_f).to_i
165:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 263
263:       def stats
264:         return unless stats_file
265:         raw = {}
266:         stats_file.each_line { |l|
267:           l.chomp!
268:           nvpair = l.split(':')
269:           next unless nvpair && nvpair.size == 2
270:           n = nvpair[0].strip.tr(' ', '_').downcase[/\w+/]
271:           v = nvpair[1].strip[/[\.\d]+/]
272:           raw[n.to_sym] = v.to_f
273:         }
274: 
275:         stats = Stella::Test::RunSummary.new
276: 
277:         stats.vusers = raw[:concurrency]
278:         stats.data_transferred = raw[:data_transferred]
279: 
280: 
281:         stats.elapsed_time = raw[:elapsed_time]
282:         stats.response_time = raw[:response_time]
283: 
284:         #stats.shortest_transaction = raw[:shortest_transaction]
285:         #stats.longest_transaction = raw[:longest_transaction]
286: 
287:         stats.transactions = raw[:transactions].to_i
288:         stats.transaction_rate = raw[:transaction_rate]
289:         stats.failed = raw[:failed_transactions].to_i
290:         stats.successful = raw[:successful_transactions].to_i
291:         #stats.raw = raw if @global_options.debug
292:         stats
293:       end

Siege writes the summary to STDERR

[Source]

     # File lib/stella/adapter/siege.rb, line 247
247:       def stats_file
248:         File.new(stderr_path)
249:       end

Take the last line of the siege.log file and write it to the log file specified by the user. We don‘t this so running with Stella is identical to running it standalone

[Source]

     # File lib/stella/adapter/siege.rb, line 184
184:       def update_orig_logfile
185: 
186:         return unless (@orig_logfile)
187:         log_str = FileUtil.read_file_to_array(log_file) || ''
188:         return if log_str.empty?
189: 
190:         if File.exists?(@orig_logfile)
191:           FileUtil.append_file(@orig_logfile, log_str[-1], true)
192:         else  
193:           FileUtil.write_file(@orig_logfile, log_str.join(''), true)
194:         end
195: 
196:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 259
259:       def uris_file
260:         File.join(@working_directory, File.basename(@file))
261:       end

[Source]

    # File lib/stella/adapter/siege.rb, line 50
50:       def version
51:         vsn = 0
52:         text = ""
53:         Open3.popen3("#{@name} --version") do |stdin, stdout, stderr| 
54:           text = stderr.readlines.join
55:           text.scan(/SIEGE (\d+?\.\d+)/) { |v| vsn = v[0] }
56:         end
57:         vsn
58:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 166
166:       def vuser_requests
167:         @reps
168:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 154
154:       def vusers
155:         concurrent || 0 
156:       end

[Source]

     # File lib/stella/adapter/siege.rb, line 157
157:       def vusers=(v)
158:         @concurrent = v
159:       end

[Validate]