wvanbergen-request-log-analyzer 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{README → README.textile} +29 -36
- data/Rakefile +3 -70
- data/TODO +43 -8
- data/bin/request-log-analyzer +32 -99
- data/lib/base/summarizer.rb +14 -0
- data/lib/bashcolorizer.rb +1 -1
- data/lib/command_line/arguments.rb +15 -2
- data/lib/command_line/flag.rb +12 -0
- data/lib/rails_analyzer/summarizer.rb +12 -4
- data/lib/rails_analyzer/virtual_mongrel.rb +91 -0
- data/lib/request_log_analyzer/aggregator/base.rb +34 -0
- data/lib/request_log_analyzer/aggregator/database.rb +86 -0
- data/lib/request_log_analyzer/aggregator/echo.rb +10 -0
- data/lib/request_log_analyzer/aggregator/summarizer.rb +53 -0
- data/lib/request_log_analyzer/controller.rb +90 -0
- data/lib/request_log_analyzer/file_format/merb.rb +30 -0
- data/lib/request_log_analyzer/file_format/rails.rb +84 -0
- data/lib/request_log_analyzer/file_format.rb +91 -0
- data/lib/request_log_analyzer/log_parser.rb +122 -0
- data/lib/request_log_analyzer/request.rb +72 -0
- data/lib/request_log_analyzer.rb +5 -0
- data/output/blockers.rb +2 -4
- data/output/errors.rb +1 -2
- data/output/hourly_spread.rb +3 -3
- data/output/mean_db_time.rb +1 -2
- data/output/mean_rendering_time.rb +2 -3
- data/output/mean_time.rb +2 -3
- data/output/most_requested.rb +1 -2
- data/output/timespan.rb +10 -8
- data/output/total_db_time.rb +2 -3
- data/output/total_time.rb +2 -3
- data/output/usage.rb +3 -2
- data/spec/controller_spec.rb +33 -0
- data/spec/database_inserter_spec.rb +81 -0
- data/{test/log_fragments/merb_1.log → spec/fixtures/merb.log} +0 -0
- data/spec/fixtures/multiple_files_1.log +5 -0
- data/spec/fixtures/multiple_files_2.log +2 -0
- data/{test/log_fragments/fragment_1.log → spec/fixtures/rails_1x.log} +5 -5
- data/{test/log_fragments/fragment_3.log → spec/fixtures/rails_22.log} +2 -2
- data/spec/fixtures/rails_22_cached.log +10 -0
- data/spec/fixtures/rails_unordered.log +24 -0
- data/{test/log_fragments/fragment_2.log → spec/fixtures/syslog_1x.log} +0 -0
- data/spec/fixtures/test_file_format.log +11 -0
- data/spec/fixtures/test_language_combined.log +14 -0
- data/spec/fixtures/test_order.log +16 -0
- data/spec/line_definition_spec.rb +34 -0
- data/spec/log_parser_spec.rb +92 -0
- data/spec/merb_format_spec.rb +58 -0
- data/spec/rails_format_spec.rb +95 -0
- data/spec/request_spec.rb +76 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/summarizer_spec.rb +109 -0
- data/tasks/github-gem.rake +177 -0
- data/tasks/request_log_analyzer.rake +10 -0
- data/tasks/rspec.rake +6 -0
- data/test/base_summarizer_test.rb +30 -0
- metadata +46 -22
- data/bin/request-log-database +0 -81
- data/lib/base/log_parser.rb +0 -78
- data/lib/base/record_inserter.rb +0 -139
- data/lib/merb_analyzer/log_parser.rb +0 -26
- data/lib/rails_analyzer/log_parser.rb +0 -35
- data/lib/rails_analyzer/record_inserter.rb +0 -39
- data/test/merb_log_parser_test.rb +0 -39
- data/test/rails_log_parser_test.rb +0 -95
- data/test/record_inserter_test.rb +0 -45
- data/test/tasks.rake +0 -8
data/output/blockers.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
# Print requests that took more than a second to complete, sorted by their frequency.
|
2
|
-
amount = $arguments[:amount] || 10
|
3
|
-
|
4
2
|
puts
|
5
|
-
puts "Mongrel process blockers (> #{
|
3
|
+
puts "Mongrel process blockers (> #{@summarizer.blocker_duration} seconds)"
|
6
4
|
puts green("========================================================================")
|
7
5
|
|
8
|
-
|
6
|
+
@summarizer.sort_blockers_by(:count).reverse[0, @amount].each do |a|
|
9
7
|
puts "%-50s: %10.03fs [#{green("%d requests")}]" % [a[0], a[1][:total_time], a[1][:count]]
|
10
8
|
end
|
11
9
|
|
data/output/errors.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# Print errors that occured often
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
3
|
puts "Errors"
|
5
4
|
puts green("========================================================================")
|
6
|
-
|
5
|
+
@summarizer.sort_errors_by(:count).reverse[0, @amount].each do |a|
|
7
6
|
puts "%s: [#{green("%d requests")}]" % [a[0] + 'Error', a[1][:count]]
|
8
7
|
puts blue(' -> ' + (a[1][:exception_strings].invert[ a[1][:exception_strings].values.max ])[0..79])
|
9
8
|
end
|
data/output/hourly_spread.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Draws a graph containing the average amound of requests per hour per day
|
2
|
-
if
|
2
|
+
if @summarizer.request_time_graph?
|
3
3
|
|
4
|
-
max_request_graph =
|
4
|
+
max_request_graph = @summarizer.request_time_graph.max / @summarizer.duration
|
5
5
|
deviation = max_request_graph / 20
|
6
6
|
deviation = 1 if deviation == 0
|
7
7
|
color_cutoff = 15
|
@@ -11,7 +11,7 @@ if $summarizer.request_time_graph?
|
|
11
11
|
puts green("========================================================================")
|
12
12
|
|
13
13
|
(0..23).each do |a|
|
14
|
-
requests =
|
14
|
+
requests = @summarizer.request_time_graph[a] / @summarizer.duration
|
15
15
|
display_chars = requests / deviation
|
16
16
|
|
17
17
|
if display_chars >= color_cutoff
|
data/output/mean_db_time.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Prints a table sorted by the highest database times.
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
3
|
puts "Top #{amount} worst DB offenders - mean time"
|
5
4
|
puts green("========================================================================")
|
6
|
-
print_table(
|
5
|
+
print_table(@summarizer, :mean_db_time, @amount)
|
7
6
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# Prints a table showing the slowest renderes
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
|
-
puts "Top #{amount} slow renderers - mean time"
|
3
|
+
puts "Top #{@amount} slow renderers - mean time"
|
5
4
|
puts green("========================================================================")
|
6
|
-
print_table(
|
5
|
+
print_table(@summarizer, :mean_rendering_time, @amount)
|
7
6
|
|
data/output/mean_time.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Prints table sorted by the duration of the requests
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
|
-
puts "Top #{amount} actions by time - per request mean"
|
3
|
+
puts "Top #{@amount} actions by time - per request mean"
|
5
4
|
puts green("========================================================================")
|
6
5
|
|
7
|
-
print_table(
|
6
|
+
print_table(@summarizer, :mean_time, @amount)
|
data/output/most_requested.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Prints a table sorted by the most frequently requested actions
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
3
|
puts "Top #{amount} most requested actions"
|
5
4
|
puts green("========================================================================")
|
6
|
-
print_table(
|
5
|
+
print_table(@summarizer, :count, @amount)
|
data/output/timespan.rb
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
puts
|
3
3
|
puts green("========================================================================")
|
4
4
|
|
5
|
-
if
|
6
|
-
puts "Timestamp first request: #{
|
7
|
-
puts "Timestamp last request: #{
|
8
|
-
puts "Total time analyzed:
|
5
|
+
if @summarizer.has_timestamps?
|
6
|
+
puts "Timestamp first request: #{@summarizer.first_request_at}"
|
7
|
+
puts "Timestamp last request: #{@summarizer.last_request_at}"
|
8
|
+
puts "Total time analyzed: #{@summarizer.duration} days"
|
9
|
+
puts ""
|
10
|
+
puts "Total requests analyzed: #{@summarizer.request_count}"
|
9
11
|
end
|
10
12
|
|
11
13
|
methods_print_array = []
|
12
|
-
methods_request_count =
|
13
|
-
|
14
|
-
methods_print_array << "%s (%0.01f%%)" % [key,
|
14
|
+
methods_request_count = @summarizer.methods.inject(0) { |subtotal, (k, v)| subtotal + v }
|
15
|
+
@summarizer.methods.each do |key, value|
|
16
|
+
methods_print_array << green("%s (%0.01f%%)") % [key, (value * 100) / methods_request_count.to_f]
|
15
17
|
end
|
16
|
-
puts 'Methods: ' + methods_print_array.join(', ') + '.'
|
18
|
+
puts 'Methods: ' + methods_print_array.join(', ') + '.'
|
data/output/total_db_time.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Prints a list of the actions that spend most of their time waiting for database results.
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
|
-
puts "Top #{amount} worst DB offenders - cumulative time"
|
3
|
+
puts "Top #{@amount} worst DB offenders - cumulative time"
|
5
4
|
puts green("========================================================================")
|
6
|
-
print_table(
|
5
|
+
print_table(@summarizer, :total_db_time, @amount)
|
data/output/total_time.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# Prints a list ordered by the requests that took the most time in total.
|
2
|
-
amount = $arguments[:amount] || 10
|
3
2
|
puts
|
4
|
-
puts "Top #{amount} actions by time - cumulative"
|
3
|
+
puts "Top #{@amount} actions by time - cumulative"
|
5
4
|
puts green("========================================================================")
|
6
|
-
print_table(
|
5
|
+
print_table(@summarizer, :total_time, @amount)
|
data/output/usage.rb
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
puts "Usage: request-log-analyzer [LOGFILES*] <OPTIONS>"
|
3
3
|
puts
|
4
4
|
puts "Options:"
|
5
|
-
puts " --fast, -
|
5
|
+
puts " --fast, -f: Only use completed requests"
|
6
6
|
puts " --guess-database-time, -g: Guesses the database duration of requests"
|
7
7
|
puts " --output, -o: Comma-separated list of reports to show"
|
8
8
|
puts " --amount, -c: Displays the top <amount> elements in the reports"
|
9
9
|
puts " --colorize, -z: Fancy bash coloring"
|
10
10
|
puts " --merb, -m: Parse merb logfiles"
|
11
|
+
puts " --install rails, -i rails Install Rails task rake log:analyze"
|
11
12
|
puts
|
12
13
|
puts "Examples:"
|
13
14
|
puts " request-log-analyzer development.log"
|
14
15
|
puts " request-log-analyzer mongrel.0.log mongrel.1.log mongrel.2.log -g -f -o mean_time,most_requested,blockers -c 20 -z"
|
15
|
-
puts
|
16
|
+
puts " request-log-analyzer --install rails"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::Controller do
|
4
|
+
|
5
|
+
include RequestLogAnalyzerSpecHelper
|
6
|
+
|
7
|
+
it "should include the file format module" do
|
8
|
+
controller = RequestLogAnalyzer::Controller.new(:rails)
|
9
|
+
(class << controller; self; end).ancestors.include?(RequestLogAnalyzer::FileFormat::Rails)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should call the aggregators when run" do
|
13
|
+
controller = RequestLogAnalyzer::Controller.new(:rails)
|
14
|
+
controller << log_fixture(:rails_1x)
|
15
|
+
|
16
|
+
mock_aggregator = mock('aggregator')
|
17
|
+
mock_aggregator.should_receive(:prepare).once.ordered
|
18
|
+
mock_aggregator.should_receive(:aggregate).with(an_instance_of(RequestLogAnalyzer::Request)).at_least(:twice).ordered
|
19
|
+
mock_aggregator.should_receive(:finalize).once.ordered
|
20
|
+
mock_aggregator.should_receive(:report).once.ordered
|
21
|
+
|
22
|
+
another_mock_aggregator = mock('another aggregator')
|
23
|
+
another_mock_aggregator.should_receive(:prepare).once.ordered
|
24
|
+
another_mock_aggregator.should_receive(:aggregate).with(an_instance_of(RequestLogAnalyzer::Request)).at_least(:twice).ordered
|
25
|
+
another_mock_aggregator.should_receive(:finalize).once.ordered
|
26
|
+
another_mock_aggregator.should_receive(:report).once.ordered
|
27
|
+
|
28
|
+
|
29
|
+
controller.aggregators << mock_aggregator << another_mock_aggregator
|
30
|
+
controller.run!
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'request_log_analyzer/aggregator/database'
|
3
|
+
|
4
|
+
|
5
|
+
describe RequestLogAnalyzer::Aggregator::Database, "schema creation" do
|
6
|
+
|
7
|
+
TEST_DATABASE_FILE = File.dirname(__FILE__) + "/fixtures/requests.db"
|
8
|
+
include RequestLogAnalyzerSpecHelper
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@database_inserter = RequestLogAnalyzer::Aggregator::Database.new(TestFileFormat, :database => TEST_DATABASE_FILE)
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should create the correct tables" do
|
19
|
+
ActiveRecord::Migration.should_receive(:create_table).with("warnings")
|
20
|
+
ActiveRecord::Migration.should_receive(:create_table).with("first_lines")
|
21
|
+
ActiveRecord::Migration.should_receive(:create_table).with("test_lines")
|
22
|
+
ActiveRecord::Migration.should_receive(:create_table).with("last_lines")
|
23
|
+
@database_inserter.prepare
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should create the default table names" do
|
27
|
+
@database_inserter.prepare
|
28
|
+
@database_inserter.file_format.line_definitions.each do |name, definition|
|
29
|
+
klass = TestFileFormat.const_get("#{name}_line".camelize)
|
30
|
+
klass.column_names.should include('id')
|
31
|
+
klass.column_names.should include('lineno')
|
32
|
+
klass.column_names.should include('request_id')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should create the correct fields in the table" do
|
37
|
+
@database_inserter.prepare
|
38
|
+
|
39
|
+
TestFileFormat::FirstLine.column_names.should include('request_no')
|
40
|
+
TestFileFormat::LastLine.column_names.should include('request_no')
|
41
|
+
TestFileFormat::TestLine.column_names.should include('test_capture')
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe RequestLogAnalyzer::Aggregator::Database, "record insertion" do
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
@database_inserter = RequestLogAnalyzer::Aggregator::Database.new(TestFileFormat, :database => TEST_DATABASE_FILE)
|
50
|
+
@database_inserter.prepare
|
51
|
+
|
52
|
+
@single = RequestLogAnalyzer::Request.create(TestFileFormat, {:line_type => :first, :request_no => 564})
|
53
|
+
@combined = RequestLogAnalyzer::Request.create(TestFileFormat,
|
54
|
+
{:line_type => :first, :request_no => 564},
|
55
|
+
{:line_type => :test, :test_capture => "awesome"},
|
56
|
+
{:line_type => :test, :test_capture => "indeed"},
|
57
|
+
{:line_type => :last, :request_no => 564})
|
58
|
+
end
|
59
|
+
|
60
|
+
after(:each) do
|
61
|
+
File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should insert a record in the relevant table" do
|
65
|
+
TestFileFormat::FirstLine.should_receive(:create!).with(hash_including(:request_no => 564))
|
66
|
+
@database_inserter.aggregate(@single)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should insert records in all relevant tables" do
|
70
|
+
TestFileFormat::FirstLine.should_receive(:create!).with(hash_including(:request_no => 564)).once
|
71
|
+
TestFileFormat::TestLine.should_receive(:create!).twice
|
72
|
+
TestFileFormat::LastLine.should_receive(:create!).with(hash_including(:request_no => 564)).once
|
73
|
+
@database_inserter.aggregate(@combined)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should log a warning in the warnings table" do
|
77
|
+
TestFileFormat::Warning.should_receive(:create!).with(hash_including(:warning_type => 'test_warning'))
|
78
|
+
@database_inserter.warning(:test_warning, "Testing the warning system", 12)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Processing DashboardController#index (for
|
1
|
+
Processing DashboardController#index (for 1.1.1.1 at 2008-08-14 21:16:25) [GET]
|
2
2
|
Session ID: BAh7CToMcmVmZXJlciIbL3ByaXNjaWxsYS9wZW9wbGUvMjM1MCIKZmxhc2hJ
|
3
3
|
QzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVz
|
4
4
|
ZWR7ADoNbGFuZ3VhZ2VvOhNMb2NhbGU6Ok9iamVjdBI6CUB3aW4wOg1AY291
|
@@ -13,7 +13,7 @@ Rendering dashboard/index
|
|
13
13
|
Completed in 0.22699 (4 reqs/sec) | Rendering: 0.02667 (11%) | DB: 0.03057 (13%) | 200 OK [https://www.example.com/]
|
14
14
|
|
15
15
|
|
16
|
-
Processing PeopleController#index (for
|
16
|
+
Processing PeopleController#index (for 1.1.1.1 at 2008-08-14 21:16:30) [GET]
|
17
17
|
Session ID: BAh7CSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo
|
18
18
|
SGFzaHsABjoKQHVzZWR7ADoMcmVmZXJlciIQL3ByaXNjaWxsYS86DnBlcnNv
|
19
19
|
bl9pZGkCMgc6DWxhbmd1YWdlbzoTTG9jYWxlOjpPYmplY3QSOg1AY291bnRy
|
@@ -27,7 +27,7 @@ Redirected to https://www.example.com/people/2545
|
|
27
27
|
Completed in 0.04759 (21 reqs/sec) | DB: 0.03719 (78%) | 302 Found [https://www.example.com/people?q=gaby&commit=Zoek]
|
28
28
|
|
29
29
|
|
30
|
-
Processing PeopleController#show (for
|
30
|
+
Processing PeopleController#show (for 1.1.1.1 at 2008-08-14 21:16:30) [GET]
|
31
31
|
Session ID: BAh7CToMcmVmZXJlciIpL3ByaXNjaWxsYS9wZW9wbGU/cT1nYWJ5JmNvbW1p
|
32
32
|
dD1ab2VrIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxh
|
33
33
|
c2hIYXNoewAGOgpAdXNlZHsAOg1sYW5ndWFnZW86E0xvY2FsZTo6T2JqZWN0
|
@@ -40,11 +40,11 @@ X2lkaQIyBw==--3ad1948559448522a49d289a2a89dc7ccbe8847a
|
|
40
40
|
Set language to: nl_NL
|
41
41
|
Rendering template within layouts/priscilla
|
42
42
|
Rendering people/show
|
43
|
-
person:
|
43
|
+
person: John Doe, study_year: 2008/2009
|
44
44
|
Completed in 0.29077 (3 reqs/sec) | Rendering: 0.24187 (83%) | DB: 0.04030 (13%) | 200 OK [https://www.example.com/people/2545]
|
45
45
|
|
46
46
|
|
47
|
-
Processing PeopleController#picture (for
|
47
|
+
Processing PeopleController#picture (for 1.1.1.1 at 2008-08-14 21:16:35) [GET]
|
48
48
|
Session ID: BAh7CSIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo
|
49
49
|
SGFzaHsABjoKQHVzZWR7ADoMcmVmZXJlciIbL3ByaXNjaWxsYS9wZW9wbGUv
|
50
50
|
MjU0NToOcGVyc29uX2lkaQIyBzoNbGFuZ3VhZ2VvOhNMb2NhbGU6Ok9iamVj
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Processing PageController#demo (for 127.0.0.1 at 2008-12-10 16:28:09) [GET]
|
2
2
|
Parameters: {"action"=>"demo", "controller"=>"page"}
|
3
3
|
Logging in from session data...
|
4
|
-
Logged in as
|
4
|
+
Logged in as test@example.com
|
5
5
|
Using locale: en-US, http-accept: ["en-US"], session: , det browser: en-US, det domain:
|
6
6
|
Rendering template within layouts/demo
|
7
7
|
Rendering page/demo
|
@@ -9,4 +9,4 @@ Rendered shared/_analytics (0.2ms)
|
|
9
9
|
Rendered layouts/_actions (0.6ms)
|
10
10
|
Rendered layouts/_menu (2.2ms)
|
11
11
|
Rendered layouts/_tabbar (0.5ms)
|
12
|
-
Completed in 614ms (View: 120, DB: 31) | 200 OK [http://
|
12
|
+
Completed in 614ms (View: 120, DB: 31) | 200 OK [http://www.example.coml/demo]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Processing CachedController#cached (for 1.1.1.1 at 2008-12-24 07:36:53) [GET]
|
2
|
+
Parameters: {"action"=>"cached", "controller"=>"cached"}
|
3
|
+
Logging in from session data...
|
4
|
+
Logging in using cookie...
|
5
|
+
Using locale: zh-Hans, http-accept: ["zh-CN", "zh-HK", "zh-TW", "en-US"], session: , det browser: zh-Hans, det domain: , user pref locale:
|
6
|
+
Referer: http://www.example.com/referer
|
7
|
+
Cached fragment hit: views/zh-Hans-www-cached-cached-all-CN--- (0.0ms)
|
8
|
+
Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>] rendered_or_redirected.
|
9
|
+
Filter chain halted as [#<ActionController::Filters::AroundFilter:0x2a999ad120 @identifier=nil, @kind=:filter, @options={:only=>#<Set: {"cached"}>, :if=>:not_logged_in?, :unless=>nil}, @method=#<ActionController::Caching::Actions::ActionCacheFilter:0x2a999ad620 @check=nil, @options={:store_options=>{}, :layout=>nil, :cache_path=>#<Proc:0x0000002a999b8890@/app/controllers/cached_controller.rb:8>}>>] did_not_yield.
|
10
|
+
Completed in 3ms (View: 0, DB: 0) | 200 OK [http://www.example.com/cached/cached/]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Processing AccountController#dashboard (for 1.1.1.1 at 2008-12-24 07:36:49) [GET]
|
2
|
+
Parameters: {"action"=>"dashboard", "controller"=>"account", "first_use"=>"true"}
|
3
|
+
Logging in from session data...
|
4
|
+
|
5
|
+
|
6
|
+
Processing ProjectsController#new (for 1.1.1.1 at 2008-12-24 07:36:49) [GET]
|
7
|
+
Parameters: {"action"=>"new", "controller"=>"projects"}
|
8
|
+
Rendering template within layouts/default
|
9
|
+
Rendering account/dashboard
|
10
|
+
Logging in from session data...
|
11
|
+
Logging in using cookie...
|
12
|
+
Using locale: en-US, http-accept: [], session: , det browser: , det domain: , user pref locale:
|
13
|
+
Rendered shared/_maintenance (0.6ms)
|
14
|
+
Rendering template within layouts/templates/general_default/index.html.erb
|
15
|
+
Rendered projects/_recent_designs (4.3ms)
|
16
|
+
Rendered projects/_project (13.6ms)
|
17
|
+
Rendered projects/_projects (18.7ms)
|
18
|
+
Rendered layouts/_menu (1.4ms)
|
19
|
+
Completed in 36ms (View: 30, DB: 3) | 200 OK [http://www.example.com/projects/new]
|
20
|
+
Rendered layouts/_actions (0.3ms)
|
21
|
+
Rendered layouts/_menu (1.6ms)
|
22
|
+
Rendered layouts/_tabbar (1.9ms)
|
23
|
+
Rendered layouts/_footer (3.2ms)
|
24
|
+
Completed in 50ms (View: 41, DB: 4) | 200 OK [http://www.example.com/dashboard?first_use=true]
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::FileFormat::LineDefinition do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@line_definition = RequestLogAnalyzer::FileFormat::LineDefinition.new(:test, {
|
7
|
+
:teaser => /Testing /,
|
8
|
+
:regexp => /Testing (\w+), tries\: (\d+)/,
|
9
|
+
:captures => [{:what => :string}, {:tries => :integer}]
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return false on an unmatching line" do
|
14
|
+
(@line_definition =~ "nonmatching").should be_false
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return false when only the teaser matches" do
|
18
|
+
(@line_definition =~ "Testing LineDefinition").should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return a hash if the line matches" do
|
22
|
+
(@line_definition =~ "Testing LineDefinition, tries: 123").should be_kind_of(Hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return a hash with all captures set" do
|
26
|
+
hash = @line_definition.matches("Testing LineDefinition, tries: 123")
|
27
|
+
hash[:what].should == "LineDefinition"
|
28
|
+
hash[:tries].should == 123
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return a hash with :line_type set" do
|
32
|
+
@line_definition.matches("Testing LineDefinition, tries: 123")[:line_type].should == :test
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::LogParser, :single_line_requests do
|
4
|
+
|
5
|
+
include RequestLogAnalyzerSpecHelper
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(TestFileFormat)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have line definitions" do
|
12
|
+
@log_parser.file_format.line_definitions.should_not be_empty
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have include the language specific hooks in the instance, not in the class" do
|
16
|
+
metaclass = (class << @log_parser; self; end)
|
17
|
+
metaclass.ancestors.should include(TestFileFormat::LogParser)
|
18
|
+
@log_parser.class.ancestors.should_not include(TestFileFormat::LogParser)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should parse a stream and find valid requests" do
|
22
|
+
io = File.new(log_fixture(:test_file_format), 'r')
|
23
|
+
@log_parser.parse_io(io, :line_types => [:test]) do |request|
|
24
|
+
request.should be_kind_of(RequestLogAnalyzer::Request)
|
25
|
+
request.should =~ :test
|
26
|
+
request[:test_capture].should_not be_nil
|
27
|
+
end
|
28
|
+
io.close
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should find as many lines as request" do
|
32
|
+
@log_parser.parse_file(log_fixture(:test_file_format)) { |request| request.should be_single_line }
|
33
|
+
@log_parser.parsed_lines.should eql(@log_parser.parsed_requests)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe RequestLogAnalyzer::LogParser, :combined_requests do
|
38
|
+
include RequestLogAnalyzerSpecHelper
|
39
|
+
|
40
|
+
before(:each) do
|
41
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(TestFileFormat, :combined_requests => true)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have multiple line definitions" do
|
45
|
+
@log_parser.file_format.line_definitions.length.should >= 2
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have a valid language" do
|
49
|
+
@log_parser.file_format.should be_valid
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should parse more lines than requests" do
|
53
|
+
@log_parser.should_receive(:handle_request).with(an_instance_of(RequestLogAnalyzer::Request)).twice
|
54
|
+
@log_parser.parse_file(log_fixture(:test_language_combined)) { |request| request.should be_combined }
|
55
|
+
@log_parser.parsed_lines.should > 2
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should parse requests spanned over multiple files" do
|
59
|
+
@log_parser.should_receive(:handle_request).with(an_instance_of(RequestLogAnalyzer::Request)).once
|
60
|
+
@log_parser.parse_files([log_fixture(:multiple_files_1), log_fixture(:multiple_files_2)])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should parse all request values when spanned over multiple files" do
|
64
|
+
@log_parser.parse_files([log_fixture(:multiple_files_1), log_fixture(:multiple_files_2)]) do |request|
|
65
|
+
request.lines.should have(4).items
|
66
|
+
|
67
|
+
request[:request_no].should == 1
|
68
|
+
request[:test_capture].should == "amazing"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe RequestLogAnalyzer::LogParser, :warnings do
|
74
|
+
include RequestLogAnalyzerSpecHelper
|
75
|
+
|
76
|
+
it "should warn about teaser matching problems" do
|
77
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(TestFileFormat)
|
78
|
+
@log_parser.should_receive(:warn).with(:teaser_check_failed, anything).exactly(5).times
|
79
|
+
@log_parser.parse_file(log_fixture(:test_file_format))
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should warn about unmatching request headers and footers" do
|
83
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(TestFileFormat, :combined_requests => true)
|
84
|
+
|
85
|
+
@log_parser.should_receive(:warn).with(:unclosed_request, anything).at_least(1).times
|
86
|
+
@log_parser.should_receive(:warn).with(:no_current_request, anything).at_least(1).times
|
87
|
+
@log_parser.should_not_receive(:handle_request)
|
88
|
+
@log_parser.parse_file(log_fixture(:test_order))
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe RequestLogAnalyzer::LogParser, "Merb without combined requests" do
|
4
|
+
include RequestLogAnalyzerSpecHelper
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(:merb, :combined_requests => false)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should parse a stream and find valid requests" do
|
11
|
+
File.open(log_fixture(:merb), 'r') do |io|
|
12
|
+
@log_parser.parse_io(io) do |request|
|
13
|
+
request.should be_kind_of(RequestLogAnalyzer::Request)
|
14
|
+
request.should be_single_line
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should find 33 request lines when lines are not linked" do
|
20
|
+
@log_parser.should_receive(:handle_request).exactly(33).times
|
21
|
+
@log_parser.parse_file(log_fixture(:merb))
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should find 11 request start lines when lines are not linked" do
|
25
|
+
@log_parser.should_receive(:handle_request).exactly(11).times
|
26
|
+
@log_parser.parse_file(log_fixture(:merb), :line_types => [:started])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
describe RequestLogAnalyzer::LogParser, "Merb with combined requests" do
|
32
|
+
include RequestLogAnalyzerSpecHelper
|
33
|
+
|
34
|
+
before(:each) do
|
35
|
+
@log_parser = RequestLogAnalyzer::LogParser.new(:merb, :combined_requests => true)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have a valid language definitions" do
|
39
|
+
@log_parser.file_format.should be_valid
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should find 11 completed requests when lines are linked" do
|
43
|
+
@log_parser.should_receive(:handle_request).exactly(11).times
|
44
|
+
@log_parser.parse_file(log_fixture(:merb))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should parse all details from a request correctly" do
|
48
|
+
request = nil
|
49
|
+
@log_parser.parse_file(log_fixture(:merb)) { |found_request| request ||= found_request }
|
50
|
+
|
51
|
+
request.should be_completed
|
52
|
+
request[:timestamp].should == 'Fri Aug 29 11:10:23 +0200 2008'
|
53
|
+
request[:dispatch_time].should == 0.243424
|
54
|
+
request[:after_filters_time].should == 6.9e-05
|
55
|
+
request[:before_filters_time].should == 0.213213
|
56
|
+
request[:action_time].should == 0.241652
|
57
|
+
end
|
58
|
+
end
|