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,41 +1,39 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe RequestLogAnalyzer::FileFormat::DelayedJob do
3
+ describe RequestLogAnalyzer::FileFormat::DelayedJob2 do
4
4
 
5
- it "should be a valid file format" do
6
- RequestLogAnalyzer::FileFormat.load(:delayed_job).should be_valid
7
- end
5
+ subject { RequestLogAnalyzer::FileFormat.load(:delayed_job2) }
8
6
 
7
+ it { should be_well_formed }
8
+ it { should have_line_definition(:job_lock).capturing(:timestamp, :job, :host, :pid) }
9
+ it { should have_line_definition(:job_completed).capturing(:timestamp, :duration, :host, :pid) }
10
+ it { should have(4).report_trackers }
11
+
9
12
  describe '#parse_line' do
10
13
 
11
- before(:each) do
12
- @file_format = RequestLogAnalyzer::FileFormat.load(:delayed_job2)
13
- end
14
+ let(:job_lock_sample1) { "2010-05-17T17:37:34+0000: * [Worker(delayed_job host:hostname.co.uk pid:11888)] acquired lock on S3FileJob" }
15
+ let(:job_lock_sample2) { "2010-05-17T17:37:34+0000: * [Worker(delayed_job.0 host:hostname.co.uk pid:11888)] acquired lock on S3FileJob" }
16
+ let(:job_completed_sample) { '2010-05-17T17:37:35+0000: * [JOB] delayed_job host:hostname.co.uk pid:11888 completed after 1.0676' }
17
+ let(:starting_sample) { '2010-05-17T17:36:44+0000: *** Starting job worker delayed_job host:hostname.co.uk pid:11888' }
18
+ let(:summary_sample) { '3 jobs processed at 0.3163 j/s, 0 failed ...' }
19
+
20
+ it { should parse_line(job_lock_sample1, 'with a single worker').as(:job_lock).and_capture(
21
+ :timestamp => 20100517173734, :job => 'S3FileJob', :host => 'hostname.co.uk', :pid => 11888) }
14
22
 
15
- it "should parse a :job_lock line correctly" do
16
- line = "2010-05-17T17:37:34+0000: * [Worker(delayed_job host:hostname.co.uk pid:11888)] acquired lock on S3FileJob"
17
- @file_format.should parse_line(line).as(:job_lock).and_capture(:timestamp => 20100517173734,
18
- :job => 'S3FileJob', :host => 'hostname.co.uk', :pid => 11888)
19
- end
23
+ it { should parse_line(job_lock_sample2, 'with multiple workers').as(:job_lock).and_capture(
24
+ :timestamp => 20100517173734, :job => 'S3FileJob', :host => 'hostname.co.uk', :pid => 11888) }
20
25
 
21
- it "should parse a :job_lock line correctly when the worker is one of many" do
22
- line = "2010-05-17T17:37:34+0000: * [Worker(delayed_job.0 host:hostname.co.uk pid:11888)] acquired lock on S3FileJob"
23
- @file_format.should parse_line(line).as(:job_lock).and_capture(:timestamp => 20100517173734,
24
- :job => 'S3FileJob', :host => 'hostname.co.uk', :pid => 11888)
25
- end
26
+ it { should parse_line(job_completed_sample).as(:job_completed).and_capture(:timestamp => 20100517173735,
27
+ :duration => 1.0676, :host => 'hostname.co.uk', :pid => 11888) }
26
28
 
27
- it "should parse a :job_completed line correctly" do
28
- line = '2010-05-17T17:37:35+0000: * [JOB] delayed_job host:hostname.co.uk pid:11888 completed after 1.0676'
29
- @file_format.should parse_line(line).as(:job_completed).and_capture(:timestamp => 20100517173735,
30
- :duration => 1.0676, :host => 'hostname.co.uk', :pid => 11888)
31
- end
29
+ it { should_not parse_line(starting_sample, 'a starting line') }
30
+ it { should_not parse_line(summary_sample, 'a summary line') }
31
+ it { should_not parse_line('nonsense', 'a nonsense line') }
32
32
  end
33
33
 
34
34
  describe '#parse_io' do
35
- before(:each) do
36
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:delayed_job2))
37
- end
38
-
35
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
36
+
39
37
  it "should parse a batch of completed jobs without warnings" do
40
38
  fragment = <<-EOLOG
41
39
  2010-05-17T17:36:44+0000: *** Starting job worker delayed_job host:hostname.co.uk pid:11888
@@ -49,12 +47,9 @@ describe RequestLogAnalyzer::FileFormat::DelayedJob do
49
47
  2010-05-19T11:47:26+0000: Exiting...
50
48
  EOLOG
51
49
 
52
- request_counter.should_receive(:hit!).exactly(3).times
53
- @log_parser.should_not_receive(:warn)
54
-
55
- @log_parser.parse_io(StringIO.new(fragment)) do |request|
56
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::DelayedJob2::Request)
57
- end
50
+ log_parser.should_receive(:handle_request).exactly(3).times
51
+ log_parser.should_not_receive(:warn)
52
+ log_parser.parse_string(fragment)
58
53
  end
59
54
  end
60
55
  end
@@ -1,83 +1,64 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::FileFormat::DelayedJob do
4
+
5
+ subject { RequestLogAnalyzer::FileFormat.load(:delayed_job) }
4
6
 
5
- it "should be a valid file format" do
6
- RequestLogAnalyzer::FileFormat.load(:delayed_job).should be_valid
7
- end
7
+ it { should be_well_formed }
8
+ it { should have_line_definition(:job_lock).capturing(:job) }
9
+ it { should have_line_definition(:job_completed).capturing(:completed_job, :duration) }
10
+ it { should have_line_definition(:job_lock_failed).capturing(:locked_job) }
11
+ it { should have_line_definition(:job_failed).capturing(:failed_job, :attempts, :exception) }
12
+ it { should have(3).report_trackers }
8
13
 
9
14
  describe '#parse_line' do
10
- before(:each) do
11
- @file_format = RequestLogAnalyzer::FileFormat.load(:delayed_job)
12
- end
15
+ let(:job_lock_sample) { '* [JOB] acquiring lock on BackgroundJob::ThumbnailSaver' }
16
+ let(:job_completed_sample) { '* [JOB] BackgroundJob::ThumbnailSaver completed after 0.7932' }
17
+ let(:job_lock_failed_sample) { '* [JOB] failed to acquire exclusive lock for BackgroundJob::ThumbnailSaver' }
18
+ let(:job_failed_sample) { "* [JOB] BackgroundJob::ThumbnailSaver failed with ActiveRecord::RecordNotFound: Couldn't find Design with ID=20413443 - 1 failed attempts" }
19
+ let(:summary_sample) { '1 jobs processed at 1.0834 j/s, 0 failed ...' }
13
20
 
14
- it "should parse a :job_lock line correctly" do
15
- line = "* [JOB] acquiring lock on BackgroundJob::ThumbnailSaver"
16
- @file_format.should parse_line(line).as(:job_lock).and_capture(:job => 'BackgroundJob::ThumbnailSaver')
17
- end
18
-
19
- it "should parse a :job_completed line correctly" do
20
- line = '* [JOB] BackgroundJob::ThumbnailSaver completed after 0.7932'
21
- @file_format.should parse_line(line).as(:job_completed).and_capture(
22
- :duration => 0.7932, :completed_job => 'BackgroundJob::ThumbnailSaver')
23
- end
24
-
25
- it "should pase a :job_failed line correctly" do
26
- line = "* [JOB] BackgroundJob::ThumbnailSaver failed with ActiveRecord::RecordNotFound: Couldn't find Design with ID=20413443 - 1 failed attempts"
27
- @file_format.should parse_line(line).as(:job_failed).and_capture(:attempts => 1,
28
- :failed_job => 'BackgroundJob::ThumbnailSaver', :exception => 'ActiveRecord::RecordNotFound')
29
- end
30
-
31
- it "should parse a failed job lock line correctly" do
32
- line = "* [JOB] failed to acquire exclusive lock for BackgroundJob::ThumbnailSaver"
33
- @file_format.should parse_line(line).as(:job_lock_failed).and_capture(:locked_job => 'BackgroundJob::ThumbnailSaver')
34
- end
35
-
36
- # it "should pase a :batch_completed line correctly" do
37
- # line = '1 jobs processed at 1.0834 j/s, 0 failed ...'
38
- # @file_format.should parse_line(line).as(:batch_completed).and_capture(
39
- # :mean_duration => 0.7932, :total_amount => 1, :failed_amount => 0)
40
- # end
21
+ it { should parse_line(job_lock_sample).as(:job_lock).and_capture(:job => 'BackgroundJob::ThumbnailSaver') }
22
+ it { should parse_line(job_completed_sample).as(:job_completed).and_capture(:duration => 0.7932, :completed_job => 'BackgroundJob::ThumbnailSaver') }
23
+ it { should parse_line(job_lock_failed_sample).as(:job_lock_failed).and_capture(:locked_job => 'BackgroundJob::ThumbnailSaver') }
24
+ it { should parse_line(job_failed_sample).as(:job_failed).and_capture(:attempts => 1, :failed_job => 'BackgroundJob::ThumbnailSaver', :exception => 'ActiveRecord::RecordNotFound') }
41
25
 
26
+ it { should_not parse_line(summary_sample, 'a summary line') }
27
+ it { should_not parse_line('nonsense', 'a nonsense line') }
42
28
  end
43
-
29
+
44
30
  describe '#parse_io' do
45
- before(:each) do
46
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:delayed_job))
47
- end
31
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
48
32
 
49
33
  it "should parse a batch of completed jobs without warnings" do
50
- fragment = "* [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
51
- * [JOB] BackgroundJob::ThumbnailSaver completed after 0.9114
52
- * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
53
- * [JOB] BackgroundJob::ThumbnailSaver completed after 0.9110
54
- 2 jobs processed at 1.0832 j/s, 0 failed ..."
55
-
56
- request_counter.should_receive(:hit!).exactly(2).times
57
- @log_parser.should_not_receive(:warn)
34
+ fragment = log_snippet(<<-EOLOG)
35
+ * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
36
+ * [JOB] BackgroundJob::ThumbnailSaver completed after 0.9114
37
+ * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
38
+ * [JOB] BackgroundJob::ThumbnailSaver completed after 0.9110
39
+ 2 jobs processed at 1.0832 j/s, 0 failed ...
40
+ EOLOG
58
41
 
59
- @log_parser.parse_io(StringIO.new(fragment)) do |request|
60
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::DelayedJob::Request)
61
- end
42
+ log_parser.should_receive(:handle_request).twice
43
+ log_parser.should_not_receive(:warn)
44
+ log_parser.parse_io(fragment)
62
45
  end
63
46
 
64
47
  it "should parse a batch with a failed job without warnings" do
65
- fragment = "* [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
66
- * [JOB] BackgroundJob::ThumbnailSaver completed after 1.0627
67
- * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
68
- * [JOB] BackgroundJob::ThumbnailSaver failed with ActiveRecord::RecordNotFound: Couldn't find Design with ID=20413443 - 3 failed attempts
69
- Couldn't find Design with ID=20413443
70
- * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
71
- * [JOB] failed to acquire exclusive lock for BackgroundJob::ThumbnailSaver
72
- 2 jobs processed at 1.4707 j/s, 1 failed ..."
48
+ fragment = log_snippet(<<-EOLOG)
49
+ * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
50
+ * [JOB] BackgroundJob::ThumbnailSaver completed after 1.0627
51
+ * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
52
+ * [JOB] BackgroundJob::ThumbnailSaver failed with ActiveRecord::RecordNotFound: Couldn't find Design with ID=20413443 - 3 failed attempts
53
+ Couldn't find Design with ID=20413443
54
+ * [JOB] acquiring lock on BackgroundJob::ThumbnailSaver
55
+ * [JOB] failed to acquire exclusive lock for BackgroundJob::ThumbnailSaver
56
+ 2 jobs processed at 1.4707 j/s, 1 failed ...
57
+ EOLOG
73
58
 
74
- request_counter.should_receive(:hit!).exactly(3).times
75
- @log_parser.should_not_receive(:warn)
76
-
77
- @log_parser.parse_io(StringIO.new(fragment)) do |request|
78
- request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::DelayedJob::Request)
79
- end
59
+ log_parser.should_receive(:handle_request).exactly(3).times
60
+ log_parser.should_not_receive(:warn)
61
+ log_parser.parse_io(fragment)
80
62
  end
81
63
  end
82
64
  end
83
-
@@ -2,83 +2,81 @@ require 'spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::FileFormat::Haproxy do
4
4
 
5
- before(:each) do
6
- @file_format = RequestLogAnalyzer::FileFormat.load(:haproxy)
7
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
8
- @sample1 = 'Feb 6 12:14:14 localhost haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} {} "GET /index.html HTTP/1.1"'
9
- @sample2 = 'haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http px-http/<NOSRV> -1/-1/-1/-1/+50001 408 +2750 - - cR-- 2/2/2/0/+2 0/0 ""'
10
- end
5
+ subject { RequestLogAnalyzer::FileFormat.load(:haproxy) }
6
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
11
7
 
12
- it "should be a valid file format" do
13
- @file_format.should be_valid
14
- end
8
+ it { should be_well_formed }
15
9
 
16
- it "should parse access lines and capture all of its fields" do
17
- @file_format.should have_line_definition(:haproxy).capturing(:client_ip, :accept_date, :frontend_name, :backend_name, :server_name, :tq, :tw, :tc, :tr, :tt, :status_code, :bytes_read, :captured_request_cookie, :captured_response_cookie, :termination_event_code, :terminated_session_state, :clientside_persistence_cookie, :serverside_persistence_cookie, :actconn, :feconn, :beconn, :srv_conn, :retries, :srv_queue, :backend_queue, :captured_request_headers, :captured_response_headers, :http_request)
18
- end
10
+ it { should have_line_definition(:haproxy13).capturing(:client_ip, :timestamp, :frontend_name, :backend_name, :server_name, :tq, :tw, :tc, :tr, :tt, :status_code, :bytes_read, :captured_request_cookie, :captured_response_cookie, :termination_event_code, :terminated_session_state, :clientside_persistence_cookie, :serverside_persistence_cookie, :actconn, :feconn, :beconn, :srv_conn, :retries, :srv_queue, :backend_queue, :captured_request_headers, :captured_response_headers, :http_request) }
11
+ it { should have_line_definition(:haproxy12).capturing(:client_ip, :timestamp, :frontend_name, :server_name, :tq, :tw, :tc, :tr, :tt, :status_code, :bytes_read, :captured_request_cookie, :captured_response_cookie, :termination_event_code, :terminated_session_state, :clientside_persistence_cookie, :serverside_persistence_cookie, :srv_conn, :listener_conn, :process_conn, :srv_queue, :backend_queue, :captured_request_headers, :captured_response_headers, :http_request) }
12
+ it { should have_line_definition(:haproxy11).capturing(:client_ip, :timestamp, :frontend_name, :server_name, :tq, :tc, :tr, :tt, :status_code, :bytes_read, :captured_request_cookie, :captured_response_cookie, :termination_event_code, :terminated_session_state, :clientside_persistence_cookie, :serverside_persistence_cookie, :listener_conn, :process_conn, :captured_request_headers, :captured_response_headers, :http_request) }
19
13
 
20
- it "should match the sample line" do
21
- @file_format.parse_line(@sample1).should include(:line_definition, :captures)
22
- end
14
+ it { should have(14).report_trackers }
23
15
 
24
- it "should not match a nonsense line" do
25
- @file_format.parse_line('dsadasdas dsaadsads dsaadsads').should be_nil
26
- end
16
+ let(:sample_haproxy13) { 'Feb 6 12:14:14 localhost haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} {} "GET /index.html HTTP/1.1"' }
17
+ let(:sample_haproxy12) { 'Mar 15 06:36:49 localhost haproxy[9367]: 127.0.0.1:38990 [15/Mar/2011:06:36:45.103] as-proxy mc-search-2 0/0/0/730/731 200 29404 - - --NN 2/54/54 0/0 {66.249.68.216} {} "GET /neighbor/26014153 HTTP/1.0" ' }
18
+ let(:sample_haproxy11) { 'haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17] relais-http Srv1 9/7/14/30 502 243 - - PH-- 2/3 "GET /cgi-bin/bug.cgi? HTTP/1.0"' }
19
+ let(:sample_errors) { 'haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http px-http/<NOSRV> -1/-1/-1/-1/+50001 408 +2750 - - cR-- 2/2/2/0/+2 0/0 ""' }
27
20
 
28
- it "should parse and convert the sample fields correctly" do
29
- @log_parser.parse_io(StringIO.new(@sample1)) do |request|
30
- request[:client_ip].should == '10.0.1.2'
31
- request[:accept_date].should == 20090206121414
32
- request[:frontend_name].should == 'http-in'
33
- request[:backend_name].should == 'static'
34
- request[:server_name].should == 'srv1'
35
- request[:tq].should == 0.010
36
- request[:tw].should == 0.000
37
- request[:tc].should == 0.030
38
- request[:tr].should == 0.069
39
- request[:tt].should == 0.109
40
- request[:status_code].should == 200
41
- request[:bytes_read].should == 2750
42
- request[:captured_request_cookie].should == nil
43
- request[:captured_response_cookie].should == nil
44
- request[:termination_event_code].should == nil
45
- request[:terminated_session_state].should == nil
46
- request[:clientside_persistence_cookie].should == nil
47
- request[:serverside_persistence_cookie].should == nil
48
- request[:actconn].should == 1
49
- request[:feconn].should == 1
50
- request[:beconn].should == 1
51
- request[:srv_conn].should == 1
52
- request[:retries].should == 0
53
- request[:srv_queue].should == 0
54
- request[:backend_queue].should == 0
55
- request[:captured_request_headers].should == '{1wt.eu}'
56
- request[:captured_response_headers].should == nil
57
- request[:http_request].should == 'GET /index.html HTTP/1.1'
58
- end
59
- end
21
+ describe '#parse_line' do
22
+ it { should parse_line(sample_haproxy13, 'an haproxy 1.3 access line').and_capture(
23
+ :client_ip => '10.0.1.2', :tq => 0.010, :captured_request_cookie => nil,
24
+ :timestamp => 20090206121414, :tw => 0.000, :captured_response_cookie => nil,
25
+ :frontend_name => 'http-in', :tc => 0.030, :clientside_persistence_cookie => nil,
26
+ :backend_name => 'static', :tr => 0.069, :serverside_persistence_cookie => nil,
27
+ :server_name => 'srv1', :tt => 0.109, :termination_event_code => nil,
28
+ :status_code => 200, :actconn => 1, :terminated_session_state => nil,
29
+ :bytes_read => 2750, :feconn => 1, :captured_request_headers => '{1wt.eu}',
30
+ :backend_queue => 0, :beconn => 1, :captured_response_headers => nil,
31
+ :retries => 0, :srv_conn => 1, :srv_queue => 0,
32
+ :http_request => 'GET /index.html HTTP/1.1')
33
+ }
34
+
35
+ it { should parse_line(sample_haproxy12, 'an haproxy 1.2 access line').and_capture(
36
+ :client_ip => '127.0.0.1', :tq => 0.000, :captured_request_cookie => nil,
37
+ :timestamp => 20110315063645, :tw => 0.000, :captured_response_cookie => nil,
38
+ :frontend_name => 'as-proxy', :tc => 0.000, :clientside_persistence_cookie => 'N',
39
+ :server_name => 'mc-search-2',:tr => 0.730, :serverside_persistence_cookie => 'N',
40
+ :status_code => 200, :tt => 0.731, :termination_event_code => nil,
41
+ :bytes_read => 29404, :listener_conn => 54, :terminated_session_state => nil,
42
+ :backend_queue => 0, :process_conn => 54, :captured_request_headers => '{66.249.68.216}',
43
+ :srv_queue => 0, :srv_conn => 2, :captured_response_headers => nil,
44
+ :http_request => 'GET /neighbor/26014153 HTTP/1.0')
45
+ }
60
46
 
61
- it "should parse and convert edge case sample fields correctly" do
62
- @log_parser.parse_io(StringIO.new(@sample2)) do |request|
63
- request[:accept_date].should == 20031015151906
64
- request[:server_name].should == '<NOSRV>'
65
- request[:tq].should == nil
66
- request[:tw].should == nil
67
- request[:tc].should == nil
68
- request[:tr].should == nil
69
- request[:tt].should == 50.001
70
- request[:bytes_read].should == 2750
71
- request[:captured_request_cookie].should == nil
72
- request[:captured_response_cookie].should == nil
73
- request[:termination_event_code].should == 'c'
74
- request[:terminated_session_state].should == 'R'
75
- request[:clientside_persistence_cookie].should == nil
76
- request[:serverside_persistence_cookie].should == nil
77
- request[:retries].should == 2
78
- request[:captured_request_headers].should == nil
79
- request[:captured_response_headers].should == nil
80
- request[:http_request].should == nil
47
+ it { should parse_line(sample_haproxy11, 'an haproxy 1.1 access line').and_capture(
48
+ :client_ip => '127.0.0.1', :tq => 0.009, :captured_request_cookie => nil,
49
+ :timestamp => 20031015083217, :tc => 0.007, :captured_response_cookie => nil,
50
+ :frontend_name => 'relais-http',:tr => 0.014, :clientside_persistence_cookie => nil,
51
+ :server_name => 'Srv1', :tt => 0.030, :serverside_persistence_cookie => nil,
52
+ :status_code => 502, :listener_conn => 2,:termination_event_code => 'P',
53
+ :bytes_read => 243, :process_conn => 3, :terminated_session_state => 'H',
54
+ :captured_request_headers => nil, :captured_response_headers => nil,
55
+ :http_request => nil)
56
+ }
57
+
58
+ it { should parse_line(sample_errors, 'a failed access line').and_capture(
59
+ :timestamp => 20031015151906, :tq => nil, :captured_request_cookie => nil,
60
+ :server_name => '<NOSRV>', :tw => nil, :captured_response_cookie => nil,
61
+ :bytes_read => 2750, :tc => nil, :clientside_persistence_cookie => nil,
62
+ :retries => 2, :tr => nil, :serverside_persistence_cookie => nil,
63
+ :http_request => nil, :tt => 50.001, :termination_event_code => 'c',
64
+ :terminated_session_state => 'R',
65
+ :captured_request_headers => nil,
66
+ :captured_response_headers => nil)
67
+ }
68
+
69
+ it { should_not parse_line('nonsense') }
70
+ end
71
+
72
+ describe '#parse_io' do
73
+ let(:log_parser) { RequestLogAnalyzer::Source::LogParser.new(subject) }
74
+ let(:snippet) { log_snippet(sample_haproxy13, sample_haproxy12, sample_haproxy11, sample_errors, 'nonsense') }
75
+
76
+ it "should parse a log snippet without warnings" do
77
+ log_parser.should_receive(:handle_request).exactly(4).times
78
+ log_parser.should_not_receive(:warn)
79
+ log_parser.parse_io(snippet)
81
80
  end
82
81
  end
83
-
84
82
  end
@@ -2,74 +2,67 @@ require 'spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::LineDefinition do
4
4
 
5
- before(:each) do
6
- @line_definition = RequestLogAnalyzer::LineDefinition.new(:test, {
5
+ subject { RequestLogAnalyzer::LineDefinition.new(:test, {
7
6
  :teaser => /Testing /,
8
7
  :regexp => /Testing (\w+), tries\: (\d+)/,
9
8
  :captures => [{ :name => :what, :type => :string }, { :name => :tries, :type => :integer }]
10
9
  })
11
- end
10
+ }
12
11
 
13
12
  describe '#matches' do
14
13
 
15
14
  it "should return false on an unmatching line" do
16
- @line_definition.matches("nonmatching").should be_false
15
+ subject.matches("nonmatching").should be_false
17
16
  end
18
17
 
19
18
  it "should return false when only the teaser matches" do
20
- @line_definition.matches("Testing LineDefinition").should be_false
19
+ subject.matches("Testing LineDefinition").should be_false
21
20
  end
22
21
 
23
22
  it "should parse a line and capture the expected values" do
24
- @line_definition.matches("Testing LineDefinition, tries: 123").should == {:line_definition => @line_definition, :captures => ['LineDefinition', '123'] }
23
+ subject.matches("Testing LineDefinition, tries: 123").should == {:line_definition => subject, :captures => ['LineDefinition', '123'] }
25
24
  end
26
25
 
27
26
  it "should know which names it can capture" do
28
- @line_definition.captures?(:what).should be_true
29
- @line_definition.captures?(:tries).should be_true
30
- @line_definition.captures?(:bogus).should be_false
27
+ subject.captures?(:what).should be_true
28
+ subject.captures?(:tries).should be_true
29
+ subject.captures?(:bogus).should be_false
31
30
  end
32
-
33
31
  end
34
32
 
35
33
  describe '#convert_captured_values' do
36
-
37
- before(:each) do
38
- @request = mock('request')
39
- @request.stub!(:convert_value).and_return('foo')
40
- end
34
+ let(:request) { mock('request', :convert_value => 'foo') }
41
35
 
42
36
  it "should call convert_value for every captured value" do
43
- @request.should_receive(:convert_value).twice
44
- @line_definition.convert_captured_values(['test', '123'], @request)
37
+ request.should_receive(:convert_value).twice
38
+ subject.convert_captured_values(['test', '123'], request)
45
39
  end
46
40
 
47
41
  it "should set the converted values" do
48
- @line_definition.convert_captured_values(['test', '123'], @request).should == {:what => 'foo', :tries => 'foo'}
42
+ subject.convert_captured_values(['test', '123'], request).should == {:what => 'foo', :tries => 'foo'}
49
43
  end
50
44
 
51
45
  context 'when using :provides option' do
52
- before(:each) do
53
- @ld = RequestLogAnalyzer::LineDefinition.new(:test, :regexp => /Hash\: (\{.+\})/,
54
- :captures => [{ :name => :hash, :type => :hash, :provides => {:bar => :string}}])
55
-
56
- @request = mock('request')
57
-
58
- @request.stub!(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
59
- @request.stub!(:convert_value).with('baz', anything).and_return('foo')
46
+
47
+ subject { RequestLogAnalyzer::LineDefinition.new(:test,
48
+ :regexp => /Hash\: (\{.+\})/,
49
+ :captures => [{ :name => :hash, :type => :hash, :provides => {:bar => :string}}])
50
+ }
51
+
52
+ before do
53
+ request.stub!(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
54
+ request.stub!(:convert_value).with('baz', anything).and_return('foo')
60
55
  end
61
56
 
62
57
  it "should call Request#convert_value for the initial hash and the value in the hash" do
63
- @request.should_receive(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
64
- @request.should_receive(:convert_value).with("baz", anything)
65
- @ld.convert_captured_values(["{:bar=>'baz'}"], @request)
58
+ request.should_receive(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
59
+ request.should_receive(:convert_value).with("baz", anything)
60
+ subject.convert_captured_values(["{:bar=>'baz'}"], request)
66
61
  end
67
62
 
68
- it "should set the provides fields" do
69
- # The captures field must be set and converted as well
70
- @ld.convert_captured_values(["{:bar=>'baz'}"], @request)[:bar].should eql('foo')
63
+ it "should return the converted hash" do
64
+ subject.convert_captured_values(["{:bar=>'baz'}"], request).should include(:bar => 'foo')
71
65
  end
72
66
  end
73
-
74
67
  end
75
68
  end