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.
Files changed (67) hide show
  1. data/{README → README.textile} +29 -36
  2. data/Rakefile +3 -70
  3. data/TODO +43 -8
  4. data/bin/request-log-analyzer +32 -99
  5. data/lib/base/summarizer.rb +14 -0
  6. data/lib/bashcolorizer.rb +1 -1
  7. data/lib/command_line/arguments.rb +15 -2
  8. data/lib/command_line/flag.rb +12 -0
  9. data/lib/rails_analyzer/summarizer.rb +12 -4
  10. data/lib/rails_analyzer/virtual_mongrel.rb +91 -0
  11. data/lib/request_log_analyzer/aggregator/base.rb +34 -0
  12. data/lib/request_log_analyzer/aggregator/database.rb +86 -0
  13. data/lib/request_log_analyzer/aggregator/echo.rb +10 -0
  14. data/lib/request_log_analyzer/aggregator/summarizer.rb +53 -0
  15. data/lib/request_log_analyzer/controller.rb +90 -0
  16. data/lib/request_log_analyzer/file_format/merb.rb +30 -0
  17. data/lib/request_log_analyzer/file_format/rails.rb +84 -0
  18. data/lib/request_log_analyzer/file_format.rb +91 -0
  19. data/lib/request_log_analyzer/log_parser.rb +122 -0
  20. data/lib/request_log_analyzer/request.rb +72 -0
  21. data/lib/request_log_analyzer.rb +5 -0
  22. data/output/blockers.rb +2 -4
  23. data/output/errors.rb +1 -2
  24. data/output/hourly_spread.rb +3 -3
  25. data/output/mean_db_time.rb +1 -2
  26. data/output/mean_rendering_time.rb +2 -3
  27. data/output/mean_time.rb +2 -3
  28. data/output/most_requested.rb +1 -2
  29. data/output/timespan.rb +10 -8
  30. data/output/total_db_time.rb +2 -3
  31. data/output/total_time.rb +2 -3
  32. data/output/usage.rb +3 -2
  33. data/spec/controller_spec.rb +33 -0
  34. data/spec/database_inserter_spec.rb +81 -0
  35. data/{test/log_fragments/merb_1.log → spec/fixtures/merb.log} +0 -0
  36. data/spec/fixtures/multiple_files_1.log +5 -0
  37. data/spec/fixtures/multiple_files_2.log +2 -0
  38. data/{test/log_fragments/fragment_1.log → spec/fixtures/rails_1x.log} +5 -5
  39. data/{test/log_fragments/fragment_3.log → spec/fixtures/rails_22.log} +2 -2
  40. data/spec/fixtures/rails_22_cached.log +10 -0
  41. data/spec/fixtures/rails_unordered.log +24 -0
  42. data/{test/log_fragments/fragment_2.log → spec/fixtures/syslog_1x.log} +0 -0
  43. data/spec/fixtures/test_file_format.log +11 -0
  44. data/spec/fixtures/test_language_combined.log +14 -0
  45. data/spec/fixtures/test_order.log +16 -0
  46. data/spec/line_definition_spec.rb +34 -0
  47. data/spec/log_parser_spec.rb +92 -0
  48. data/spec/merb_format_spec.rb +58 -0
  49. data/spec/rails_format_spec.rb +95 -0
  50. data/spec/request_spec.rb +76 -0
  51. data/spec/spec_helper.rb +49 -0
  52. data/spec/summarizer_spec.rb +109 -0
  53. data/tasks/github-gem.rake +177 -0
  54. data/tasks/request_log_analyzer.rake +10 -0
  55. data/tasks/rspec.rake +6 -0
  56. data/test/base_summarizer_test.rb +30 -0
  57. metadata +46 -22
  58. data/bin/request-log-database +0 -81
  59. data/lib/base/log_parser.rb +0 -78
  60. data/lib/base/record_inserter.rb +0 -139
  61. data/lib/merb_analyzer/log_parser.rb +0 -26
  62. data/lib/rails_analyzer/log_parser.rb +0 -35
  63. data/lib/rails_analyzer/record_inserter.rb +0 -39
  64. data/test/merb_log_parser_test.rb +0 -39
  65. data/test/rails_log_parser_test.rb +0 -95
  66. data/test/record_inserter_test.rb +0 -45
  67. 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 (> #{$summarizer.blocker_duration} seconds)"
3
+ puts "Mongrel process blockers (> #{@summarizer.blocker_duration} seconds)"
6
4
  puts green("========================================================================")
7
5
 
8
- $summarizer.sort_blockers_by(:count).reverse[0, amount.to_i].each do |a|
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
- $summarizer.sort_errors_by(:count).reverse[0, amount.to_i].each do |a|
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
@@ -1,7 +1,7 @@
1
1
  # Draws a graph containing the average amound of requests per hour per day
2
- if $summarizer.request_time_graph?
2
+ if @summarizer.request_time_graph?
3
3
 
4
- max_request_graph = $summarizer.request_time_graph.max / $summarizer.duration
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 = $summarizer.request_time_graph[a] / $summarizer.duration
14
+ requests = @summarizer.request_time_graph[a] / @summarizer.duration
15
15
  display_chars = requests / deviation
16
16
 
17
17
  if display_chars >= color_cutoff
@@ -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($summarizer, :mean_db_time, amount)
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($summarizer, :mean_rendering_time, amount)
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($summarizer, :mean_time, amount)
6
+ print_table(@summarizer, :mean_time, @amount)
@@ -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($summarizer, :count, amount)
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 $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"
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 = $summarizer.methods.inject(0) { |subtotal, (k, v)| subtotal + v }
13
- $summarizer.methods.each do |key, value|
14
- methods_print_array << "%s (%0.01f%%)" % [key, green((value * 100) / methods_request_count.to_f)]
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(', ') + '.'
@@ -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($summarizer, :total_db_time, amount)
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($summarizer, :total_time, amount)
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, -t: Only use completed requests"
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
@@ -0,0 +1,5 @@
1
+ initializing
2
+
3
+ processing request 1
4
+
5
+ testing is amazing
@@ -0,0 +1,2 @@
1
+ testing is cool
2
+ finishing request 1
@@ -1,4 +1,4 @@
1
- Processing DashboardController#index (for 130.89.162.199 at 2008-08-14 21:16:25) [GET]
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 130.89.162.199 at 2008-08-14 21:16:30) [GET]
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 130.89.162.199 at 2008-08-14 21:16:30) [GET]
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: Gaby Somers, study_year: 2008/2009
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 130.89.162.199 at 2008-08-14 21:16:35) [GET]
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 willem@depillem.com
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://floorplanner.local/demo]
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]
@@ -0,0 +1,11 @@
1
+ testing
2
+ testing methods
3
+ testing is cool
4
+ testing fixtures
5
+ testing is amazing
6
+ testing can be cumbersome
7
+ testing
8
+ nonsense
9
+ testing is
10
+
11
+ more nonsense
@@ -0,0 +1,14 @@
1
+ initializing
2
+
3
+ processing request 1
4
+
5
+ testing is amazing
6
+ testing is cool
7
+
8
+ finishing request 1
9
+
10
+ asdfad # garbage
11
+ dsaads # garbage
12
+
13
+ processing request 1
14
+ finishing request 1
@@ -0,0 +1,16 @@
1
+ initializing
2
+
3
+ processing request 1
4
+
5
+ testing is amazing
6
+ testing is cool
7
+
8
+ processing request 1
9
+ testing is cool
10
+ finishing request 1
11
+
12
+ asdfad # garbage
13
+ dsaads # garbage
14
+
15
+
16
+ finishing request 1
@@ -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