wvanbergen-request-log-analyzer 0.2.2 → 0.3.0

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.
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