request-log-analyzer 1.1.2 → 1.2.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.
- data/DESIGN +24 -10
- data/README.rdoc +1 -1
- data/Rakefile +1 -2
- data/bin/request-log-analyzer +4 -27
- data/lib/cli/progressbar.rb +2 -19
- data/lib/cli/tools.rb +46 -0
- data/lib/request_log_analyzer/aggregator/database.rb +33 -8
- data/lib/request_log_analyzer/aggregator/echo.rb +1 -0
- data/lib/request_log_analyzer/aggregator/summarizer.rb +15 -13
- data/lib/request_log_analyzer/controller.rb +8 -4
- data/lib/request_log_analyzer/file_format/merb.rb +17 -4
- data/lib/request_log_analyzer/file_format/rails.rb +2 -2
- data/lib/request_log_analyzer/file_format/rails_development.rb +30 -92
- data/lib/request_log_analyzer/file_format.rb +8 -4
- data/lib/request_log_analyzer/filter/anonymize.rb +0 -3
- data/lib/request_log_analyzer/filter/field.rb +6 -1
- data/lib/request_log_analyzer/filter/timespan.rb +7 -1
- data/lib/request_log_analyzer/filter.rb +0 -4
- data/lib/request_log_analyzer/line_definition.rb +12 -2
- data/lib/request_log_analyzer/output/fixed_width.rb +14 -3
- data/lib/request_log_analyzer/output/html.rb +1 -0
- data/lib/request_log_analyzer/request.rb +6 -0
- data/lib/request_log_analyzer/source/database.rb +76 -0
- data/lib/request_log_analyzer/source/log_parser.rb +101 -48
- data/lib/request_log_analyzer/source.rb +28 -6
- data/lib/request_log_analyzer/tracker/duration.rb +90 -15
- data/lib/request_log_analyzer/tracker/frequency.rb +22 -10
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +20 -9
- data/lib/request_log_analyzer/tracker/timespan.rb +15 -8
- data/lib/request_log_analyzer.rb +29 -16
- data/spec/integration/command_line_usage_spec.rb +71 -0
- data/spec/lib/helper.rb +33 -0
- data/spec/lib/mocks.rb +47 -0
- data/spec/{file_formats/spec_format.rb → lib/testing_format.rb} +6 -1
- data/spec/spec_helper.rb +5 -41
- data/spec/{database_inserter_spec.rb → unit/aggregator/database_inserter_spec.rb} +40 -37
- data/spec/unit/aggregator/summarizer_spec.rb +28 -0
- data/spec/unit/controller/controller_spec.rb +43 -0
- data/spec/{log_processor_spec.rb → unit/controller/log_processor_spec.rb} +4 -3
- data/spec/{file_format_spec.rb → unit/file_format/file_format_api_spec.rb} +16 -4
- data/spec/{line_definition_spec.rb → unit/file_format/line_definition_spec.rb} +13 -6
- data/spec/{merb_format_spec.rb → unit/file_format/merb_format_spec.rb} +2 -2
- data/spec/{rails_format_spec.rb → unit/file_format/rails_format_spec.rb} +19 -11
- data/spec/unit/filter/anonymize_filter_spec.rb +22 -0
- data/spec/unit/filter/field_filter_spec.rb +69 -0
- data/spec/unit/filter/timespan_filter_spec.rb +61 -0
- data/spec/{log_parser_spec.rb → unit/source/log_parser_spec.rb} +7 -7
- data/spec/{request_spec.rb → unit/source/request_spec.rb} +5 -5
- data/spec/unit/tracker/duration_tracker_spec.rb +99 -0
- data/spec/unit/tracker/frequency_tracker_spec.rb +83 -0
- data/spec/unit/tracker/hourly_spread_spec.rb +75 -0
- data/spec/unit/tracker/timespan_tracker_spec.rb +65 -0
- data/spec/unit/tracker/tracker_api_test.rb +45 -0
- data/tasks/rspec.rake +12 -0
- metadata +54 -26
- data/spec/controller_spec.rb +0 -64
- data/spec/filter_spec.rb +0 -157
- data/spec/summarizer_spec.rb +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::FileFormat, :format_definition do
|
|
4
4
|
|
|
@@ -63,7 +63,18 @@ end
|
|
|
63
63
|
|
|
64
64
|
describe RequestLogAnalyzer::FileFormat, :load do
|
|
65
65
|
|
|
66
|
-
include
|
|
66
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
67
|
+
|
|
68
|
+
it "should return an instance of a FileFormat class" do
|
|
69
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(TestingFormat)
|
|
70
|
+
@file_format.should be_kind_of(TestingFormat)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
it "should return itself if it already is a FileFormat::Base instance" do
|
|
75
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(testing_format)
|
|
76
|
+
@file_format.should be_kind_of(TestingFormat)
|
|
77
|
+
end
|
|
67
78
|
|
|
68
79
|
it "should load a predefined file format from the /file_format dir" do
|
|
69
80
|
@file_format = RequestLogAnalyzer::FileFormat.load(:rails)
|
|
@@ -71,8 +82,9 @@ describe RequestLogAnalyzer::FileFormat, :load do
|
|
|
71
82
|
end
|
|
72
83
|
|
|
73
84
|
it "should load a provided format file" do
|
|
74
|
-
|
|
75
|
-
@file_format.
|
|
85
|
+
format_filename = File.dirname(__FILE__) + '/../../lib/testing_format.rb'
|
|
86
|
+
@file_format = RequestLogAnalyzer::FileFormat.load(format_filename)
|
|
87
|
+
@file_format.should be_kind_of(TestingFormat)
|
|
76
88
|
end
|
|
77
89
|
|
|
78
90
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::LineDefinition, :parsing do
|
|
4
4
|
|
|
@@ -35,11 +35,11 @@ end
|
|
|
35
35
|
|
|
36
36
|
describe RequestLogAnalyzer::LineDefinition, :converting do
|
|
37
37
|
|
|
38
|
-
include
|
|
38
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
39
39
|
|
|
40
40
|
before(:each) do
|
|
41
|
-
@file_format =
|
|
42
|
-
@request = @file_format.
|
|
41
|
+
@file_format = testing_format
|
|
42
|
+
@request = @file_format.request
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
it "should convert captures to a hash of converted values" do
|
|
@@ -48,10 +48,17 @@ describe RequestLogAnalyzer::LineDefinition, :converting do
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
it "should convert captures to a hash" do
|
|
51
|
-
hash = @file_format.line_definitions[:test].convert_captured_values(["
|
|
52
|
-
hash[:test_capture].should == 'Testing is
|
|
51
|
+
hash = @file_format.line_definitions[:test].convert_captured_values(["great", nil], @request)
|
|
52
|
+
hash[:test_capture].should == 'Testing is great'
|
|
53
53
|
hash[:duration].should be_nil
|
|
54
54
|
end
|
|
55
|
+
|
|
56
|
+
it "should merge a hash capture into the line hash" do
|
|
57
|
+
hash = @file_format.line_definitions[:eval].convert_captured_values(["{ 'greating' => 'hello', 'what' => 'world'}"], @request)
|
|
58
|
+
hash[:evaluated].should == { :greating => "hello", :what => "world"}
|
|
59
|
+
hash[:greating].should == 'hello'
|
|
60
|
+
hash[:what].should == 'world'
|
|
61
|
+
end
|
|
55
62
|
|
|
56
63
|
|
|
57
64
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::Source::LogParser, :merb do
|
|
4
|
-
include
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
5
|
|
|
6
6
|
before(:each) do
|
|
7
7
|
@log_parser = RequestLogAnalyzer::Source::LogParser.new(RequestLogAnalyzer::FileFormat.load(:merb))
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::Source::LogParser, "Rails" do
|
|
4
|
-
include
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
5
|
|
|
6
6
|
before(:each) do
|
|
7
|
-
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
7
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
8
|
+
RequestLogAnalyzer::FileFormat.load(:rails), :parse_strategy => 'cautious')
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
it "should have a valid language definitions" do
|
|
@@ -66,27 +67,34 @@ describe RequestLogAnalyzer::Source::LogParser, "Rails" do
|
|
|
66
67
|
end
|
|
67
68
|
|
|
68
69
|
it "should detect unordered requests in the logs" do
|
|
70
|
+
# No valid request should be found in cautious mode
|
|
69
71
|
@log_parser.should_not_receive(:handle_request)
|
|
70
72
|
# the first Processing-line will not give a warning, but the next one will
|
|
71
73
|
@log_parser.should_receive(:warn).with(:unclosed_request, anything).once
|
|
72
|
-
# Both Completed
|
|
74
|
+
# Both Completed lines will give a warning
|
|
73
75
|
@log_parser.should_receive(:warn).with(:no_current_request, anything).twice
|
|
76
|
+
|
|
74
77
|
@log_parser.parse_file(log_fixture(:rails_unordered))
|
|
75
78
|
end
|
|
76
79
|
end
|
|
77
80
|
|
|
78
|
-
describe
|
|
79
|
-
include
|
|
81
|
+
describe RequestLogAnalyzer::FileFormat::RailsDevelopment, "Rails with development details" do
|
|
82
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
80
83
|
|
|
81
84
|
before(:each) do
|
|
82
85
|
@file_format = RequestLogAnalyzer::FileFormat.load(:rails_development)
|
|
83
|
-
@request = @file_format.
|
|
86
|
+
@request = @file_format.request
|
|
84
87
|
end
|
|
85
88
|
|
|
86
89
|
it "should have a valid language definitions" do
|
|
87
90
|
@file_format.should be_valid
|
|
88
91
|
end
|
|
89
92
|
|
|
93
|
+
it "should have a different line definer than Rails" do
|
|
94
|
+
rails = RequestLogAnalyzer::FileFormat.load(:rails)
|
|
95
|
+
rails.class.line_definer.should_not == @file_format.class.line_definer
|
|
96
|
+
end
|
|
97
|
+
|
|
90
98
|
it "should parse a rendered line" do
|
|
91
99
|
info = @file_format.line_definitions[:rendered].match_for("Rendered layouts/_footer (2.9ms)", @request)
|
|
92
100
|
info[:render_file].should == 'layouts/_footer'
|
|
@@ -97,25 +105,25 @@ describe "RequestLogAnalyzer::FileFormat::RailsDevelopment - Rails with developm
|
|
|
97
105
|
info = @file_format.line_definitions[:query_executed].match_for(" [4;36;1mUser Load (0.4ms)[0m [0;1mSELECT * FROM `users` WHERE (`users`.`id` = 18205844) [0m", @request)
|
|
98
106
|
info[:query_class].should == 'User'
|
|
99
107
|
info[:query_duration].should == 0.0004
|
|
100
|
-
info[:query_sql].should == 'SELECT * FROM
|
|
108
|
+
info[:query_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
101
109
|
end
|
|
102
110
|
|
|
103
111
|
it "should parse a query executed line without colors" do
|
|
104
112
|
info = @file_format.line_definitions[:query_executed].match_for(" User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) ", @request)
|
|
105
113
|
info[:query_class].should == 'User'
|
|
106
114
|
info[:query_duration].should == 0.0004
|
|
107
|
-
info[:query_sql].should == 'SELECT * FROM
|
|
115
|
+
info[:query_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
108
116
|
end
|
|
109
117
|
|
|
110
118
|
it "should parse a cached query line with colors" do
|
|
111
119
|
info = @file_format.line_definitions[:query_cached].match_for(' [4;35;1mCACHE (0.0ms)[0m [0mSELECT * FROM `users` WHERE (`users`.`id` = 0) [0m', @request)
|
|
112
120
|
info[:cached_duration].should == 0.0
|
|
113
|
-
info[:cached_sql].should == 'SELECT * FROM
|
|
121
|
+
info[:cached_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
114
122
|
end
|
|
115
123
|
|
|
116
124
|
it "should parse a cached query line without colors" do
|
|
117
125
|
info = @file_format.line_definitions[:query_cached].match_for(' CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) ', @request)
|
|
118
126
|
info[:cached_duration].should == 0.0
|
|
119
|
-
info[:cached_sql].should == 'SELECT * FROM
|
|
127
|
+
info[:cached_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
120
128
|
end
|
|
121
129
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Anonymize, 'anonymize request' do
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@filter = RequestLogAnalyzer::Filter::Anonymize.new(testing_format)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should anonimize ip" do
|
|
11
|
+
@filter.filter(request(:ip => '123.123.123.123'))[:ip].should_not eql('123.123.123.123')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should anonimize url" do
|
|
15
|
+
@filter.filter(request(:url => 'https://test.mysite.com/employees'))[:url].should eql('http://example.com/employees')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should fuzz durations" do
|
|
19
|
+
@filter.filter(request(:duration => 100))[:duration].should_not eql(100)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Field, 'string in accept mode' do
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => 'test', :mode => :select)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should reject a request if the field value does not match" do
|
|
11
|
+
@filter.filter(request(:test => 'not test')).should be_nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should reject a request if the field name does not match" do
|
|
15
|
+
@filter.filter(request(:testing => 'test')).should be_nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should accept a request if the both name and value match" do
|
|
19
|
+
@filter.filter(request(:test => 'test')).should_not be_nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should accept a request if the value is not the first value" do
|
|
23
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'test'}])).should_not be_nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe RequestLogAnalyzer::Filter::Field, 'string in reject mode' do
|
|
28
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
29
|
+
|
|
30
|
+
before(:each) do
|
|
31
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => 'test', :mode => :reject)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should accept a request if the field value does not match" do
|
|
35
|
+
@filter.filter(request(:test => 'not test')).should_not be_nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should accept a request if the field name does not match" do
|
|
39
|
+
@filter.filter(request(:testing => 'test')).should_not be_nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should reject a request if the both name and value match" do
|
|
43
|
+
@filter.filter(request(:test => 'test')).should be_nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should reject a request if the value is not the first value" do
|
|
47
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'test'}])).should be_nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe RequestLogAnalyzer::Filter::Field, 'regexp in accept mode' do
|
|
52
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
53
|
+
|
|
54
|
+
before(:each) do
|
|
55
|
+
@filter = RequestLogAnalyzer::Filter::Field.new(testing_format, :field => :test, :value => '/test/', :mode => :select)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should reject a request if the field value does not match" do
|
|
59
|
+
@filter.filter(request(:test => 'a working test')).should_not be_nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should reject a request if the field name does not match" do
|
|
63
|
+
@filter.filter(request(:testing => 'test')).should be_nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "should accept a request if the value is not the first value" do
|
|
67
|
+
@filter.filter(request([{:test => 'ignore'}, {:test => 'testing 123'}])).should_not be_nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'both before and after' do
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :after => DateTime.parse('2009-01-01'), :before => DateTime.parse('2009-02-02'))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should reject a request before the after date" do
|
|
11
|
+
@filter.filter(request(:timestamp => 20081212000000)).should be_nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should reject a request after the before date" do
|
|
15
|
+
@filter.filter(request(:timestamp => 20090303000000)).should be_nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should accept a request between the after and before dates" do
|
|
19
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'only before' do
|
|
24
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
25
|
+
|
|
26
|
+
before(:each) do
|
|
27
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :before => DateTime.parse('2009-02-02'))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should accept a request before the after date" do
|
|
31
|
+
@filter.filter(request(:timestamp => 20081212000000)).should_not be_nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should reject a request after the before date" do
|
|
35
|
+
@filter.filter(request(:timestamp => 20090303000000)).should be_nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should accept a request between the after and before dates" do
|
|
39
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe RequestLogAnalyzer::Filter::Timespan, 'only after' do
|
|
44
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
45
|
+
|
|
46
|
+
before(:each) do
|
|
47
|
+
@filter = RequestLogAnalyzer::Filter::Timespan.new(testing_format, :after => DateTime.parse('2009-01-01'))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should reject a request before the after date" do
|
|
51
|
+
@filter.filter(request(:timestamp => 20081212000000)).should be_nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should accept a request after the before date" do
|
|
55
|
+
@filter.filter(request(:timestamp => 20090303000000)).should_not be_nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should accept a request between the after and before dates" do
|
|
59
|
+
@filter.filter(request(:timestamp => 20090102000000)).should_not be_nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::Source::LogParser, :requests do
|
|
4
|
-
include
|
|
4
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
5
5
|
|
|
6
6
|
before(:each) do
|
|
7
|
-
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
7
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(testing_format)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
it "should have multiple line definitions" do
|
|
@@ -16,13 +16,13 @@ describe RequestLogAnalyzer::Source::LogParser, :requests do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
it "should parse more lines than requests" do
|
|
19
|
-
@log_parser.should_receive(:handle_request).with(an_instance_of(
|
|
19
|
+
@log_parser.should_receive(:handle_request).with(an_instance_of(TestingFormat::Request)).twice
|
|
20
20
|
@log_parser.parse_file(log_fixture(:test_language_combined))
|
|
21
21
|
@log_parser.parsed_lines.should > 2
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
it "should parse requests spanned over multiple files" do
|
|
25
|
-
@log_parser.should_receive(:handle_request).with(an_instance_of(
|
|
25
|
+
@log_parser.should_receive(:handle_request).with(an_instance_of(TestingFormat::Request)).once
|
|
26
26
|
@log_parser.parse_files([log_fixture(:multiple_files_1), log_fixture(:multiple_files_2)])
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -47,10 +47,10 @@ describe RequestLogAnalyzer::Source::LogParser, :requests do
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
describe RequestLogAnalyzer::Source::LogParser, :warnings do
|
|
50
|
-
include
|
|
50
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
51
51
|
|
|
52
52
|
before(:each) do
|
|
53
|
-
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
53
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(testing_format, :parse_strategy => 'cautious')
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it "should warn about teaser matching problems" do
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require File.dirname(__FILE__) + '
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
|
|
3
3
|
describe RequestLogAnalyzer::Request, :incomplete_request do
|
|
4
4
|
|
|
5
|
-
include
|
|
5
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
6
6
|
|
|
7
7
|
before(:each) do
|
|
8
|
-
@incomplete_request =
|
|
8
|
+
@incomplete_request = testing_format.request
|
|
9
9
|
@incomplete_request << { :line_type => :test, :lineno => 1, :test_capture => 'awesome!' }
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -34,10 +34,10 @@ end
|
|
|
34
34
|
|
|
35
35
|
describe RequestLogAnalyzer::Request, :completed_request do
|
|
36
36
|
|
|
37
|
-
include
|
|
37
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
38
38
|
|
|
39
39
|
before(:each) do
|
|
40
|
-
@completed_request =
|
|
40
|
+
@completed_request = testing_format.request
|
|
41
41
|
@completed_request << { :line_type => :first, :lineno => 1, :name => 'first line!' }
|
|
42
42
|
@completed_request << { :line_type => :test, :lineno => 4, :test_capture => 'testing' }
|
|
43
43
|
@completed_request << { :line_type => :test, :lineno => 7, :test_capture => 'testing some more' }
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Tracker::Duration, 'static category' do
|
|
4
|
+
|
|
5
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
6
|
+
|
|
7
|
+
before(:each) do
|
|
8
|
+
@tracker = RequestLogAnalyzer::Tracker::Duration.new(:duration => :duration, :category => :category)
|
|
9
|
+
@tracker.prepare
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should register a request in the right category" do
|
|
13
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
14
|
+
@tracker.categories.keys.should include('a')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should register a hit in the right category" do
|
|
18
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
19
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
20
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
21
|
+
|
|
22
|
+
@tracker.hits('a').should == 1
|
|
23
|
+
@tracker.hits('b').should == 2
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should sum the durations of the same category as cumulative duration" do
|
|
27
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
28
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
29
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
30
|
+
|
|
31
|
+
@tracker.cumulative_duration('a').should == 0.2
|
|
32
|
+
@tracker.cumulative_duration('b').should == 0.7
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should calculate the average duration correctly" do
|
|
36
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
37
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
38
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
39
|
+
|
|
40
|
+
@tracker.average_duration('a').should == 0.2
|
|
41
|
+
@tracker.average_duration('b').should == 0.35
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should set min and max duration correctly" do
|
|
45
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
46
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
47
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
48
|
+
|
|
49
|
+
@tracker.min_duration('b').should == 0.3
|
|
50
|
+
@tracker.max_duration('b').should == 0.4
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe RequestLogAnalyzer::Tracker::Duration, 'dynamic category' do
|
|
56
|
+
|
|
57
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
58
|
+
|
|
59
|
+
before(:each) do
|
|
60
|
+
@categorizer = Proc.new { |request| request[:duration] > 0.2 ? 'slow' : 'fast' }
|
|
61
|
+
@tracker = RequestLogAnalyzer::Tracker::Duration.new(:duration => :duration, :category => @categorizer)
|
|
62
|
+
@tracker.prepare
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should use the categorizer to determine the right category" do
|
|
66
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
67
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
68
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
69
|
+
|
|
70
|
+
@tracker.cumulative_duration('fast').should == 0.2
|
|
71
|
+
@tracker.cumulative_duration('slow').should == 0.7
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe RequestLogAnalyzer::Tracker::Duration, 'reporting' do
|
|
77
|
+
|
|
78
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
79
|
+
|
|
80
|
+
before(:each) do
|
|
81
|
+
@tracker = RequestLogAnalyzer::Tracker::Duration.new(:category => :category, :duration => :duration)
|
|
82
|
+
@tracker.prepare
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should generate a report without errors when one category is present" do
|
|
86
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
87
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should generate a report without errors when no category is present" do
|
|
91
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should generate a report without errors when multiple categories are present" do
|
|
95
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
96
|
+
@tracker.update(request(:category => 'b', :duration => 0.2))
|
|
97
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Tracker::Frequency, 'static category' do
|
|
4
|
+
|
|
5
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
6
|
+
|
|
7
|
+
before(:each) do
|
|
8
|
+
@tracker = RequestLogAnalyzer::Tracker::Frequency.new(:category => :category)
|
|
9
|
+
@tracker.prepare
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
it "should register a request in the right category" do
|
|
14
|
+
@tracker.update(request(:category => 'a', :blah => 0.2))
|
|
15
|
+
@tracker.frequencies.keys.should include('a')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should register a request in the right category" do
|
|
19
|
+
@tracker.update(request(:category => 'a', :blah => 0.2))
|
|
20
|
+
@tracker.update(request(:category => 'b', :blah => 0.2))
|
|
21
|
+
@tracker.update(request(:category => 'b', :blah => 0.2))
|
|
22
|
+
|
|
23
|
+
@tracker.frequency('a').should == 1
|
|
24
|
+
@tracker.frequency('b').should == 2
|
|
25
|
+
@tracker.overall_frequency.should == 3
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should sort correctly by frequency" do
|
|
29
|
+
@tracker.update(request(:category => 'a', :blah => 0.2))
|
|
30
|
+
@tracker.update(request(:category => 'b', :blah => 0.2))
|
|
31
|
+
@tracker.update(request(:category => 'b', :blah => 0.2))
|
|
32
|
+
|
|
33
|
+
@tracker.sorted_by_frequency.should == [['b', 2], ['a', 1]]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe RequestLogAnalyzer::Tracker::Frequency, 'dynamic category' do
|
|
38
|
+
|
|
39
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
40
|
+
|
|
41
|
+
before(:each) do
|
|
42
|
+
@categorizer = Proc.new { |request| request[:duration] > 0.2 ? 'slow' : 'fast' }
|
|
43
|
+
@tracker = RequestLogAnalyzer::Tracker::Frequency.new(:category => @categorizer)
|
|
44
|
+
@tracker.prepare
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should use the categorizer to determine the right category" do
|
|
48
|
+
@tracker.update(request(:category => 'a', :duration => 0.2))
|
|
49
|
+
@tracker.update(request(:category => 'b', :duration => 0.3))
|
|
50
|
+
@tracker.update(request(:category => 'b', :duration => 0.4))
|
|
51
|
+
|
|
52
|
+
@tracker.frequency('fast').should == 1
|
|
53
|
+
@tracker.frequency('slow').should == 2
|
|
54
|
+
@tracker.frequency('moderate').should == 0
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
describe RequestLogAnalyzer::Tracker::Frequency, 'reporting' do
|
|
61
|
+
|
|
62
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
63
|
+
|
|
64
|
+
before(:each) do
|
|
65
|
+
@tracker = RequestLogAnalyzer::Tracker::Frequency.new(:category => :category)
|
|
66
|
+
@tracker.prepare
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should generate a report without errors when one category is present" do
|
|
70
|
+
@tracker.update(request(:category => 'a', :blah => 0.2))
|
|
71
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should generate a report without errors when no category is present" do
|
|
75
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should generate a report without errors when multiple categories are present" do
|
|
79
|
+
@tracker.update(request(:category => 'a', :blah => 0.2))
|
|
80
|
+
@tracker.update(request(:category => 'b', :blah => 0.2))
|
|
81
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::Tracker::HourlySpread do
|
|
4
|
+
|
|
5
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
6
|
+
|
|
7
|
+
before(:each) do
|
|
8
|
+
@tracker = RequestLogAnalyzer::Tracker::HourlySpread.new
|
|
9
|
+
@tracker.prepare
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should store timestamps correctly" do
|
|
13
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
14
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
15
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
16
|
+
|
|
17
|
+
@tracker.request_time_graph[0].should eql(3)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should count the number of timestamps correctly" do
|
|
21
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
22
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
23
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
24
|
+
@tracker.update(request(:timestamp => 20090103010000))
|
|
25
|
+
|
|
26
|
+
@tracker.total_requests.should eql(4)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should set the first request timestamp correctly" do
|
|
30
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
31
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
32
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
33
|
+
|
|
34
|
+
@tracker.first_timestamp.should == DateTime.parse('Januari 1, 2009 00:00:00')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should set the last request timestamp correctly" do
|
|
38
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
39
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
40
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
41
|
+
|
|
42
|
+
@tracker.last_timestamp.should == DateTime.parse('Januari 3, 2009 00:00:00')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should return the correct timespan in days when multiple requests are given" do
|
|
46
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
47
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
48
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
49
|
+
|
|
50
|
+
@tracker.timespan.should == 2
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe RequestLogAnalyzer::Tracker::HourlySpread, 'reporting' do
|
|
56
|
+
|
|
57
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
58
|
+
|
|
59
|
+
before(:each) do
|
|
60
|
+
@tracker = RequestLogAnalyzer::Tracker::HourlySpread.new
|
|
61
|
+
@tracker.prepare
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should generate a report without errors when no request was tracked" do
|
|
65
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should generate a report without errors when multiple requests were tracked" do
|
|
69
|
+
@tracker.update(request(:timestamp => 20090102000000))
|
|
70
|
+
@tracker.update(request(:timestamp => 20090101000000))
|
|
71
|
+
@tracker.update(request(:timestamp => 20090103000000))
|
|
72
|
+
@tracker.update(request(:timestamp => 20090103010000))
|
|
73
|
+
lambda { @tracker.report(mock_output) }.should_not raise_error
|
|
74
|
+
end
|
|
75
|
+
end
|