solutious-stella 0.5.5
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 +36 -0
- data/README.textile +162 -0
- data/Rakefile +88 -0
- data/bin/stella +12 -0
- data/bin/stella.bat +12 -0
- data/lib/daemonize.rb +56 -0
- data/lib/pcaplet.rb +180 -0
- data/lib/stella.rb +101 -0
- data/lib/stella/adapter/ab.rb +337 -0
- data/lib/stella/adapter/base.rb +106 -0
- data/lib/stella/adapter/httperf.rb +305 -0
- data/lib/stella/adapter/pcap_watcher.rb +221 -0
- data/lib/stella/adapter/proxy_watcher.rb +76 -0
- data/lib/stella/adapter/siege.rb +341 -0
- data/lib/stella/cli.rb +258 -0
- data/lib/stella/cli/agents.rb +73 -0
- data/lib/stella/cli/base.rb +55 -0
- data/lib/stella/cli/language.rb +18 -0
- data/lib/stella/cli/localtest.rb +78 -0
- data/lib/stella/cli/sysinfo.rb +16 -0
- data/lib/stella/cli/watch.rb +278 -0
- data/lib/stella/command/base.rb +40 -0
- data/lib/stella/command/localtest.rb +358 -0
- data/lib/stella/data/domain.rb +82 -0
- data/lib/stella/data/http.rb +131 -0
- data/lib/stella/logger.rb +84 -0
- data/lib/stella/response.rb +85 -0
- data/lib/stella/storable.rb +201 -0
- data/lib/stella/support.rb +276 -0
- data/lib/stella/sysinfo.rb +257 -0
- data/lib/stella/test/definition.rb +79 -0
- data/lib/stella/test/run/summary.rb +70 -0
- data/lib/stella/test/stats.rb +114 -0
- data/lib/stella/text.rb +64 -0
- data/lib/stella/text/resource.rb +38 -0
- data/lib/utils/crypto-key.rb +84 -0
- data/lib/utils/domainutil.rb +47 -0
- data/lib/utils/escape.rb +302 -0
- data/lib/utils/fileutil.rb +78 -0
- data/lib/utils/httputil.rb +266 -0
- data/lib/utils/mathutil.rb +15 -0
- data/lib/utils/stats.rb +88 -0
- data/lib/utils/textgraph.rb +267 -0
- data/lib/utils/timerutil.rb +58 -0
- data/lib/win32/Console.rb +970 -0
- data/lib/win32/Console/ANSI.rb +305 -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 +80 -0
- data/support/text/nl.yaml +7 -0
- data/support/useragents.txt +75 -0
- data/tests/01-util_test.rb +0 -0
- data/tests/02-stella-util_test.rb +42 -0
- data/tests/10-stella_test.rb +104 -0
- data/tests/11-stella-storable_test.rb +68 -0
- data/tests/60-stella-command_test.rb +248 -0
- data/tests/80-stella-cli_test.rb +45 -0
- data/tests/spec-helper.rb +31 -0
- metadata +165 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Stella::Command
|
4
|
+
class Base
|
5
|
+
|
6
|
+
|
7
|
+
# TODO: See EC2::Platform for example to improve/generalize platform
|
8
|
+
# discovery. We'll need this for monitoring.
|
9
|
+
IMPLEMENTATIONS = [
|
10
|
+
[/darwin/i, :unix, :macosx ]
|
11
|
+
]
|
12
|
+
ARCHITECTURES = [
|
13
|
+
[/(i\d86)/i, :i386 ]
|
14
|
+
]
|
15
|
+
|
16
|
+
# When using Stella::CLI this will contain the string used to call this command
|
17
|
+
# i.e. ab, siege, help, etc...
|
18
|
+
attr_accessor :shortname
|
19
|
+
|
20
|
+
|
21
|
+
def initialize()
|
22
|
+
|
23
|
+
#agent = find_agent(*expand_str(v))
|
24
|
+
#@logger.info(:cli_print_agent, agent) if @options.verbose >= 1
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def run_sleeper(duration)
|
29
|
+
remainder = duration % 1
|
30
|
+
duration.to_i.times {
|
31
|
+
Stella::LOGGER.info_print('.') unless @quiet
|
32
|
+
sleep 1
|
33
|
+
}
|
34
|
+
sleep remainder if remainder > 0
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,358 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Stella
|
4
|
+
class LocalTest < Stella::Command::Base
|
5
|
+
|
6
|
+
# A container for the test parameters
|
7
|
+
attr_accessor :testdef
|
8
|
+
# The load tool adapter
|
9
|
+
attr_accessor :adapter
|
10
|
+
|
11
|
+
attr_accessor :test_path
|
12
|
+
|
13
|
+
attr_accessor :quiet
|
14
|
+
attr_accessor :guid
|
15
|
+
attr_accessor :verbose
|
16
|
+
attr_accessor :format
|
17
|
+
|
18
|
+
# list of all filesystem paths for each run in a single test
|
19
|
+
attr_reader :test_runpaths
|
20
|
+
# same as above, expect for all tests
|
21
|
+
attr_reader :all_runpaths
|
22
|
+
# list of all hostname:port in the test
|
23
|
+
attr_reader :hosts
|
24
|
+
# list of all /paths in the test
|
25
|
+
attr_reader :paths
|
26
|
+
|
27
|
+
attr_accessor :working_directory
|
28
|
+
attr_reader :available_agents
|
29
|
+
attr_reader :test_stats
|
30
|
+
attr_reader :rampup_test_stats
|
31
|
+
|
32
|
+
def initialize(testdef=nil, adapter=nil)
|
33
|
+
@testdef = testdef if testdef
|
34
|
+
@adapter = adapter if adapter
|
35
|
+
|
36
|
+
# Disabled until we resolve JRuby on OSX issue (won't load openssl)
|
37
|
+
#@guid = Crypto.sign(rand.to_s, rand.to_s)
|
38
|
+
|
39
|
+
@test_runpaths = []
|
40
|
+
@all_runpaths = []
|
41
|
+
@hosts = []
|
42
|
+
@paths = []
|
43
|
+
@format = 'yaml'
|
44
|
+
@agents = []
|
45
|
+
@verbose = 0
|
46
|
+
|
47
|
+
ua_path = File.join(STELLA_HOME, 'support', 'useragents.txt')
|
48
|
+
Stella::LOGGER.debug("LOADING #{ua_path}")
|
49
|
+
|
50
|
+
@available_agents = Stella::Util.process_useragents(ua_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
def run
|
56
|
+
|
57
|
+
|
58
|
+
raise UnavailableAdapter.new(@adapter.name) unless @adapter.available?
|
59
|
+
|
60
|
+
# If the adapter isn't being called for a loadtest, we don't have anything to do.
|
61
|
+
unless @adapter.loadtest?
|
62
|
+
system(@adapter.command)
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
@agents = Stella::Util.find_agents(@available_agents, @testdef.agents)
|
67
|
+
|
68
|
+
@test_path = _generate_test_path
|
69
|
+
|
70
|
+
prepare_test(@test_path)
|
71
|
+
|
72
|
+
threshold = (@testdef.rampup) ? @testdef.rampup.ceiling : @adapter.vusers
|
73
|
+
|
74
|
+
runnum = "00"
|
75
|
+
while(@adapter.vusers <= threshold) do
|
76
|
+
|
77
|
+
# Make sure the load factor is set to 1. If there was a warmup,
|
78
|
+
# then this value will be less than 1.
|
79
|
+
testrun = maker_of_testruns(1)
|
80
|
+
|
81
|
+
# We empty test_runpaths so we can keep track of the runpaths for each
|
82
|
+
# level of virtual users. This is useful during a rampup test so we can
|
83
|
+
# collect the stats for the repetitions at each virtual user level.
|
84
|
+
@test_runpaths = []
|
85
|
+
|
86
|
+
# Execute each test run in turn. All of the steps are the same for each
|
87
|
+
# run. This is important because the purpose of the test runs is to
|
88
|
+
# create a statistical certainty of performance.
|
89
|
+
@testdef.repetitions.times do
|
90
|
+
|
91
|
+
# This value is used to create the run directory and show which run we're on
|
92
|
+
runnum.succ!
|
93
|
+
|
94
|
+
# Generate the filesystem path to store the run data.
|
95
|
+
runpath = File.join(test_path, "run#{runnum}")
|
96
|
+
|
97
|
+
# Keep track of every run path. We use this in postpare to
|
98
|
+
# do some stuff after all the tests have run
|
99
|
+
@all_runpaths << runpath
|
100
|
+
|
101
|
+
# test_runpaths will be identical to all_runpaths except when there is a
|
102
|
+
# rampup. In that case, test_runpaths will contain the runpaths for all
|
103
|
+
# repetitions of each level of virtual users.
|
104
|
+
@test_runpaths << runpath
|
105
|
+
|
106
|
+
testrun.call("Run #{runnum}", runpath)
|
107
|
+
|
108
|
+
# Only sleep if requested and there is more than 1 test run
|
109
|
+
if @testdef.sleep && @testdef.sleep.to_f > 0 && @testdef.repetitions > 1
|
110
|
+
run_sleeper(@testdef.sleep)
|
111
|
+
end
|
112
|
+
Stella::LOGGER.info('') unless @quiet # We want the newline
|
113
|
+
end
|
114
|
+
|
115
|
+
# Rampup tests produce multiple summary files which include the batch
|
116
|
+
# number. Regular runs have just one file we set here as the default.
|
117
|
+
summary_name = "STATS"
|
118
|
+
|
119
|
+
# It's possible for the interval to not divide evenly into the ceiling
|
120
|
+
# If we have room between the current number of virtual users and the
|
121
|
+
# ceiling, we'll add the difference for the final test run.
|
122
|
+
if (@testdef.rampup)
|
123
|
+
final_total = @adapter.vusers + @testdef.rampup.interval
|
124
|
+
if final_total > threshold && (threshold - @adapter.vusers) > 0
|
125
|
+
@adapter.vusers += (threshold - @adapter.vusers)
|
126
|
+
else
|
127
|
+
@adapter.vusers += @testdef.rampup.interval
|
128
|
+
end
|
129
|
+
padded_users = @adapter.vusers.to_s.rjust(4, '0')
|
130
|
+
summary_name << "-#{padded_users}"
|
131
|
+
end
|
132
|
+
|
133
|
+
# Read the run summaries for this batch and produce totals, averages,
|
134
|
+
# and standard deviations.
|
135
|
+
@test_stats = process_test_stats(@test_runpaths)
|
136
|
+
print_summary(test_stats) if (@testdef.repetitions > 1)
|
137
|
+
save_summary(File.join(test_path, "#{summary_name}.#{@format}"), @test_stats)
|
138
|
+
|
139
|
+
|
140
|
+
# Non-rampup tests only need to run through the loop once.
|
141
|
+
break if (!@testdef.rampup && @adapter.vusers == threshold)
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
if @testdef.rampup
|
146
|
+
# Notice the difference between these test stats and the ones above?
|
147
|
+
# These stats are based on the entire rampup test, across all levels
|
148
|
+
# of virtual users.
|
149
|
+
@rampup_test_stats = process_test_stats(@all_runpaths)
|
150
|
+
save_summary(File.join(test_path, "STATS.#{@format}"), @rampup_test_stats)
|
151
|
+
print_summary(test_stats) if (@testdef.repetitions > 1)
|
152
|
+
end
|
153
|
+
rescue Interrupt
|
154
|
+
exit
|
155
|
+
rescue AdapterError => ex
|
156
|
+
Stella::LOGGER.error(ex.message)
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_path_symlink
|
160
|
+
return unless @working_directory
|
161
|
+
File.join(@working_directory, 'latest')
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
# prepare_test
|
168
|
+
#
|
169
|
+
# Execute the group of testruns associated to this test. This includes
|
170
|
+
# zero or one warmup and one or more testruns.
|
171
|
+
#
|
172
|
+
# INPUT:
|
173
|
+
# +test_path+ filesystem path to store all test data
|
174
|
+
#
|
175
|
+
def prepare_test(test_path)
|
176
|
+
|
177
|
+
Stella::LOGGER.info("Writing test data to: #{test_path}\n\n") unless @quiet
|
178
|
+
|
179
|
+
# Make sure the test storage directory is created along with the
|
180
|
+
# latest symlink
|
181
|
+
FileUtil.create_dir(test_path)
|
182
|
+
if Stella.sysinfo.os == :unix
|
183
|
+
File.unlink(test_path_symlink) if File.exists?(test_path_symlink)
|
184
|
+
File.symlink(File.expand_path(test_path), test_path_symlink)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Write the test ID to the storage directory
|
188
|
+
# NOTE: Disabled until we resolve the issue with JRuby on OSX (won't load openssl)
|
189
|
+
#FileUtil.write_file(test_path + "/ID.txt", @guid, true)
|
190
|
+
|
191
|
+
# And the test run message
|
192
|
+
FileUtil.write_file(test_path + "/MESSAGE.txt", @testdef.message, true) if @testdef.message
|
193
|
+
|
194
|
+
@adapter.user_agent = @agents unless @agents.empty?
|
195
|
+
|
196
|
+
# The warmup is identical to a testrun except for two things:
|
197
|
+
# - we don't make note of the runpath
|
198
|
+
# - there is a one second sleep after the run.
|
199
|
+
# Everything else is identical.
|
200
|
+
if @testdef.warmup
|
201
|
+
|
202
|
+
testrun = maker_of_testruns(@testdef.warmup)
|
203
|
+
|
204
|
+
# Generate the filesystem path to store the run data.
|
205
|
+
# NOTE: We don't keep the warmup path in @test_runpaths because we
|
206
|
+
# include it in the final calculation for the test.
|
207
|
+
runpath = File.join(test_path, "warmup")
|
208
|
+
|
209
|
+
# Run the warmpup round
|
210
|
+
testrun.call("Warmup", runpath)
|
211
|
+
|
212
|
+
run_sleeper(@testdef.sleep || 1)
|
213
|
+
|
214
|
+
Stella::LOGGER.info('', '') unless @quiet # We just need the newline
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
print_title unless @quiet
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
# maker_of_testruns
|
223
|
+
#
|
224
|
+
# Generator of test runs. Everything that happens during a test
|
225
|
+
# run is defined here. We use a Proc so we can toss the functionality
|
226
|
+
# around like something that's dirty and loves a good tossing.
|
227
|
+
# It's important that all output be on a single line without a
|
228
|
+
# line terminator. Otherwise great descruction could occur.
|
229
|
+
def maker_of_testruns(factor)
|
230
|
+
testrun = Proc.new do |name,runpath|
|
231
|
+
# Make sure the test run storage directory is created
|
232
|
+
FileUtil.create_dir(runpath)
|
233
|
+
|
234
|
+
@adapter.load_factor = factor
|
235
|
+
@adapter.working_directory = runpath
|
236
|
+
@adapter.before
|
237
|
+
|
238
|
+
Stella::LOGGER.info_printf("%8s: %10d@%-6s ", name, @adapter.requests, @adapter.vuser_rate) unless @quiet
|
239
|
+
|
240
|
+
# Here we record the command arguments. This needs to be last because we modify
|
241
|
+
# some of the arguments above.
|
242
|
+
FileUtil.write_file(runpath + "/COMMAND.txt", @adapter.command, true)
|
243
|
+
|
244
|
+
# Execute the command, send STDOUT and STDERR to separate files.
|
245
|
+
command = "#{@adapter.command} 1> \"#{@adapter.stdout_path}\" 2> \"#{@adapter.stderr_path}\""
|
246
|
+
Stella::LOGGER.info(" COMMAND: #{command}") if @verbose >= 2
|
247
|
+
|
248
|
+
begin
|
249
|
+
# Call the load tool
|
250
|
+
# $? contains the error status
|
251
|
+
succeeded = system(command)
|
252
|
+
|
253
|
+
# TODO: Catch interrupts for system calls. Currently it will simply and and continue with the next command
|
254
|
+
# i.e. these don't work:
|
255
|
+
rescue Interrupt
|
256
|
+
exit
|
257
|
+
rescue SystemExit
|
258
|
+
exit
|
259
|
+
end
|
260
|
+
|
261
|
+
unless succeeded
|
262
|
+
Stella::LOGGER.info('', '') # We used print so we need a new line for the error message.
|
263
|
+
raise AdapterError.new(@adapter.name, @adapter.error)
|
264
|
+
end
|
265
|
+
|
266
|
+
@adapter.after
|
267
|
+
|
268
|
+
stats = @adapter.summary
|
269
|
+
|
270
|
+
save_summary(@adapter.summary_path(@format), stats)
|
271
|
+
|
272
|
+
|
273
|
+
if !@quiet && stats && stats.available?
|
274
|
+
Stella::LOGGER.info_print(sprintf("%3.0f%% %9.2f/s %8.3fs ", stats.availability || 0, stats.transaction_rate || 0, stats.response_time || 0))
|
275
|
+
Stella::LOGGER.info_print(sprintf("%8.3fMB/s %8.3fMB %8.3fs ", stats.throughput || 0, stats.data_transferred || 0, stats.elapsed_time || 0))
|
276
|
+
# NOTE: We don't print a line terminator here
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
# print_summary
|
283
|
+
#
|
284
|
+
# Called during the test after every batch of test runs. For a rampup test
|
285
|
+
# it's also called at the end of all the runs.
|
286
|
+
#
|
287
|
+
# INPUT:
|
288
|
+
# stats:: Any object that extends Stella::Test::Base object
|
289
|
+
def print_summary(stats)
|
290
|
+
return if stats.nil?
|
291
|
+
Stella::LOGGER.info(' ' << "-"*67) unless @quiet
|
292
|
+
|
293
|
+
Stella::LOGGER.info_printf("%8s: %10d@%-6d %3.0f%% %9.2f/s ", "Total", stats.transactions_total || 0, stats.vusers_avg || 0, stats.availability || 0, stats.transaction_rate_avg || 0)
|
294
|
+
Stella::LOGGER.info_printf("%8.3fs %8.3fMB/s %8.3fMB %8.3fs", stats.response_time_avg || 0, stats.throughput_avg || 0, stats.data_transferred_total || 0, stats.elapsed_time_total || 0)
|
295
|
+
Stella::LOGGER.info('') # New line
|
296
|
+
Stella::LOGGER.info_printf("%8s: %22s %9.2f/s %8.3fs %8.3fMB/s %10s %8.3fs", "Std Dev", '', stats.transaction_rate_sdev || 0, stats.response_time_sdev || 0, stats.throughput_sdev || 0, '', stats.elapsed_time_sdev || 0)
|
297
|
+
Stella::LOGGER.info('') # New line
|
298
|
+
Stella::LOGGER.info('') unless @quiet # Extra new line
|
299
|
+
end
|
300
|
+
|
301
|
+
# print_title
|
302
|
+
#
|
303
|
+
# Prints the column headers for the test run output. Field widths match those
|
304
|
+
# in print_summary and test_maker
|
305
|
+
def print_title
|
306
|
+
Stella::LOGGER.info(' ' << "-"*67) unless @quiet
|
307
|
+
|
308
|
+
Stella::LOGGER.info_printf("%8s %10s@%-5s %5s %11s", "", 'REQ', 'VU/s', 'AVAIL', 'REQ/s')
|
309
|
+
Stella::LOGGER.info_printf("%10s %12s %10s %9s", 'RTIME', 'DATA/s', 'DATA', 'TIME')
|
310
|
+
Stella::LOGGER.info('') # New line
|
311
|
+
Stella::LOGGER.info('') unless @quiet # Extra new line
|
312
|
+
end
|
313
|
+
|
314
|
+
# save_summary
|
315
|
+
#
|
316
|
+
# Write a summary object to disk
|
317
|
+
#
|
318
|
+
# INPUT:
|
319
|
+
# filepath:: the complete path for the file (string)
|
320
|
+
# stats:: Any object that extends Stella::Test::Base object
|
321
|
+
def save_summary(filepath, stats)
|
322
|
+
return unless stats
|
323
|
+
stats.format = @format
|
324
|
+
stats.to_file(filepath)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Load SUMMARY file for each run and create a summary with
|
328
|
+
# totals, averages, and standard deviations.
|
329
|
+
def process_test_stats(paths)
|
330
|
+
return unless paths && !paths.empty?
|
331
|
+
test_stats = Stella::Test::Stats.new(@message)
|
332
|
+
|
333
|
+
paths.each do |path|
|
334
|
+
next unless File.exists?("#{path}/SUMMARY.#{@format}")
|
335
|
+
test_run = Stella::Test::Run::Summary.from_file("#{path}/SUMMARY.#{@format}")
|
336
|
+
test_stats.add_run(test_run)
|
337
|
+
end
|
338
|
+
|
339
|
+
test_stats
|
340
|
+
end
|
341
|
+
|
342
|
+
# This is the path where all test data will be stored
|
343
|
+
# The default is testruns/2008-12-31/test-001
|
344
|
+
def _generate_test_path
|
345
|
+
now = DateTime.now
|
346
|
+
time = Time.now
|
347
|
+
daystr = "#{now.year}-#{now.mon.to_s.rjust(2,'0')}-#{now.mday.to_s.rjust(2,'0')}"
|
348
|
+
testpath = File.join(@working_directory, 'testruns', daystr, 'test-')
|
349
|
+
testnum = 1.to_s.rjust(3,'0')
|
350
|
+
testnum.succ! while(File.directory? "#{testpath}#{testnum}")
|
351
|
+
"#{testpath}#{testnum}"
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Stella::Data
|
4
|
+
class DomainRequest < Stella::Storable
|
5
|
+
attr_accessor :dns_data
|
6
|
+
attr_reader :raw_data
|
7
|
+
|
8
|
+
field :time => DateTime
|
9
|
+
field :client_ip => String
|
10
|
+
field :server_ip => String
|
11
|
+
field :domain_name => String
|
12
|
+
field :header => String
|
13
|
+
|
14
|
+
def initialize(raw_data)
|
15
|
+
@raw_data = raw_data
|
16
|
+
@dns_data, @domain_name, @header = DomainUtil::parse_domain_request(@raw_data)
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_request?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
def has_response?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
def has_body?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"%s: %s -> %s (%s)" % [@time, @client_ip, @server_ip, @domain_name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
str = "#{$/};; REQUEST #{@time.to_s}"
|
35
|
+
str << "#{$/};; %s %s> %s" % [@client_ip, '-'*30, @server_ip]
|
36
|
+
str << "#{$/};;#{$/}"
|
37
|
+
str << @dns_data.inspect
|
38
|
+
str
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
class DomainResponse < Stella::Storable
|
44
|
+
attr_accessor :dns_data
|
45
|
+
attr_reader :raw_data
|
46
|
+
|
47
|
+
field :time => DateTime
|
48
|
+
field :client_ip => String
|
49
|
+
field :server_ip => String
|
50
|
+
field :domain_name => String
|
51
|
+
field :header => String
|
52
|
+
field :addresses => Array
|
53
|
+
field :cnames => Array
|
54
|
+
|
55
|
+
|
56
|
+
def initialize(raw_data)
|
57
|
+
@raw_data = raw_data
|
58
|
+
@dns_data, @domain_name, @header, @addresses, @cnames = DomainUtil::parse_domain_response(@raw_data)
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_request?
|
62
|
+
false
|
63
|
+
end
|
64
|
+
def has_response?
|
65
|
+
false
|
66
|
+
end
|
67
|
+
def has_body?
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
"%s: %s <- %s (%s) %s" % [@time, @client_ip, @server_ip, @domain_name, (@addresses || []).join(',')]
|
73
|
+
end
|
74
|
+
|
75
|
+
def inspect
|
76
|
+
str = "#{$/};; RESPONSE #{@time.strftime(NICE_TIME_FORMAT)}"
|
77
|
+
str << "#{$/};; %s <%s %s" % [@client_ip, '-'*30, @server_ip]
|
78
|
+
str << "#{$/};;#{$/}"
|
79
|
+
str << @dns_data.inspect
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|