request-log-analyzer 1.3.5 → 1.4.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 (86) hide show
  1. data/LICENSE +3 -3
  2. data/README.rdoc +1 -1
  3. data/bin/request-log-analyzer +17 -14
  4. data/lib/cli/command_line_arguments.rb +51 -51
  5. data/lib/cli/database_console.rb +3 -3
  6. data/lib/cli/database_console_init.rb +4 -3
  7. data/lib/cli/progressbar.rb +10 -10
  8. data/lib/cli/tools.rb +3 -3
  9. data/lib/request_log_analyzer/aggregator/database_inserter.rb +13 -14
  10. data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
  11. data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
  12. data/lib/request_log_analyzer/aggregator.rb +11 -15
  13. data/lib/request_log_analyzer/controller.rb +162 -89
  14. data/lib/request_log_analyzer/database/base.rb +21 -21
  15. data/lib/request_log_analyzer/database/connection.rb +3 -3
  16. data/lib/request_log_analyzer/database/request.rb +22 -0
  17. data/lib/request_log_analyzer/database/source.rb +13 -0
  18. data/lib/request_log_analyzer/database/warning.rb +14 -0
  19. data/lib/request_log_analyzer/database.rb +28 -103
  20. data/lib/request_log_analyzer/file_format/amazon_s3.rb +17 -18
  21. data/lib/request_log_analyzer/file_format/apache.rb +26 -27
  22. data/lib/request_log_analyzer/file_format/merb.rb +30 -13
  23. data/lib/request_log_analyzer/file_format/rack.rb +4 -4
  24. data/lib/request_log_analyzer/file_format/rails.rb +143 -73
  25. data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
  26. data/lib/request_log_analyzer/file_format.rb +16 -28
  27. data/lib/request_log_analyzer/filter/anonymize.rb +8 -7
  28. data/lib/request_log_analyzer/filter/field.rb +9 -9
  29. data/lib/request_log_analyzer/filter/timespan.rb +12 -10
  30. data/lib/request_log_analyzer/filter.rb +12 -16
  31. data/lib/request_log_analyzer/line_definition.rb +15 -14
  32. data/lib/request_log_analyzer/log_processor.rb +27 -29
  33. data/lib/request_log_analyzer/mailer.rb +15 -9
  34. data/lib/request_log_analyzer/output/fixed_width.rb +40 -41
  35. data/lib/request_log_analyzer/output/html.rb +20 -20
  36. data/lib/request_log_analyzer/output.rb +53 -12
  37. data/lib/request_log_analyzer/request.rb +75 -68
  38. data/lib/request_log_analyzer/source/database_loader.rb +10 -14
  39. data/lib/request_log_analyzer/source/log_parser.rb +57 -50
  40. data/lib/request_log_analyzer/source.rb +10 -12
  41. data/lib/request_log_analyzer/tracker/duration.rb +39 -132
  42. data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
  43. data/lib/request_log_analyzer/tracker/hourly_spread.rb +21 -21
  44. data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
  45. data/lib/request_log_analyzer/tracker/traffic.rb +36 -116
  46. data/lib/request_log_analyzer/tracker.rb +139 -32
  47. data/lib/request_log_analyzer.rb +4 -4
  48. data/request-log-analyzer.gemspec +19 -15
  49. data/spec/database.yml +6 -0
  50. data/spec/fixtures/rails_22.log +1 -1
  51. data/spec/integration/command_line_usage_spec.rb +7 -1
  52. data/spec/lib/helpers.rb +7 -7
  53. data/spec/lib/macros.rb +3 -3
  54. data/spec/lib/matchers.rb +41 -27
  55. data/spec/lib/mocks.rb +15 -14
  56. data/spec/lib/testing_format.rb +9 -9
  57. data/spec/spec_helper.rb +6 -6
  58. data/spec/unit/aggregator/database_inserter_spec.rb +16 -16
  59. data/spec/unit/aggregator/summarizer_spec.rb +4 -4
  60. data/spec/unit/controller/controller_spec.rb +2 -2
  61. data/spec/unit/controller/log_processor_spec.rb +1 -1
  62. data/spec/unit/database/base_class_spec.rb +26 -33
  63. data/spec/unit/database/connection_spec.rb +3 -3
  64. data/spec/unit/database/database_spec.rb +33 -38
  65. data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
  66. data/spec/unit/file_format/apache_format_spec.rb +13 -13
  67. data/spec/unit/file_format/file_format_api_spec.rb +13 -13
  68. data/spec/unit/file_format/line_definition_spec.rb +24 -17
  69. data/spec/unit/file_format/merb_format_spec.rb +41 -45
  70. data/spec/unit/file_format/rails_format_spec.rb +157 -117
  71. data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
  72. data/spec/unit/filter/field_filter_spec.rb +13 -13
  73. data/spec/unit/filter/filter_spec.rb +1 -1
  74. data/spec/unit/filter/timespan_filter_spec.rb +15 -15
  75. data/spec/unit/mailer_spec.rb +30 -0
  76. data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
  77. data/spec/unit/source/log_parser_spec.rb +27 -27
  78. data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
  79. data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
  80. data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
  81. data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
  82. data/spec/unit/tracker/tracker_api_spec.rb +117 -42
  83. data/spec/unit/tracker/traffic_tracker_spec.rb +81 -79
  84. data/tasks/github-gem.rake +125 -75
  85. data/tasks/request_log_analyzer.rake +2 -2
  86. metadata +13 -8
@@ -1,28 +1,28 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::Database do
4
-
4
+
5
5
  describe '#load_database_schema!' do
6
-
6
+
7
7
  context 'for a Rails request database' do
8
8
  before(:each) do
9
9
  @database = RequestLogAnalyzer::Database.new(log_fixture(:rails, :db))
10
10
  @database.load_database_schema!
11
11
  end
12
-
12
+
13
13
  after(:each) { @database.remove_orm_classes! }
14
-
14
+
15
15
  # FileFormat-agnostic classes
16
16
  default_orm_class_names.each do |const|
17
17
  it "should create the default #{const} constant" do
18
- Object.const_defined?(const).should be_true
18
+ RequestLogAnalyzer::Database.const_defined?(const).should be_true
19
19
  end
20
20
 
21
21
  it "should create the default #{const} class inheriting from ActiveRecord::Base and RequestLogAnalyzer::Database::Base" do
22
- Object.const_get(const).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
22
+ RequestLogAnalyzer::Database.const_get(const).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
23
23
  end
24
24
  end
25
-
25
+
26
26
  # Some Fileformat-specific classes
27
27
  ['CompletedLine', 'ProcessingLine'].each do |const|
28
28
  it "should create the #{const} constant" do
@@ -32,19 +32,19 @@ describe RequestLogAnalyzer::Database do
32
32
  it "should create the #{const} class inheriting from ActiveRecord::Base and RequestLogAnalyzer::Database::Base" do
33
33
  Object.const_get(const).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
34
34
  end
35
-
35
+
36
36
  it "should create a :belongs_to relation from the #{const} class to Request and Source" do
37
37
  Object.const_get(const).send(:reflections).should include(:request, :source)
38
38
  end
39
-
39
+
40
40
  it "should create a :has_many relation from the Request and Source class to the #{const} class" do
41
- @database.request_class.send(:reflections).should include(const.underscore.pluralize.to_sym)
42
- @database.source_class.send(:reflections).should include(const.underscore.pluralize.to_sym)
41
+ RequestLogAnalyzer::Database::Request.send(:reflections).should include(const.underscore.pluralize.to_sym)
42
+ RequestLogAnalyzer::Database::Source.send(:reflections).should include(const.underscore.pluralize.to_sym)
43
43
  end
44
44
  end
45
45
  end
46
46
  end
47
-
47
+
48
48
  describe '#create_database_schema!' do
49
49
 
50
50
  before(:each) do
@@ -56,10 +56,11 @@ describe RequestLogAnalyzer::Database do
56
56
  @mock_class = Class.new(RequestLogAnalyzer::Database::Base)
57
57
  @mock_class.stub!(:create_table!)
58
58
  end
59
-
59
+
60
60
  after(:each) { @database.remove_orm_classes! }
61
61
 
62
62
  default_orm_class_names.each do |klass|
63
+
63
64
  it "should create a table for the default #{klass} class" do
64
65
  @database.connection.should_receive(:create_table).with(klass.underscore.pluralize.to_sym)
65
66
  @database.send :create_database_schema!
@@ -67,69 +68,63 @@ describe RequestLogAnalyzer::Database do
67
68
 
68
69
  it "should create a #{klass} class inheriting from ActiveRecord and the base class of the ORM module" do
69
70
  @database.send :create_database_schema!
70
- @database.send("#{klass.underscore}_class".to_sym).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
71
+ RequestLogAnalyzer::Database.const_get(klass).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
71
72
  end
72
73
  end
73
74
 
74
75
  testing_format.line_definitions.each do |name, definition|
75
-
76
+
76
77
  it "should create the #{(name.to_s + '_line').camelize} class for #{name.inspect} lines" do
77
78
  @database.send :create_database_schema!
78
79
  Object.const_defined?("#{name}_line".camelize).should be_true
79
80
  end
80
-
81
+
81
82
  it "should create the #{name.to_s + '_lines'} table for the parsed #{name.inspect} lines" do
82
83
  @database.connection.should_receive(:create_table).with("#{name}_lines".to_sym)
83
84
  @database.send :create_database_schema!
84
85
  end
85
86
  end
86
87
  end
87
-
88
+
88
89
  describe '#load_activerecord_class' do
89
-
90
- before(:each) do
90
+
91
+ before(:each) do
91
92
  @database = RequestLogAnalyzer::Database.new
92
93
  @connection = mock_connection
93
94
  @database.stub!(:connection).and_return(@connection)
94
-
95
- # Mock the request ORM class
96
- @request_class = mock('Request ActiveRecord::Base class')
97
- @request_class.stub!(:has_many)
98
-
99
- @source_class = mock('Source ActiveRecord::Base class')
100
- @source_class.stub!(:has_many)
101
-
102
- @database.stub!(:request_class).and_return(@request_class)
103
- @database.stub!(:source_class).and_return(@source_class)
104
-
95
+
96
+ # Mock the has_many method of the defaukt ORM classes
97
+ RequestLogAnalyzer::Database::Request.stub!(:has_many)
98
+ RequestLogAnalyzer::Database::Source.stub!(:has_many)
99
+
105
100
  @mock_class = Class.new(RequestLogAnalyzer::Database::Base)
106
-
101
+
107
102
  RequestLogAnalyzer::Database::Base.stub!(:subclass_from_table).and_return(@mock_class)
108
103
  RequestLogAnalyzer::Database::Base.stub!(:subclass_from_line_definition).and_return(@mock_class)
109
104
  end
110
-
105
+
111
106
  after(:each) { @database.remove_orm_classes! }
112
-
107
+
113
108
  it "should call :subclass_from_table when a table name is given as string" do
114
109
  RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_table).and_return(@mock_class)
115
110
  @database.load_activerecord_class('test_lines')
116
111
  end
117
-
112
+
118
113
  it "should call :subclass_from_table when a table name is given as symbol" do
119
114
  RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_table).and_return(@mock_class)
120
115
  @database.load_activerecord_class(:test_lines)
121
116
  end
122
-
117
+
123
118
  it "should call :subclass_from_table when a LineDefinition is given" do
124
119
  RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_line_definition).and_return(@mock_class)
125
120
  @database.load_activerecord_class(RequestLogAnalyzer::LineDefinition.new(:test))
126
- end
127
-
121
+ end
122
+
128
123
  it "should define the class in the ORM module" do
129
124
  @database.load_activerecord_class(:test_lines)
130
125
  Object.const_defined?('TestLine').should be_true
131
126
  end
132
-
127
+
133
128
  it "should add the class to the line_classes array of the database" do
134
129
  @database.load_activerecord_class(:test_lines)
135
130
  @database.line_classes.should include(TestLine)
@@ -7,24 +7,24 @@ describe RequestLogAnalyzer::FileFormat::AmazonS3 do
7
7
  @log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
8
8
  @sample = '2f88111968424e6306bf4d292c0188ccb94ff9374ea2836b50a1a79f7cd656e1 sample-bucket [06/Oct/2006:01:42:14 +0000] 207.171.172.6 65a011a29cdf8ec533ec3d1ccaae921c C980091AD89C936A REST.GET.OBJECT object.png "GET /sample-bucket/object.png HTTP/1.1" 200 - 1243 1243 988 987 "-" "aranhabot"'
9
9
  end
10
-
10
+
11
11
  it "should be a valid file format" do
12
12
  @file_format.should be_valid
13
13
  end
14
-
14
+
15
15
  it "should parse access lines and capture all of its fields" do
16
16
  @file_format.should have_line_definition(:access).capturing(:bucket_owner, :bucket, :timestamp, :remote_ip, :requester,
17
17
  :key, :operation, :total_time, :turnaround_time, :bytes_sent, :object_size, :referer, :user_agent)
18
18
  end
19
-
19
+
20
20
  it "should match the sample line" do
21
21
  @file_format.parse_line(@sample).should include(:line_definition, :captures)
22
22
  end
23
-
23
+
24
24
  it "should not match a nonsense line" do
25
25
  @file_format.parse_line('dsadasdas dsaadsads dsaadsads').should be_nil
26
26
  end
27
-
27
+
28
28
  it "should parse and convert the sample fields correctly" do
29
29
  @log_parser.parse_io(StringIO.new(@sample)) do |request|
30
30
  request[:bucket_owner].should == '2f88111968424e6306bf4d292c0188ccb94ff9374ea2836b50a1a79f7cd656e1'
@@ -23,7 +23,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
23
23
  it "should make it a footer line" do
24
24
  @line_definition.should be_footer
25
25
  end
26
-
26
+
27
27
  it "should capture :duration" do
28
28
  @line_definition.captures?(:duration).should be_true
29
29
  end
@@ -43,7 +43,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
43
43
  it "should be a valid file format" do
44
44
  @format.should be_valid
45
45
  end
46
-
46
+
47
47
  it "should setup report trackers" do
48
48
  @format.report_trackers.should_not be_empty
49
49
  end
@@ -60,7 +60,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
60
60
  it "should have a valid language definitions" do
61
61
  @file_format.should be_valid
62
62
  end
63
-
63
+
64
64
  it "should parse a valid access log line" do
65
65
  @file_format.line_definitions[:access].matches(@sample_1).should be_kind_of(Hash)
66
66
  end
@@ -68,7 +68,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
68
68
  it "should not parse a valid access log line" do
69
69
  @file_format.line_definitions[:access].matches('addasdsasadadssadasd').should be_false
70
70
  end
71
-
71
+
72
72
  it "should read the correct values from a valid HTTP/1.0 access log line" do
73
73
  @log_parser.parse_io(StringIO.new(@sample_1)) do |request|
74
74
  request[:remote_host].should == '1.129.119.13'
@@ -80,7 +80,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
80
80
  request[:user].should == nil
81
81
  end
82
82
  end
83
-
83
+
84
84
  it "should read the correct values from a valid 200 access log line" do
85
85
  @log_parser.parse_io(StringIO.new(@sample_2)) do |request|
86
86
  request[:remote_host].should == '1.82.235.29'
@@ -91,7 +91,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
91
91
  request[:bytes_sent].should == 23414
92
92
  request[:user].should == nil
93
93
  end
94
- end
94
+ end
95
95
 
96
96
  it "should parse 10 request from fixture access log" do
97
97
  counter = mock('counter')
@@ -99,18 +99,18 @@ describe RequestLogAnalyzer::FileFormat::Apache do
99
99
  @log_parser.parse_file(log_fixture(:apache_common)) { counter.hit! }
100
100
  end
101
101
  end
102
-
102
+
103
103
  context '"Rack" access log parser' do
104
104
  before(:each) do
105
105
  @file_format = RequestLogAnalyzer::FileFormat.load(:rack)
106
106
  @log_parser = RequestLogAnalyzer::Source::LogParser.new(@file_format)
107
107
  @sample_1 = '127.0.0.1 - - [16/Sep/2009 06:40:08] "GET /favicon.ico HTTP/1.1" 500 63183 0.0453'
108
108
  end
109
-
109
+
110
110
  it "should create a kind of an Apache file format" do
111
111
  @file_format.should be_kind_of(RequestLogAnalyzer::FileFormat::Apache)
112
112
  end
113
-
113
+
114
114
  it "should have a valid language definitions" do
115
115
  @file_format.should be_valid
116
116
  end
@@ -136,7 +136,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
136
136
  end
137
137
  end
138
138
  end
139
-
139
+
140
140
  context '"Combined" access log parsing' do
141
141
 
142
142
  before(:all) do
@@ -171,7 +171,7 @@ describe RequestLogAnalyzer::FileFormat::Apache do
171
171
  request[:user_agent].should == 'Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)'
172
172
  end
173
173
  end
174
-
174
+
175
175
  it "should read the correct values from a valid 200 access log line" do
176
176
  @log_parser.parse_io(StringIO.new(@sample_2)) do |request|
177
177
  request[:remote_host].should == '10.0.1.1'
@@ -184,8 +184,8 @@ describe RequestLogAnalyzer::FileFormat::Apache do
184
184
  request[:user].should == nil
185
185
  request[:user_agent].should == 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9'
186
186
  end
187
- end
188
-
187
+ end
188
+
189
189
  it "should parse 5 request from fixture access log" do
190
190
  counter = mock('counter')
191
191
  counter.should_receive(:hit!).exactly(5).times
@@ -3,43 +3,43 @@ require File.dirname(__FILE__) + '/../../spec_helper'
3
3
  describe RequestLogAnalyzer::FileFormat do
4
4
 
5
5
  describe ".format_definition" do
6
-
6
+
7
7
  before(:each) do
8
8
  @first_file_format = Class.new(RequestLogAnalyzer::FileFormat::Base)
9
9
  @second_file_format = Class.new(RequestLogAnalyzer::FileFormat::Base)
10
10
  end
11
-
11
+
12
12
  it "should specify line definitions directly within the file_format" do
13
13
  @first_file_format.format_definition.direct_test :regexp => /test/
14
14
  @first_file_format.should have_line_definition(:direct_test)
15
15
  end
16
-
16
+
17
17
  it "specify lines with a block for the format definition" do
18
18
  @first_file_format.format_definition do |format|
19
19
  format.block_test :regexp => /test (\w+)/, :captures => [{:name => :tester, :type => :string}]
20
- end
21
-
20
+ end
21
+
22
22
  @first_file_format.should have_line_definition(:block_test).capturing(:tester)
23
23
  end
24
-
24
+
25
25
  it "should specify a line with a block" do
26
26
  @first_file_format.format_definition.hash_test do |line|
27
27
  line.regexp = /test/
28
28
  line.captures = []
29
29
  end
30
-
30
+
31
31
  @first_file_format.should have_line_definition(:hash_test)
32
32
  end
33
-
33
+
34
34
  it "should define lines only for its own language" do
35
35
  @first_file_format.format_definition.first :regexp => /test 123/
36
36
  @second_file_format.format_definition.second :regexp => /test 456/
37
-
37
+
38
38
  @first_file_format.should have_line_definition(:first)
39
39
  @first_file_format.should_not have_line_definition(:second)
40
- @second_file_format.should_not have_line_definition(:first)
40
+ @second_file_format.should_not have_line_definition(:first)
41
41
  @second_file_format.should have_line_definition(:second)
42
- end
42
+ end
43
43
  end
44
44
 
45
45
  describe ".load" do
@@ -58,12 +58,12 @@ describe RequestLogAnalyzer::FileFormat do
58
58
  @file_format = RequestLogAnalyzer::FileFormat.load(:rails)
59
59
  @file_format.should be_kind_of(RequestLogAnalyzer::FileFormat::Rails)
60
60
  end
61
-
61
+
62
62
  it "should load a provided format file" do
63
63
  format_filename = File.dirname(__FILE__) + '/../../lib/testing_format.rb'
64
64
  @file_format = RequestLogAnalyzer::FileFormat.load(format_filename)
65
65
  @file_format.should be_kind_of(TestingFormat)
66
66
  end
67
-
67
+
68
68
  end
69
69
  end
@@ -9,20 +9,27 @@ describe RequestLogAnalyzer::LineDefinition do
9
9
  :captures => [{ :name => :what, :type => :string }, { :name => :tries, :type => :integer }]
10
10
  })
11
11
  end
12
-
12
+
13
13
  describe '#matches' do
14
-
14
+
15
15
  it "should return false on an unmatching line" do
16
- @line_definition.should_not parse("nonmatching")
16
+ @line_definition.matches("nonmatching").should be_false
17
17
  end
18
-
18
+
19
19
  it "should return false when only the teaser matches" do
20
- @line_definition.should_not parse("Testing LineDefinition")
20
+ @line_definition.matches("Testing LineDefinition").should be_false
21
21
  end
22
-
22
+
23
23
  it "should parse a line and capture the expected values" do
24
- @line_definition.should parse("Testing LineDefinition, tries: 123").capturing('LineDefinition', '123')
24
+ @line_definition.matches("Testing LineDefinition, tries: 123").should == {:line_definition => @line_definition, :captures => ['LineDefinition', '123'] }
25
+ end
26
+
27
+ 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
25
31
  end
32
+
26
33
  end
27
34
 
28
35
  describe '#convert_captured_values' do
@@ -31,38 +38,38 @@ describe RequestLogAnalyzer::LineDefinition do
31
38
  @request = mock('request')
32
39
  @request.stub!(:convert_value).and_return('foo')
33
40
  end
34
-
41
+
35
42
  it "should call convert_value for every captured value" do
36
43
  @request.should_receive(:convert_value).twice
37
44
  @line_definition.convert_captured_values(['test', '123'], @request)
38
45
  end
39
-
46
+
40
47
  it "should set the converted values" do
41
48
  @line_definition.convert_captured_values(['test', '123'], @request).should == {:what => 'foo', :tries => 'foo'}
42
49
  end
43
-
50
+
44
51
  context 'when using :provides option' do
45
52
  before(:each) do
46
- @ld = RequestLogAnalyzer::LineDefinition.new(:test, :regexp => /Hash\: (\{.+\})/,
53
+ @ld = RequestLogAnalyzer::LineDefinition.new(:test, :regexp => /Hash\: (\{.+\})/,
47
54
  :captures => [{ :name => :hash, :type => :hash, :provides => {:bar => :string}}])
48
-
55
+
49
56
  @request = mock('request')
50
57
 
51
58
  @request.stub!(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
52
59
  @request.stub!(:convert_value).with('baz', anything).and_return('foo')
53
- end
54
-
60
+ end
61
+
55
62
  it "should call Request#convert_value for the initial hash and the value in the hash" do
56
63
  @request.should_receive(:convert_value).with("{:bar=>'baz'}", anything).and_return(:bar => 'baz')
57
64
  @request.should_receive(:convert_value).with("baz", anything)
58
65
  @ld.convert_captured_values(["{:bar=>'baz'}"], @request)
59
66
  end
60
-
67
+
61
68
  it "should set the provides fields" do
62
69
  # The captures field must be set and converted as well
63
70
  @ld.convert_captured_values(["{:bar=>'baz'}"], @request)[:bar].should eql('foo')
64
- end
71
+ end
65
72
  end
66
-
73
+
67
74
  end
68
75
  end
@@ -1,56 +1,52 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
2
 
3
3
  describe RequestLogAnalyzer::FileFormat::Merb do
4
-
5
- before(:each) do
6
- @log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:merb))
7
- end
8
-
9
- it "should have a valid language definitions" do
10
- @log_parser.file_format.should be_valid
11
- end
12
-
13
- it "should parse a stream and find valid requests" do
14
- File.open(log_fixture(:merb), 'r') do |io|
15
- @log_parser.parse_io(io) do |request|
16
- request.should be_kind_of(RequestLogAnalyzer::Request)
17
- end
18
- end
19
- end
20
4
 
21
- it "should find 11 completed requests" do
22
- @log_parser.should_receive(:handle_request).exactly(11).times
23
- @log_parser.parse_file(log_fixture(:merb))
5
+ it "should be a valid file format" do
6
+ RequestLogAnalyzer::FileFormat.load(:merb).should be_valid
24
7
  end
25
-
26
- it "should parse all details from the first request correctly" do
27
- request = nil
28
- @log_parser.parse_file(log_fixture(:merb)) { |found_request| request ||= found_request }
8
+
9
+ describe '#parse_line' do
10
+ before(:each) do
11
+ @file_format = RequestLogAnalyzer::FileFormat.load(:merb)
12
+ end
29
13
 
30
- request.should be_completed
31
- request[:controller].should == 'session'
32
- request[:action].should == 'destroy'
33
- request[:method].should == 'delete'
34
- request[:params].should be_kind_of(Hash)
35
- request[:timestamp].should == 20080829111023 # 'Fri Aug 29 11:10:23 +0200 2008'
36
- request[:dispatch_time].should == 0.243424
37
- request[:after_filters_time].should == 6.9e-05
38
- request[:before_filters_time].should == 0.213213
39
- request[:action_time].should == 0.241652
14
+ it "should parse a :started line correctly" do
15
+ line = '~ Started request handling: Fri Aug 29 11:10:23 +0200 2008'
16
+ @file_format.should parse_line(line).as(:started).and_capture(:timestamp => 20080829111023)
17
+ end
40
18
 
19
+ it "should parse a prefixed :started line correctly" do
20
+ line = '~ Aug 31 18:35:24 typekit-web001 merb: ~ Started request handling: Mon Aug 31 18:35:25 +0000 2009'
21
+ @file_format.should parse_line(line).as(:started).and_capture(:timestamp => 20090831183525)
22
+ end
23
+
24
+ it "should parse a :params line correctly" do
25
+ line = '~ Params: {"_method"=>"delete", "authenticity_token"=>"[FILTERED]", "action"=>"delete", "controller"=>"session"}'
26
+ @file_format.should parse_line(line).as(:params).and_capture(:controller => 'session', :action => 'delete', :namespace => nil)
27
+ end
28
+
29
+ it "should parse a :completed line correctly" do
30
+ line = '~ {:dispatch_time=>0.006117, :after_filters_time=>6.1e-05, :before_filters_time=>0.000712, :action_time=>0.005833}'
31
+ @file_format.should parse_line(line).as(:completed).and_capture(:dispatch_time => 0.006117,
32
+ :before_filters_time => 0.000712, :action_time => 0.005833, :after_filters_time => 6.1e-05)
33
+ end
41
34
  end
35
+
36
+ describe '#parse_io' do
37
+ before(:each) do
38
+ @log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:merb))
39
+ end
40
+
41
+ it "should parse a stream and find valid Merb requests" do
42
+ @log_parser.parse_file(log_fixture(:merb)) do |request|
43
+ request.should be_kind_of(RequestLogAnalyzer::FileFormat::Merb::Request)
44
+ end
45
+ end
42
46
 
43
- it "should parse a prefixed Merb file correctly" do
44
- request = nil
45
- @log_parser.parse_file(log_fixture(:merb_prefixed)) { |found_request| request ||= found_request }
46
-
47
- request.should be_completed
48
- request[:timestamp].should == 20090831183525
49
- request[:controller].should == 'home'
50
- request[:action].should == 'index'
51
- request[:dispatch_time].should == 0.012001
52
- request[:after_filters_time].should == 0.0
53
- request[:before_filters_time].should == 0.0
54
- request[:action_time].should == 0.012001
47
+ it "should find 11 completed requests" do
48
+ @log_parser.should_receive(:handle_request).exactly(11).times
49
+ @log_parser.parse_file(log_fixture(:merb))
50
+ end
55
51
  end
56
52
  end