request-log-analyzer 1.1.1 → 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 -38
- 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 +22 -16
- data/lib/request_log_analyzer/controller.rb +21 -5
- data/lib/request_log_analyzer/file_format/merb.rb +22 -9
- data/lib/request_log_analyzer/file_format/rails.rb +37 -23
- data/lib/request_log_analyzer/file_format/rails_development.rb +33 -88
- data/lib/request_log_analyzer/file_format.rb +50 -18
- data/lib/request_log_analyzer/filter/{anonimize.rb → anonymize.rb} +3 -8
- data/lib/request_log_analyzer/filter/field.rb +7 -6
- data/lib/request_log_analyzer/filter/timespan.rb +7 -3
- data/lib/request_log_analyzer/filter.rb +0 -4
- data/lib/request_log_analyzer/line_definition.rb +22 -88
- data/lib/request_log_analyzer/log_processor.rb +5 -25
- 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 +62 -4
- data/lib/request_log_analyzer/source/database.rb +76 -0
- data/lib/request_log_analyzer/source/log_parser.rb +104 -52
- 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/{category.rb → frequency.rb} +24 -12
- 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/lib/testing_format.rb +39 -0
- data/spec/spec_helper.rb +5 -25
- 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/unit/controller/log_processor_spec.rb +20 -0
- data/spec/{file_format_spec.rb → unit/file_format/file_format_api_spec.rb} +18 -6
- data/spec/unit/file_format/line_definition_spec.rb +64 -0
- data/spec/{merb_format_spec.rb → unit/file_format/merb_format_spec.rb} +3 -3
- data/spec/{rails_format_spec.rb → unit/file_format/rails_format_spec.rb} +24 -15
- 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} +9 -10
- 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 +56 -28
- data/spec/controller_spec.rb +0 -45
- data/spec/file_formats/spec_format.rb +0 -27
- data/spec/filter_spec.rb +0 -157
- data/spec/line_definition_spec.rb +0 -124
- data/spec/log_processor_spec.rb +0 -57
- data/spec/summarizer_spec.rb +0 -9
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'request_log_analyzer/log_processor'
|
|
4
|
+
|
|
5
|
+
describe RequestLogAnalyzer::LogProcessor, 'stripping log files' do
|
|
6
|
+
|
|
7
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
8
|
+
|
|
9
|
+
before(:each) do
|
|
10
|
+
@log_stripper = RequestLogAnalyzer::LogProcessor.new(testing_format, :strip, {})
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should remove a junk line" do
|
|
14
|
+
@log_stripper.strip_line("junk line\n").should be_empty
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should keep a teaser line intact" do
|
|
18
|
+
@log_stripper.strip_line("processing 1234\n").should be_empty
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -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
|
|
|
@@ -50,20 +50,31 @@ describe RequestLogAnalyzer::FileFormat, :format_definition do
|
|
|
50
50
|
line.first_test :regexp => /test/, :captures => []
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
|
|
53
54
|
@second_file_format.format_definition do |line|
|
|
54
55
|
line.second_test :regexp => /test/, :captures => []
|
|
55
56
|
end
|
|
56
57
|
|
|
58
|
+
@first_file_format.line_definer.should_not eql(@second_file_format.line_definer)
|
|
57
59
|
@first_file_format.new.should have(1).line_definitions
|
|
58
|
-
@first_file_format.new.line_definitions[:first_test].should_not be_nil
|
|
59
|
-
@second_file_format.new.should have(1).line_definitions
|
|
60
60
|
@second_file_format.new.line_definitions[:second_test].should_not be_nil
|
|
61
61
|
end
|
|
62
62
|
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
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe RequestLogAnalyzer::LineDefinition, :parsing 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
|
+
it "should return false on an unmatching line" do
|
|
14
|
+
(@line_definition =~ "nonmatching").should be_false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should return false when only the teaser matches" do
|
|
18
|
+
(@line_definition =~ "Testing LineDefinition").should be_false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should return a hash if the line matches" do
|
|
22
|
+
(@line_definition =~ "Testing LineDefinition, tries: 123").should be_kind_of(Hash)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should return a hash with :captures set to an array" do
|
|
26
|
+
hash = @line_definition.matches("Testing LineDefinition, tries: 123")
|
|
27
|
+
hash[:captures][0].should == "LineDefinition"
|
|
28
|
+
hash[:captures][1].should == "123"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should return a hash with :line_definition set" do
|
|
32
|
+
@line_definition.matches("Testing LineDefinition, tries: 123")[:line_definition].should == @line_definition
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe RequestLogAnalyzer::LineDefinition, :converting do
|
|
37
|
+
|
|
38
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
39
|
+
|
|
40
|
+
before(:each) do
|
|
41
|
+
@file_format = testing_format
|
|
42
|
+
@request = @file_format.request
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should convert captures to a hash of converted values" do
|
|
46
|
+
hash = @file_format.line_definitions[:first].convert_captured_values(["456"], @request)
|
|
47
|
+
hash[:request_no].should == 456
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should convert captures to a hash" do
|
|
51
|
+
hash = @file_format.line_definitions[:test].convert_captured_values(["great", nil], @request)
|
|
52
|
+
hash[:test_capture].should == 'Testing is great'
|
|
53
|
+
hash[:duration].should be_nil
|
|
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
|
|
62
|
+
|
|
63
|
+
|
|
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))
|
|
@@ -29,7 +29,7 @@ describe RequestLogAnalyzer::Source::LogParser, :merb do
|
|
|
29
29
|
@log_parser.parse_file(log_fixture(:merb)) { |found_request| request ||= found_request }
|
|
30
30
|
|
|
31
31
|
request.should be_completed
|
|
32
|
-
|
|
32
|
+
request[:timestamp].should == 20080829111023 # 'Fri Aug 29 11:10:23 +0200 2008'
|
|
33
33
|
request[:dispatch_time].should == 0.243424
|
|
34
34
|
request[:after_filters_time].should == 6.9e-05
|
|
35
35
|
request[:before_filters_time].should == 0.213213
|
|
@@ -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,55 +67,63 @@ 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)
|
|
86
|
+
@request = @file_format.request
|
|
83
87
|
end
|
|
84
88
|
|
|
85
89
|
it "should have a valid language definitions" do
|
|
86
90
|
@file_format.should be_valid
|
|
87
91
|
end
|
|
88
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
|
+
|
|
89
98
|
it "should parse a rendered line" do
|
|
90
|
-
info = @file_format.line_definitions[:rendered].
|
|
99
|
+
info = @file_format.line_definitions[:rendered].match_for("Rendered layouts/_footer (2.9ms)", @request)
|
|
91
100
|
info[:render_file].should == 'layouts/_footer'
|
|
92
101
|
info[:render_duration].should == 0.0029
|
|
93
102
|
end
|
|
94
103
|
|
|
95
104
|
it "should parse a query executed line with colors" do
|
|
96
|
-
info = @file_format.line_definitions[:query_executed].
|
|
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)
|
|
97
106
|
info[:query_class].should == 'User'
|
|
98
107
|
info[:query_duration].should == 0.0004
|
|
99
|
-
info[:query_sql].should == 'SELECT * FROM
|
|
108
|
+
info[:query_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
100
109
|
end
|
|
101
110
|
|
|
102
111
|
it "should parse a query executed line without colors" do
|
|
103
|
-
info = @file_format.line_definitions[:query_executed].
|
|
112
|
+
info = @file_format.line_definitions[:query_executed].match_for(" User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 18205844) ", @request)
|
|
104
113
|
info[:query_class].should == 'User'
|
|
105
114
|
info[:query_duration].should == 0.0004
|
|
106
|
-
info[:query_sql].should == 'SELECT * FROM
|
|
115
|
+
info[:query_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
107
116
|
end
|
|
108
117
|
|
|
109
118
|
it "should parse a cached query line with colors" do
|
|
110
|
-
info = @file_format.line_definitions[:query_cached].
|
|
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)
|
|
111
120
|
info[:cached_duration].should == 0.0
|
|
112
|
-
info[:cached_sql].should == 'SELECT * FROM
|
|
121
|
+
info[:cached_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
113
122
|
end
|
|
114
123
|
|
|
115
124
|
it "should parse a cached query line without colors" do
|
|
116
|
-
info = @file_format.line_definitions[:query_cached].
|
|
125
|
+
info = @file_format.line_definitions[:query_cached].match_for(' CACHE (0.0ms) SELECT * FROM `users` WHERE (`users`.`id` = 0) ', @request)
|
|
117
126
|
info[:cached_duration].should == 0.0
|
|
118
|
-
info[:cached_sql].should == 'SELECT * FROM
|
|
127
|
+
info[:cached_sql].should == 'SELECT * FROM users WHERE (users.id = :int)'
|
|
119
128
|
end
|
|
120
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,22 +16,21 @@ 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
|
|
|
29
29
|
it "should parse all request values when spanned over multiple files" do
|
|
30
30
|
@log_parser.parse_files([log_fixture(:multiple_files_1), log_fixture(:multiple_files_2)]) do |request|
|
|
31
|
-
request.lines.should have(4).items
|
|
32
|
-
|
|
31
|
+
request.lines.should have(4).items
|
|
33
32
|
request[:request_no].should == 1
|
|
34
|
-
request[:test_capture].should == "amazing"
|
|
33
|
+
request[:test_capture].should == "Testing is amazing" # Note the custom converter
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
|
|
@@ -48,10 +47,10 @@ describe RequestLogAnalyzer::Source::LogParser, :requests do
|
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
describe RequestLogAnalyzer::Source::LogParser, :warnings do
|
|
51
|
-
include
|
|
50
|
+
include RequestLogAnalyzer::Spec::Helper
|
|
52
51
|
|
|
53
52
|
before(:each) do
|
|
54
|
-
@log_parser = RequestLogAnalyzer::Source::LogParser.new(
|
|
53
|
+
@log_parser = RequestLogAnalyzer::Source::LogParser.new(testing_format, :parse_strategy => 'cautious')
|
|
55
54
|
end
|
|
56
55
|
|
|
57
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
|