request-log-analyzer 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/bin/request-log-analyzer +0 -1
  2. data/lib/request_log_analyzer.rb +15 -29
  3. data/lib/request_log_analyzer/aggregator.rb +5 -5
  4. data/lib/request_log_analyzer/aggregator/database_inserter.rb +2 -1
  5. data/lib/request_log_analyzer/controller.rb +0 -3
  6. data/lib/request_log_analyzer/database.rb +6 -7
  7. data/lib/request_log_analyzer/file_format.rb +42 -13
  8. data/lib/request_log_analyzer/file_format/apache.rb +1 -1
  9. data/lib/request_log_analyzer/file_format/delayed_job2.rb +2 -2
  10. data/lib/request_log_analyzer/file_format/delayed_job21.rb +2 -2
  11. data/lib/request_log_analyzer/file_format/haproxy.rb +107 -13
  12. data/lib/request_log_analyzer/file_format/mysql.rb +5 -5
  13. data/lib/request_log_analyzer/file_format/rails3.rb +7 -0
  14. data/lib/request_log_analyzer/filter.rb +4 -5
  15. data/lib/request_log_analyzer/line_definition.rb +6 -4
  16. data/lib/request_log_analyzer/output.rb +3 -5
  17. data/lib/request_log_analyzer/source.rb +3 -4
  18. data/lib/request_log_analyzer/source/log_parser.rb +56 -4
  19. data/lib/request_log_analyzer/tracker.rb +8 -8
  20. data/request-log-analyzer.gemspec +3 -3
  21. data/spec/fixtures/mysql_slow_query.log +0 -1
  22. data/spec/integration/command_line_usage_spec.rb +0 -5
  23. data/spec/lib/helpers.rb +2 -2
  24. data/spec/lib/matchers.rb +38 -7
  25. data/spec/lib/mocks.rb +1 -5
  26. data/spec/unit/database/base_class_spec.rb +1 -0
  27. data/spec/unit/file_format/amazon_s3_format_spec.rb +58 -55
  28. data/spec/unit/file_format/apache_format_spec.rb +74 -162
  29. data/spec/unit/file_format/common_regular_expressions_spec.rb +51 -26
  30. data/spec/unit/file_format/delayed_job21_format_spec.rb +22 -31
  31. data/spec/unit/file_format/delayed_job2_format_spec.rb +27 -32
  32. data/spec/unit/file_format/delayed_job_format_spec.rb +44 -63
  33. data/spec/unit/file_format/haproxy_format_spec.rb +69 -71
  34. data/spec/unit/file_format/line_definition_spec.rb +26 -33
  35. data/spec/unit/file_format/merb_format_spec.rb +22 -37
  36. data/spec/unit/file_format/mysql_format_spec.rb +80 -123
  37. data/spec/unit/file_format/oink_format_spec.rb +29 -61
  38. data/spec/unit/file_format/postgresql_format_spec.rb +2 -4
  39. data/spec/unit/file_format/rack_format_spec.rb +49 -44
  40. data/spec/unit/file_format/rails3_format_spec.rb +17 -20
  41. data/spec/unit/file_format/rails_format_spec.rb +52 -68
  42. data/spec/unit/file_format/w3c_format_spec.rb +40 -39
  43. data/spec/unit/source/log_parser_spec.rb +1 -1
  44. metadata +4 -7
  45. data/lib/mixins/gets_memory_protection.rb +0 -80
  46. data/lib/request_log_analyzer/output/fancy_html.rb +0 -44
  47. data/lib/request_log_analyzer/source/database_loader.rb +0 -87
@@ -1,50 +1,55 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::FileFormat::Rack do
4
+
5
+ subject { RequestLogAnalyzer::FileFormat.load(:rack)}
6
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
7
+
8
+ it { should be_well_formed }
9
+ it { should have_line_definition(:access).capturing(:remote_host, :user, :remote_logname,
10
+ :timestamp, :http_method, :path, :http_version, :http_status, :bytes_sent, :duration) }
11
+
12
+ it { should have(7).report_trackers }
13
+
14
+ let(:sample1) { '127.0.0.1 - - [23/Nov/2009 21:47:47] "GET /css/stylesheet.css HTTP/1.1" 200 3782 0.0024' }
15
+ let(:sample2) { '127.0.0.1 - - [16/Sep/2009 07:40:08] "GET /favicon.ico HTTP/1.1" 500 63183 0.0453' }
16
+ let(:sample3) { '127.0.0.1 - - [01/Oct/2009 07:58:10] "GET / HTTP/1.1" 200 1 0.0045' }
17
+ let(:irrelevant) { '== Sinatra/0.9.4 has taken the stage on 4567 for development with backup from Mongrel' }
18
+
19
+ describe '#parse_line' do
20
+
21
+ it { should parse_line(sample1, 'a sample access line').and_capture(
22
+ :remote_host => '127.0.0.1', :timestamp => 20091123214747, :user => nil,
23
+ :http_status => 200, :http_method => 'GET', :http_version => '1.1',
24
+ :duration => 0.0024, :bytes_sent => 3782, :remote_logname => nil,
25
+ :path => '/css/stylesheet.css')
26
+ }
27
+
28
+ it { should parse_line(sample2, 'another sample access line').and_capture(
29
+ :remote_host => '127.0.0.1', :timestamp => 20090916074008, :user => nil,
30
+ :http_status => 500, :http_method => 'GET', :http_version => '1.1',
31
+ :duration => 0.0453, :bytes_sent => 63183, :remote_logname => nil,
32
+ :path => '/favicon.ico')
33
+ }
34
+
35
+ it { should parse_line(sample3, 'a third sample access line').and_capture(
36
+ :remote_host => '127.0.0.1', :timestamp => 20091001075810, :user => nil,
37
+ :http_status => 200, :http_method => 'GET', :http_version => '1.1',
38
+ :duration => 0.0045, :bytes_sent => 1, :remote_logname => nil,
39
+ :path => '/')
40
+ }
41
+
42
+ it { should_not parse_line(irrelevant, 'an irrelevant line') }
43
+ it { should_not parse_line('nonsense', 'a nonsense line') }
44
+ end
4
45
 
5
- context '"Sinatra" access log parsing' do
6
-
7
- before(:each) do
8
- @file_format = RequestLogAnalyzer::FileFormat.load(:rack)
9
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
10
- @sample = '127.0.0.1 - - [23/Nov/2009 21:47:47] "GET /css/stylesheet.css HTTP/1.1" 200 3782 0.0024'
11
- end
12
-
13
- it "should be a valid file format" do
14
- @file_format.should be_valid
15
- end
16
-
17
- it "should parse access lines and capture all of its fields" do
18
- @file_format.should have_line_definition(:access).capturing(:remote_host, :timestamp, :http_method, :path, :http_version,
19
- :http_status, :bytes_sent, :duration)
20
- end
21
-
22
- it "should match the sample line" do
23
- @file_format.parse_line(@sample).should include(:line_definition, :captures)
24
- end
25
-
26
- it "should not match a nonsense line" do
27
- @file_format.parse_line('== Sinatra/0.9.4 has taken the stage on 4567 for development with backup from Mongrel').should be_nil
28
- end
29
-
30
- it "should parse the sample fields correctly" do
31
- match = @file_format.parse_line(@sample)
32
- match.should_not be_nil
33
- end
34
-
35
- it "should parse and convert the sample fields correctly" do
36
- @log_parser.parse_io(StringIO.new(@sample)) do |request|
37
- request[:remote_host].should == '127.0.0.1'
38
- request[:timestamp].should == 20091123214747
39
- request[:http_method].should == 'GET'
40
- request[:path].should == '/css/stylesheet.css'
41
- request[:http_version].should == '1.1'
42
- request[:http_status].should == 200
43
- request[:bytes_sent].should == 3782
44
- request[:duration].should == 0.0024
45
- end
46
+ describe '#parse_io' do
47
+ let(:snippet) { log_snippet(irrelevant, sample1, sample2, sample3) }
48
+
49
+ it "shouldparse a snippet without warnings" do
50
+ log_parser.should_receive(:handle_request).exactly(3).times
51
+ log_parser.should_not_receive(:warn)
52
+ log_parser.parse_io(snippet)
46
53
  end
47
-
48
54
  end
49
-
50
- end
55
+ end
@@ -3,12 +3,11 @@ require 'spec_helper'
3
3
  describe RequestLogAnalyzer::FileFormat::Rails3 do
4
4
 
5
5
  subject { RequestLogAnalyzer::FileFormat.load(:rails3) }
6
- let(:log_parser) {RequestLogAnalyzer::Source::LogParser.new(subject) }
7
6
 
8
- it { should be_valid }
9
-
7
+ it { should be_well_formed }
8
+ it { should have(9).report_trackers }
9
+
10
10
  describe '#parse_line' do
11
- before(:each) { @file_format = RequestLogAnalyzer::FileFormat.load(:rails3) }
12
11
 
13
12
  it "should parse :started lines correctly" do
14
13
  line = 'Started GET "/queries" for 127.0.0.1 at Thu Feb 25 16:15:18 -0800 2010'
@@ -51,6 +50,11 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
51
50
  subject.should parse_line(line).as(:processing).and_capture(
52
51
  :controller => 'ProjectsController', :action => 'avatar', :format => '')
53
52
  end
53
+
54
+ it "should parse a :parameters line correctly" do
55
+ line = ' Parameters: {"action"=>"cached", "controller"=>"cached"}'
56
+ subject.should parse_line(line).as(:parameters).and_capture(:params => {:action => 'cached', :controller => 'cached'})
57
+ end
54
58
 
55
59
  it "should parse :completed lines correctly" do
56
60
  line = 'Completed 200 OK in 170ms (Views: 78.0ms | ActiveRecord: 48.2ms)'
@@ -72,7 +76,7 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
72
76
 
73
77
  it "should pase :failure lines correctly" do
74
78
  line = "ActionView::Template::Error (undefined local variable or method `field' for #<Class>) on line #3 of /Users/willem/Code/warehouse/app/views/queries/execute.csv.erb:"
75
- @file_format.should parse_line(line).as(:failure).and_capture(:line => 3,
79
+ subject.should parse_line(line).as(:failure).and_capture(:line => 3,
76
80
  :error => 'ActionView::Template::Error',
77
81
  :message => "undefined local variable or method `field' for #<Class>",
78
82
  :file => '/Users/willem/Code/warehouse/app/views/queries/execute.csv.erb')
@@ -80,6 +84,8 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
80
84
  end
81
85
 
82
86
  describe '#parse_io' do
87
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
88
+
83
89
  it "should parse a successful request correctly" do
84
90
  log = <<-EOLOG
85
91
  Started GET "/" for 127.0.0.1 at Fri Mar 19 06:40:41 -0700 2010
@@ -90,12 +96,9 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
90
96
  Completed 200 OK in 170ms (Views: 78.4ms | ActiveRecord: 48.2ms)
91
97
  EOLOG
92
98
 
93
- request_counter.should_receive(:hit!).once
99
+ log_parser.should_receive(:handle_request).once
94
100
  log_parser.should_not_receive(:warn)
95
-
96
- log_parser.parse_io(StringIO.new(log)) do |request|
97
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails3::Request) && request.completed?
98
- end
101
+ log_parser.parse_string(log)
99
102
  end
100
103
 
101
104
  it "should parse an unroutable request correctly" do
@@ -109,12 +112,9 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
109
112
 
110
113
  EOLOG
111
114
 
112
- request_counter.should_receive(:hit!).once
115
+ log_parser.should_receive(:handle_request).once
113
116
  log_parser.should_not_receive(:warn)
114
-
115
- log_parser.parse_io(StringIO.new(log)) do |request|
116
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails3::Request) && request.completed?
117
- end
117
+ log_parser.parse_string(log)
118
118
  end
119
119
 
120
120
  it "should parse a failing request correctly" do
@@ -141,12 +141,9 @@ describe RequestLogAnalyzer::FileFormat::Rails3 do
141
141
 
142
142
  EOLOG
143
143
 
144
- request_counter.should_receive(:hit!).once
144
+ log_parser.should_receive(:handle_request).once
145
145
  log_parser.should_not_receive(:warn)
146
-
147
- log_parser.parse_io(StringIO.new(log)) do |request|
148
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails3::Request) && request.completed?
149
- end
146
+ log_parser.parse_string(log)
150
147
  end
151
148
  end
152
149
  end
@@ -5,186 +5,170 @@ describe RequestLogAnalyzer::FileFormat::Rails do
5
5
  describe '.create' do
6
6
 
7
7
  context 'without providing a lines argument' do
8
- before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails) }
8
+ subject { RequestLogAnalyzer::FileFormat::Rails.create }
9
9
 
10
- it "should create a valid file format" do
11
- @rails.should be_valid
12
- end
10
+ it { should be_well_formed }
11
+ it { should have(11).report_trackers }
13
12
 
14
- it "should parse the production lines" do
15
- production_rails = RequestLogAnalyzer::FileFormat.load(:rails, 'production')
16
- @rails.line_definitions.should == production_rails.line_definitions
13
+ it "should parse the lines in the production set" do
14
+ subject.line_definitions.should == RequestLogAnalyzer::FileFormat.load(:rails, 'production').line_definitions
17
15
  end
18
16
  end
19
17
 
20
18
  context 'using a comma separated list of lines as argument' do
21
- before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails, 'minimal,failure') }
22
-
23
- it "should return a valid language" do
24
- @rails.should be_valid
25
- end
19
+ subject { RequestLogAnalyzer::FileFormat.load(:rails, 'minimal,failure') }
26
20
 
27
- it "should at least parse :processing and :completed lines" do
28
- @rails.line_definitions.should include(:processing, :completed, :failure)
29
- end
21
+ it { should be_well_formed }
22
+ it { should have(10).report_trackers }
23
+
24
+ it { should have_line_definition(:processing) }
25
+ it { should have_line_definition(:completed) }
26
+ it { should have_line_definition(:failure) }
30
27
  end
31
28
 
32
29
  RequestLogAnalyzer::FileFormat::Rails::LINE_COLLECTIONS.keys.each do |constant|
33
30
 
34
31
  context "using the '#{constant}' line collection constant" do
35
- before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails, constant) }
32
+ subject { RequestLogAnalyzer::FileFormat.load(:rails, constant) }
36
33
 
37
- it "should return a valid language" do
38
- @rails.should be_valid
39
- end
34
+ it { should be_well_formed }
35
+ it { should have_at_least(9).report_trackers }
40
36
 
41
- it "should at least parse :processing and :completed lines" do
42
- @rails.line_definitions.should include(:processing, :completed)
43
- end
37
+ it { should have_line_definition(:processing) }
38
+ it { should have_line_definition(:completed) }
44
39
  end
45
40
  end
46
41
  end
42
+
43
+ subject { RequestLogAnalyzer::FileFormat.load(:rails, :all) }
47
44
 
48
45
  describe '#parse_line' do
49
- before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails, :all) }
50
46
 
51
47
  {'with prefix' => 'LINE PREFIX: ', 'without prefix' => '' }.each do |context, prefix|
52
48
  context context do
53
49
  it "should parse a :processing line correctly" do
54
50
  line = prefix + 'Processing PeopleController#index (for 1.1.1.1 at 2008-08-14 21:16:30) [GET]'
55
- @rails.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '1.1.1.1')
51
+ subject.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '1.1.1.1')
56
52
  end
57
53
 
58
54
  it "should parse a :processing line correctly when it contains ipv6 localhost address" do
59
55
  line = prefix + 'Processing PeopleController#index (for ::1 at 2008-08-14 21:16:30) [GET]'
60
- @rails.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '::1')
56
+ subject.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '::1')
61
57
  end
62
58
 
63
59
  it "should parse a :processing line correctly when it contains ipv6 address" do
64
60
  line = prefix + 'Processing PeopleController#index (for 3ffe:1900:4545:3:200:f8ff:fe21:67cf at 2008-08-14 21:16:30) [GET]'
65
- @rails.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '3ffe:1900:4545:3:200:f8ff:fe21:67cf')
61
+ subject.should parse_line(line).as(:processing).and_capture(:controller => 'PeopleController', :action => 'index', :timestamp => 20080814211630, :method => 'GET', :ip => '3ffe:1900:4545:3:200:f8ff:fe21:67cf')
66
62
  end
67
63
 
68
64
  it "should parse a Rails 2.1 style :completed line correctly" do
69
65
  line = prefix + 'Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://demo.nu/employees]'
70
- @rails.should parse_line(line).as(:completed).and_capture(:duration => 0.21665, :db => 0.0, :view => 0.00926, :status => 200, :url => 'http://demo.nu/employees')
66
+ subject.should parse_line(line).as(:completed).and_capture(:duration => 0.21665, :db => 0.0, :view => 0.00926, :status => 200, :url => 'http://demo.nu/employees')
71
67
  end
72
68
 
73
69
  it "should parse a Rails 2.2 style :completed line correctly" do
74
70
  line = prefix + 'Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]'
75
- @rails.should parse_line(line).as(:completed).and_capture(:duration => 0.614, :db => 0.031, :view => 0.120, :status => 200, :url => 'http://floorplanner.local/demo')
71
+ subject.should parse_line(line).as(:completed).and_capture(:duration => 0.614, :db => 0.031, :view => 0.120, :status => 200, :url => 'http://floorplanner.local/demo')
76
72
  end
77
73
 
78
74
  it "should parse a Rails 2.2 style :completed line correctly when AR is disabled" do
79
75
  line = prefix + 'Completed in 597ms (View: 298 | 200 OK [http://shapado.com]'
80
- @rails.should parse_line(line).as(:completed).and_capture(:duration => 0.597, :db => nil, :view => 0.298, :status => 200, :url => 'http://shapado.com')
76
+ subject.should parse_line(line).as(:completed).and_capture(:duration => 0.597, :db => nil, :view => 0.298, :status => 200, :url => 'http://shapado.com')
81
77
  end
82
78
 
83
79
  it "should parse a Rails 2.2 style :completed line without view" do
84
80
  line = prefix + "Completed in 148ms (DB: 0) | 302 Found [http://iwp-sod.hargray.org/login]"
85
- @rails.should parse_line(line).as(:completed).and_capture(:duration => 0.148, :db => 0.0, :view => nil, :status => 302, :url => 'http://iwp-sod.hargray.org/login')
81
+ subject.should parse_line(line).as(:completed).and_capture(:duration => 0.148, :db => 0.0, :view => nil, :status => 302, :url => 'http://iwp-sod.hargray.org/login')
86
82
  end
87
83
 
88
84
  it "should parse a :failure line with exception correctly" do
89
85
  line = prefix + "NoMethodError (undefined method `update_domain_account' for nil:NilClass):"
90
- @rails.should parse_line(line).as(:failure).and_capture(:error => 'NoMethodError', :message => "undefined method `update_domain_account' for nil:NilClass")
86
+ subject.should parse_line(line).as(:failure).and_capture(:error => 'NoMethodError', :message => "undefined method `update_domain_account' for nil:NilClass")
91
87
  end
92
88
 
93
89
  it "should parse a :cache_hit line correctly with an filter instance reference" do
94
90
  line = prefix + '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.'
95
- @rails.should parse_line(line).as(:cache_hit)
91
+ subject.should parse_line(line).as(:cache_hit)
96
92
  end
97
93
 
98
94
  it "should parse a :cache_hit line correctly with an proc instance reference" do
99
95
  line = prefix + 'Filter chain halted as [#<ActionController::Filters::AroundFilter:0x2a9a923e38 @method=#<Proc:0x0000002a9818b3f8@/usr/local/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/caching/actions.rb:64>, @kind=:filter, @identifier=nil, @options={:unless=>nil, :if=>nil, :only=>#<Set: {"show"}>}>] did_not_yield.'
100
- @rails.should parse_line(line).as(:cache_hit)
96
+ subject.should parse_line(line).as(:cache_hit)
101
97
  end
102
98
 
103
99
 
104
100
  it "should parse a :parameters line correctly" do
105
101
  line = prefix + ' Parameters: {"action"=>"cached", "controller"=>"cached"}'
106
- @rails.should parse_line(line).as(:parameters).and_capture(:params => {:action => 'cached', :controller => 'cached'})
102
+ subject.should parse_line(line).as(:parameters).and_capture(:params => {:action => 'cached', :controller => 'cached'})
107
103
  end
108
104
 
109
105
  it "should parse a :rendered line correctly" do
110
106
  line = prefix + 'Rendered layouts/_footer (2.9ms)'
111
- @rails.should parse_line(line).as(:rendered).and_capture(:render_file => 'layouts/_footer', :render_duration => 0.0029)
107
+ subject.should parse_line(line).as(:rendered).and_capture(:render_file => 'layouts/_footer', :render_duration => 0.0029)
112
108
  end
113
109
 
114
110
  it "should parse a :query_executed line with colors" do
115
111
  line = prefix + ' User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) '
116
- @rails.should parse_line(line).as(:query_executed).and_capture(:query_class => 'User', :query_duration => 0.0004, :query_sql => 'SELECT * FROM users WHERE (users.id = :int)')
112
+ subject.should parse_line(line).as(:query_executed).and_capture(:query_class => 'User', :query_duration => 0.0004, :query_sql => 'SELECT * FROM users WHERE (users.id = :int)')
117
113
  end
118
114
 
119
115
  it "should parse a :query_executed line without colors" do
120
116
  line = prefix + ' User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) '
121
- @rails.should parse_line(line).as(:query_executed).and_capture(:query_class => 'User', :query_duration => 0.0004, :query_sql => 'SELECT * FROM users WHERE (users.id = :int)')
117
+ subject.should parse_line(line).as(:query_executed).and_capture(:query_class => 'User', :query_duration => 0.0004, :query_sql => 'SELECT * FROM users WHERE (users.id = :int)')
122
118
  end
123
119
 
124
120
  it "should parse a :query_cached line with colors" do
125
121
  line = prefix + ' CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) '
126
- @rails.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
122
+ subject.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
127
123
  end
128
124
 
129
125
  it "should parse a :query_cached line without colors" do
130
126
  line = prefix + ' CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) '
131
- @rails.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
127
+ subject.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
132
128
  end
133
129
 
134
130
  it "should not parse an unsupported line" do
135
131
  line = prefix + 'nonsense line that should not be parsed as anything'
136
- @rails.should_not parse_line(line)
132
+ subject.should_not parse_line(line)
137
133
  end
138
134
  end
139
135
  end
140
136
  end
141
137
 
142
138
  describe '#parse_io' do
143
- before(:each) do
144
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(
145
- RequestLogAnalyzer::FileFormat.load(:rails), :parse_strategy => 'cautious')
146
- end
139
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject, :parse_strategy => 'cautious') }
147
140
 
148
141
  it "should parse a Rails 2.1 style log and find valid Rails requests without warnings" do
149
- request_counter.should_receive(:hit!).exactly(4).times
150
- @log_parser.should_not_receive(:warn)
151
-
152
- @log_parser.parse_file(log_fixture(:rails_1x)) do |request|
153
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
154
- end
142
+ log_parser.should_receive(:handle_request).exactly(4).times
143
+ log_parser.should_not_receive(:warn)
144
+ log_parser.parse_file(log_fixture(:rails_1x))\
155
145
  end
156
146
 
157
147
  it "should parse a Rails 2.2 style log and find valid Rails requests without warnings" do
158
- request_counter.should_receive(:hit!).once
159
- @log_parser.should_not_receive(:warn)
160
-
161
- @log_parser.parse_file(log_fixture(:rails_22)) do |request|
162
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
163
- end
148
+ log_parser.should_receive(:handle_request).once
149
+ log_parser.should_not_receive(:warn)
150
+ log_parser.parse_file(log_fixture(:rails_22))
164
151
  end
165
152
 
166
153
  it "should parse a Rails SyslogLogger file with prefix and find valid requests without warnings" do
167
- request_counter.should_receive(:hit!).once
168
- @log_parser.should_not_receive(:warn)
169
-
170
- @log_parser.parse_file(log_fixture(:syslog_1x)) do |request|
171
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
172
- end
154
+ log_parser.should_receive(:handle_request).once
155
+ log_parser.should_not_receive(:warn)
156
+ log_parser.parse_file(log_fixture(:syslog_1x))
173
157
  end
174
158
 
175
159
  it "should parse cached requests" do
176
- @log_parser.should_not_receive(:warn)
177
- @log_parser.parse_file(log_fixture(:rails_22_cached)) do |request|
160
+ log_parser.should_not_receive(:warn)
161
+ log_parser.parse_file(log_fixture(:rails_22_cached)) do |request|
178
162
  request.should be_completed
179
163
  request =~ :cache_hit
180
164
  end
181
165
  end
182
166
 
183
167
  it "should detect unordered requests in the logs" do
184
- @log_parser.should_not_receive(:handle_request)
185
- @log_parser.should_receive(:warn).with(:unclosed_request, anything).once
186
- @log_parser.should_receive(:warn).with(:no_current_request, anything).twice
187
- @log_parser.parse_file(log_fixture(:rails_unordered))
168
+ log_parser.should_not_receive(:handle_request)
169
+ log_parser.should_receive(:warn).with(:unclosed_request, anything).once
170
+ log_parser.should_receive(:warn).with(:no_current_request, anything).at_least(:twice)
171
+ log_parser.parse_file(log_fixture(:rails_unordered))
188
172
  end
189
173
  end
190
174
  end
@@ -2,45 +2,46 @@ require 'spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::FileFormat::W3c do
4
4
 
5
- before(:each) do
6
- @file_format = RequestLogAnalyzer::FileFormat.load(:w3c)
7
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
8
- # date time c-ip cs-username s-ip s-port cs-method cs-uri-stem cs-uri-query sc-status sc-bytes cs-bytes time-taken cs(User-Agent) cs(Referrer)
9
- @sample = '2002-05-24 20:18:01 172.224.24.114 - 206.73.118.24 80 GET /Default.htm - 200 7930 248 31 Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server) http://64.224.24.114/'
5
+ subject { RequestLogAnalyzer::FileFormat.load(:w3c) }
6
+
7
+ it { should be_well_formed }
8
+ it { should have_line_definition(:access).capturing(:timestamp, :remote_ip, :username, :local_ip, :port,
9
+ :method, :path, :http_status, :bytes_sent, :bytes_received, :duration, :user_agent, :referer) }
10
+
11
+ it { should have(10).report_trackers }
12
+
13
+ let(:sample1) { '2002-05-24 20:18:01 172.224.24.114 - 206.73.118.24 80 GET /Default.htm - 200 7930 248 31 Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server) http://64.224.24.114/' }
14
+ let(:irrelevant) { '#Software: Microsoft Internet Information Services 6.0' }
15
+
16
+ describe '#parse_line' do
17
+ it { should parse_line(sample1, 'an access line').and_capture(
18
+ :timestamp => 20020524201801,
19
+ :remote_ip => "172.224.24.114",
20
+ :username => nil,
21
+ :local_ip => "206.73.118.24",
22
+ :port => 80,
23
+ :method => 'GET',
24
+ :path => '/Default.htm',
25
+ :http_status => 200,
26
+ :bytes_sent => 7930,
27
+ :bytes_received => 248,
28
+ :duration => 0.031,
29
+ :user_agent => 'Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server)',
30
+ :referer => 'http://64.224.24.114/')
31
+ }
32
+
33
+ it { should_not parse_line(irrelevant, 'an irrelevant line') }
34
+ it { should_not parse_line('nonsense', 'a nonsense line') }
10
35
  end
11
-
12
- it "should be a valid file format" do
13
- @file_format.should be_valid
14
- end
15
-
16
- it "should parse access lines and capture all of its fields" do
17
- @file_format.should have_line_definition(:access).capturing(:timestamp, :remote_ip, :username, :local_ip, :port, :method, :path, :http_status, :bytes_sent, :bytes_received, :duration, :user_agent, :referer)
18
- end
19
-
20
- it "should match the sample line" do
21
- @file_format.parse_line(@sample).should include(:line_definition, :captures)
22
- end
23
-
24
- it "should not match a nonsense line" do
25
- @file_format.parse_line('#Software: Microsoft Internet Information Services 6.0').should be_nil
26
- end
27
-
28
- it "should parse and convert the sample fields correctly" do
29
- @log_parser.parse_io(StringIO.new(@sample)) do |request|
30
- request[:timestamp].should == 20020524201801
31
- request[:remote_ip].should == "172.224.24.114"
32
- request[:username].should == nil
33
- request[:local_ip].should == "206.73.118.24"
34
- request[:port].should == 80
35
- request[:method].should == 'GET'
36
- request[:path].should == '/Default.htm'
37
- request[:http_status].should == 200
38
- request[:bytes_sent].should == 7930
39
- request[:bytes_received].should == 248
40
- request[:duration].should == 0.031
41
- request[:user_agent].should == 'Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+2000+Server)'
42
- request[:referer].should == 'http://64.224.24.114/'
36
+
37
+ describe '#parse_io' do
38
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
39
+ let(:snippet) { log_snippet(irrelevant, sample1, sample1) }
40
+
41
+ it "should parse a snippet successully without warnings" do
42
+ log_parser.should_receive(:handle_request).twice
43
+ log_parser.should_not_receive(:warn)
44
+ log_parser.parse_io(snippet)
43
45
  end
44
46
  end
45
-
46
- end
47
+ end