ngmoco-request-log-analyzer 1.4.2
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.
- data/.gitignore +10 -0
- data/DESIGN.rdoc +41 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +8 -0
- data/bin/request-log-analyzer +114 -0
- data/lib/cli/command_line_arguments.rb +301 -0
- data/lib/cli/database_console.rb +26 -0
- data/lib/cli/database_console_init.rb +43 -0
- data/lib/cli/progressbar.rb +213 -0
- data/lib/cli/tools.rb +46 -0
- data/lib/request_log_analyzer.rb +44 -0
- data/lib/request_log_analyzer/aggregator.rb +49 -0
- data/lib/request_log_analyzer/aggregator/database_inserter.rb +83 -0
- data/lib/request_log_analyzer/aggregator/echo.rb +29 -0
- data/lib/request_log_analyzer/aggregator/summarizer.rb +175 -0
- data/lib/request_log_analyzer/controller.rb +332 -0
- data/lib/request_log_analyzer/database.rb +102 -0
- data/lib/request_log_analyzer/database/base.rb +115 -0
- data/lib/request_log_analyzer/database/connection.rb +38 -0
- data/lib/request_log_analyzer/database/request.rb +22 -0
- data/lib/request_log_analyzer/database/source.rb +13 -0
- data/lib/request_log_analyzer/database/warning.rb +14 -0
- data/lib/request_log_analyzer/file_format.rb +160 -0
- data/lib/request_log_analyzer/file_format/amazon_s3.rb +71 -0
- data/lib/request_log_analyzer/file_format/apache.rb +141 -0
- data/lib/request_log_analyzer/file_format/merb.rb +67 -0
- data/lib/request_log_analyzer/file_format/rack.rb +11 -0
- data/lib/request_log_analyzer/file_format/rails.rb +176 -0
- data/lib/request_log_analyzer/file_format/rails_development.rb +12 -0
- data/lib/request_log_analyzer/filter.rb +30 -0
- data/lib/request_log_analyzer/filter/anonymize.rb +39 -0
- data/lib/request_log_analyzer/filter/field.rb +42 -0
- data/lib/request_log_analyzer/filter/timespan.rb +45 -0
- data/lib/request_log_analyzer/line_definition.rb +111 -0
- data/lib/request_log_analyzer/log_processor.rb +99 -0
- data/lib/request_log_analyzer/mailer.rb +62 -0
- data/lib/request_log_analyzer/output.rb +113 -0
- data/lib/request_log_analyzer/output/fixed_width.rb +220 -0
- data/lib/request_log_analyzer/output/html.rb +184 -0
- data/lib/request_log_analyzer/request.rb +175 -0
- data/lib/request_log_analyzer/source.rb +72 -0
- data/lib/request_log_analyzer/source/database_loader.rb +87 -0
- data/lib/request_log_analyzer/source/log_parser.rb +274 -0
- data/lib/request_log_analyzer/tracker.rb +206 -0
- data/lib/request_log_analyzer/tracker/duration.rb +104 -0
- data/lib/request_log_analyzer/tracker/frequency.rb +95 -0
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +107 -0
- data/lib/request_log_analyzer/tracker/timespan.rb +81 -0
- data/lib/request_log_analyzer/tracker/traffic.rb +106 -0
- data/request-log-analyzer.gemspec +40 -0
- data/spec/database.yml +23 -0
- data/spec/fixtures/apache_combined.log +5 -0
- data/spec/fixtures/apache_common.log +10 -0
- data/spec/fixtures/decompression.log +12 -0
- data/spec/fixtures/decompression.log.bz2 +0 -0
- data/spec/fixtures/decompression.log.gz +0 -0
- data/spec/fixtures/decompression.log.zip +0 -0
- data/spec/fixtures/decompression.tar.gz +0 -0
- data/spec/fixtures/decompression.tgz +0 -0
- data/spec/fixtures/header_and_footer.log +6 -0
- data/spec/fixtures/merb.log +84 -0
- data/spec/fixtures/merb_prefixed.log +9 -0
- data/spec/fixtures/multiple_files_1.log +5 -0
- data/spec/fixtures/multiple_files_2.log +2 -0
- data/spec/fixtures/rails.db +0 -0
- data/spec/fixtures/rails_1x.log +59 -0
- data/spec/fixtures/rails_22.log +12 -0
- data/spec/fixtures/rails_22_cached.log +10 -0
- data/spec/fixtures/rails_unordered.log +24 -0
- data/spec/fixtures/syslog_1x.log +5 -0
- data/spec/fixtures/test_file_format.log +13 -0
- data/spec/fixtures/test_language_combined.log +14 -0
- data/spec/fixtures/test_order.log +16 -0
- data/spec/integration/command_line_usage_spec.rb +84 -0
- data/spec/integration/munin_plugins_rails_spec.rb +58 -0
- data/spec/integration/scout_spec.rb +151 -0
- data/spec/lib/helpers.rb +52 -0
- data/spec/lib/macros.rb +18 -0
- data/spec/lib/matchers.rb +77 -0
- data/spec/lib/mocks.rb +76 -0
- data/spec/lib/testing_format.rb +46 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/unit/aggregator/database_inserter_spec.rb +93 -0
- data/spec/unit/aggregator/summarizer_spec.rb +26 -0
- data/spec/unit/controller/controller_spec.rb +41 -0
- data/spec/unit/controller/log_processor_spec.rb +18 -0
- data/spec/unit/database/base_class_spec.rb +183 -0
- data/spec/unit/database/connection_spec.rb +34 -0
- data/spec/unit/database/database_spec.rb +133 -0
- data/spec/unit/file_format/amazon_s3_format_spec.rb +49 -0
- data/spec/unit/file_format/apache_format_spec.rb +203 -0
- data/spec/unit/file_format/file_format_api_spec.rb +69 -0
- data/spec/unit/file_format/line_definition_spec.rb +75 -0
- data/spec/unit/file_format/merb_format_spec.rb +52 -0
- data/spec/unit/file_format/rails_format_spec.rb +164 -0
- data/spec/unit/filter/anonymize_filter_spec.rb +21 -0
- data/spec/unit/filter/field_filter_spec.rb +66 -0
- data/spec/unit/filter/filter_spec.rb +17 -0
- data/spec/unit/filter/timespan_filter_spec.rb +58 -0
- data/spec/unit/mailer_spec.rb +30 -0
- data/spec/unit/request_spec.rb +111 -0
- data/spec/unit/source/log_parser_spec.rb +119 -0
- data/spec/unit/tracker/duration_tracker_spec.rb +130 -0
- data/spec/unit/tracker/frequency_tracker_spec.rb +88 -0
- data/spec/unit/tracker/hourly_spread_spec.rb +79 -0
- data/spec/unit/tracker/timespan_tracker_spec.rb +73 -0
- data/spec/unit/tracker/tracker_api_spec.rb +124 -0
- data/spec/unit/tracker/traffic_tracker_spec.rb +107 -0
- data/tasks/github-gem.rake +323 -0
- data/tasks/request_log_analyzer.rake +26 -0
- metadata +220 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::LineDefinition do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@line_definition = RequestLogAnalyzer::LineDefinition.new(:test, {
|
|
7
|
+
:teaser => /Testing /,
|
|
8
|
+
:regexp => /Testing (\w+), tries\: (\d+)/,
|
|
9
|
+
:captures => [{ :name => :what, :type => :string }, { :name => :tries, :type => :integer }]
|
|
10
|
+
})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '#matches' do
|
|
14
|
+
|
|
15
|
+
it "should return false on an unmatching line" do
|
|
16
|
+
@line_definition.matches("nonmatching").should be_false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should return false when only the teaser matches" do
|
|
20
|
+
@line_definition.matches("Testing LineDefinition").should be_false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
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'] }
|
|
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
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '#convert_captured_values' do
|
|
36
|
+
|
|
37
|
+
before(:each) do
|
|
38
|
+
@request = mock('request')
|
|
39
|
+
@request.stub!(:convert_value).and_return('foo')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
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)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should set the converted values" do
|
|
48
|
+
@line_definition.convert_captured_values(['test', '123'], @request).should == {:what => 'foo', :tries => 'foo'}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
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')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
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)
|
|
66
|
+
end
|
|
67
|
+
|
|
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')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::FileFormat::Merb do
|
|
4
|
+
|
|
5
|
+
it "should be a valid file format" do
|
|
6
|
+
RequestLogAnalyzer::FileFormat.load(:merb).should be_valid
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe '#parse_line' do
|
|
10
|
+
before(:each) do
|
|
11
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(:merb)
|
|
12
|
+
end
|
|
13
|
+
|
|
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
|
|
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
|
|
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
|
|
46
|
+
|
|
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
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::FileFormat::Rails do
|
|
4
|
+
|
|
5
|
+
describe '.create' do
|
|
6
|
+
|
|
7
|
+
context 'without providing a lines argument' do
|
|
8
|
+
before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails) }
|
|
9
|
+
|
|
10
|
+
it "should create a valid file format" do
|
|
11
|
+
@rails.should be_valid
|
|
12
|
+
end
|
|
13
|
+
|
|
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
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
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
|
|
26
|
+
|
|
27
|
+
it "should at least parse :processing and :completed lines" do
|
|
28
|
+
@rails.line_definitions.should include(:processing, :completed, :failure)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
RequestLogAnalyzer::FileFormat::Rails::LINE_COLLECTIONS.keys.each do |constant|
|
|
33
|
+
|
|
34
|
+
context "using the '#{constant}' line collection constant" do
|
|
35
|
+
before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails, constant) }
|
|
36
|
+
|
|
37
|
+
it "should return a valid language" do
|
|
38
|
+
@rails.should be_valid
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should at least parse :processing and :completed lines" do
|
|
42
|
+
@rails.line_definitions.should include(:processing, :completed)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '#parse_line' do
|
|
49
|
+
before(:each) { @rails = RequestLogAnalyzer::FileFormat.load(:rails, :all) }
|
|
50
|
+
|
|
51
|
+
{'with prefix' => 'LINE PREFIX: ', 'without prefix' => '' }.each do |context, prefix|
|
|
52
|
+
context context do
|
|
53
|
+
it "should parse a :processing line correctly" do
|
|
54
|
+
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')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should parse a Rails 2.1 style :completed line correctly" do
|
|
59
|
+
line = prefix + 'Completed in 0.21665 (4 reqs/sec) | Rendering: 0.00926 (4%) | DB: 0.00000 (0%) | 200 OK [http://demo.nu/employees]'
|
|
60
|
+
@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')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should parse a Rails 2.2 style :completed line correctly" do
|
|
64
|
+
line = prefix + 'Completed in 614ms (View: 120, DB: 31) | 200 OK [http://floorplanner.local/demo]'
|
|
65
|
+
@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')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should parse a :failure line with exception correctly" do
|
|
69
|
+
line = prefix + "NoMethodError (undefined method `update_domain_account' for nil:NilClass):"
|
|
70
|
+
@rails.should parse_line(line).as(:failure).and_capture(:error => 'NoMethodError', :message => "undefined method `update_domain_account' for nil:NilClass")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should parse a :cache_hit line correctly" do
|
|
74
|
+
line = prefix + '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.'
|
|
75
|
+
@rails.should parse_line(line).as(:cache_hit)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should parse a :parameters line correctly" do
|
|
79
|
+
line = prefix + ' Parameters: {"action"=>"cached", "controller"=>"cached"}'
|
|
80
|
+
@rails.should parse_line(line).as(:parameters).and_capture(:params => {:action => 'cached', :controller => 'cached'})
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "should parse a :rendered line correctly" do
|
|
84
|
+
line = prefix + 'Rendered layouts/_footer (2.9ms)'
|
|
85
|
+
@rails.should parse_line(line).as(:rendered).and_capture(:render_file => 'layouts/_footer', :render_duration => 0.0029)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should parse a :query_executed line with colors" do
|
|
89
|
+
line = prefix + ' [4;36;1mUser Load (0.4ms)[0m [0;1mSELECT * FROM `users` WHERE (`users`.`id` = 18205844) [0m'
|
|
90
|
+
@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)')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should parse a :query_executed line without colors" do
|
|
94
|
+
line = prefix + ' User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) '
|
|
95
|
+
@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)')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should parse a :query_cached line with colors" do
|
|
99
|
+
line = prefix + ' [4;35;1mCACHE (0.0ms)[0m [0mSELECT * FROM `users` WHERE (`users`.`id` = 0) [0m'
|
|
100
|
+
@rails.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should parse a :query_cached line without colors" do
|
|
104
|
+
line = prefix + ' CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) '
|
|
105
|
+
@rails.should parse_line(line).as(:query_cached).and_capture(:cached_duration => 0.0, :cached_sql => 'SELECT * FROM users WHERE (users.id = :int)')
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should not parse an unsupported line" do
|
|
109
|
+
line = prefix + 'nonsense line that should not be parsed as anything'
|
|
110
|
+
@rails.should_not parse_line(line)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe '#parse_io' do
|
|
117
|
+
before(:each) do
|
|
118
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
119
|
+
RequestLogAnalyzer::FileFormat.load(:rails), :parse_strategy => 'cautious')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it "should parse a Rails 2.1 style log and find valid Rails requests without warnings" do
|
|
123
|
+
request_counter.should_receive(:hit!).exactly(4).times
|
|
124
|
+
@log_parser.should_not_receive(:warn)
|
|
125
|
+
|
|
126
|
+
@log_parser.parse_file(log_fixture(:rails_1x)) do |request|
|
|
127
|
+
request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "should parse a Rails 2.2 style log and find valid Rails requests without warnings" do
|
|
132
|
+
request_counter.should_receive(:hit!).once
|
|
133
|
+
@log_parser.should_not_receive(:warn)
|
|
134
|
+
|
|
135
|
+
@log_parser.parse_file(log_fixture(:rails_22)) do |request|
|
|
136
|
+
request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should parse a Rails SyslogLogger file with prefix and find valid requests without warnings" do
|
|
141
|
+
request_counter.should_receive(:hit!).once
|
|
142
|
+
@log_parser.should_not_receive(:warn)
|
|
143
|
+
|
|
144
|
+
@log_parser.parse_file(log_fixture(:syslog_1x)) do |request|
|
|
145
|
+
request_counter.hit! if request.kind_of?(RequestLogAnalyzer::FileFormat::Rails::Request) && request.completed?
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should parse cached requests" do
|
|
150
|
+
@log_parser.should_not_receive(:warn)
|
|
151
|
+
@log_parser.parse_file(log_fixture(:rails_22_cached)) do |request|
|
|
152
|
+
request.should be_completed
|
|
153
|
+
request =~ :cache_hit
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "should detect unordered requests in the logs" do
|
|
158
|
+
@log_parser.should_not_receive(:handle_request)
|
|
159
|
+
@log_parser.should_receive(:warn).with(:unclosed_request, anything).once
|
|
160
|
+
@log_parser.should_receive(:warn).with(:no_current_request, anything).twice
|
|
161
|
+
@log_parser.parse_file(log_fixture(:rails_unordered))
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Anonymize, 'anonymize request' do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@filter = RequestLogAnalyzer::Filter::Anonymize.new(testing_format)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should anonimize ip" do
|
|
10
|
+
@filter.filter(request(:ip => '123.123.123.123'))[:ip].should_not eql('123.123.123.123')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should anonimize url" do
|
|
14
|
+
@filter.filter(request(:url => 'https://test.mysite.com/employees'))[:url].should eql('http://example.com/employees')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should fuzz durations" do
|
|
18
|
+
@filter.filter(request(:duration => 100))[:duration].should_not eql(100)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Field, 'string in accept mode' do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => 'test', :mode => :select)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should reject a request if the field value does not match" do
|
|
10
|
+
@filter.filter(request(:test => 'not test')).should be_nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should reject a request if the field name does not match" do
|
|
14
|
+
@filter.filter(request(:testing => 'test')).should be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should accept a request if the both name and value match" do
|
|
18
|
+
@filter.filter(request(:test => 'test')).should_not be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should accept a request if the value is not the first value" do
|
|
22
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'test'}])).should_not be_nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe RequestLogAnalyzer::Filter::Field, 'string in reject mode' do
|
|
27
|
+
|
|
28
|
+
before(:each) do
|
|
29
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => 'test', :mode => :reject)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should accept a request if the field value does not match" do
|
|
33
|
+
@filter.filter(request(:test => 'not test')).should_not be_nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should accept a request if the field name does not match" do
|
|
37
|
+
@filter.filter(request(:testing => 'test')).should_not be_nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should reject a request if the both name and value match" do
|
|
41
|
+
@filter.filter(request(:test => 'test')).should be_nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should reject a request if the value is not the first value" do
|
|
45
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'test'}])).should be_nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe RequestLogAnalyzer::Filter::Field, 'regexp in accept mode' do
|
|
50
|
+
|
|
51
|
+
before(:each) do
|
|
52
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => '/test/', :mode => :select)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should reject a request if the field value does not match" do
|
|
56
|
+
@filter.filter(request(:test => 'a working test')).should_not be_nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should reject a request if the field name does not match" do
|
|
60
|
+
@filter.filter(request(:testing => 'test')).should be_nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should accept a request if the value is not the first value" do
|
|
64
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'testing 123'}])).should_not be_nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Base, 'base filter' do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@filter = RequestLogAnalyzer::Filter::Base.new(testing_format)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should return everything" do
|
|
10
|
+
@filter.filter(request(:ip => '123.123.123.123'))[:ip].should eql('123.123.123.123')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should return nil on nil request" do
|
|
14
|
+
@filter.filter(nil).should be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'both before and after' do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :after => DateTime.parse('2009-01-01'), :before => DateTime.parse('2009-02-02'))
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should reject a request before the after date" do
|
|
10
|
+
@filter.filter(request(:timestamp => 20081212000000)).should be_nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should reject a request after the before date" do
|
|
14
|
+
@filter.filter(request(:timestamp => 20090303000000)).should be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should accept a request between the after and before dates" do
|
|
18
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'only before' do
|
|
23
|
+
|
|
24
|
+
before(:each) do
|
|
25
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :before => DateTime.parse('2009-02-02'))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should accept a request before the after date" do
|
|
29
|
+
@filter.filter(request(:timestamp => 20081212000000)).should_not be_nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should reject a request after the before date" do
|
|
33
|
+
@filter.filter(request(:timestamp => 20090303000000)).should be_nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should accept a request between the after and before dates" do
|
|
37
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'only after' do
|
|
42
|
+
|
|
43
|
+
before(:each) do
|
|
44
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :after => DateTime.parse('2009-01-01'))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should reject a request before the after date" do
|
|
48
|
+
@filter.filter(request(:timestamp => 20081212000000)).should be_nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should accept a request after the before date" do
|
|
52
|
+
@filter.filter(request(:timestamp => 20090303000000)).should_not be_nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should accept a request between the after and before dates" do
|
|
56
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
57
|
+
end
|
|
58
|
+
end
|