wvanbergen-request-log-analyzer 1.2.9 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/bin/request-log-analyzer +33 -19
  2. data/lib/cli/database_console.rb +26 -0
  3. data/lib/cli/database_console_init.rb +42 -0
  4. data/lib/cli/tools.rb +1 -1
  5. data/lib/request_log_analyzer/aggregator/database_inserter.rb +81 -0
  6. data/lib/request_log_analyzer/aggregator/summarizer.rb +2 -2
  7. data/lib/request_log_analyzer/aggregator.rb +4 -0
  8. data/lib/request_log_analyzer/controller.rb +23 -7
  9. data/lib/request_log_analyzer/database/base.rb +114 -0
  10. data/lib/request_log_analyzer/database/connection.rb +38 -0
  11. data/lib/request_log_analyzer/database.rb +177 -0
  12. data/lib/request_log_analyzer/file_format.rb +6 -3
  13. data/lib/request_log_analyzer/mailer.rb +46 -0
  14. data/lib/request_log_analyzer/request.rb +2 -1
  15. data/lib/request_log_analyzer/source/{database.rb → database_loader.rb} +1 -1
  16. data/lib/request_log_analyzer/source/log_parser.rb +28 -15
  17. data/lib/request_log_analyzer/source.rb +7 -2
  18. data/lib/request_log_analyzer.rb +5 -8
  19. data/request-log-analyzer.gemspec +8 -8
  20. data/spec/database.yml +17 -0
  21. data/spec/fixtures/rails.db +0 -0
  22. data/spec/integration/command_line_usage_spec.rb +14 -9
  23. data/spec/lib/macros.rb +16 -0
  24. data/spec/lib/mocks.rb +18 -6
  25. data/spec/unit/aggregator/database_inserter_spec.rb +93 -0
  26. data/spec/unit/database/base_class_spec.rb +190 -0
  27. data/spec/unit/database/connection_spec.rb +34 -0
  28. data/spec/unit/database/database_spec.rb +138 -0
  29. data/spec/unit/source/log_parser_spec.rb +12 -0
  30. metadata +29 -17
  31. data/lib/request_log_analyzer/aggregator/database.rb +0 -220
  32. data/spec/spec.opts +0 -3
  33. data/spec/unit/aggregator/database_spec.rb +0 -245
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RequestLogAnalyzer::Aggregator::DatabaseInserter do
4
+
5
+ before(:all) do
6
+ @log_parser = RequestLogAnalyzer::Source::LogParser.new(testing_format)
7
+ end
8
+
9
+ # The prepare method is called before the parsing starts. It should establish a connection
10
+ # to a database that is suitable for inserting requests later on.
11
+ describe '#prepare' do
12
+
13
+ before(:each) do
14
+ @database = mock_database(:create_database_schema!, :drop_database_schema!, :file_format=)
15
+ @database_inserter = RequestLogAnalyzer::Aggregator::DatabaseInserter.new(@log_parser)
16
+ RequestLogAnalyzer::Database.stub!(:new).and_return(@database)
17
+ end
18
+
19
+ it 'should establish the database connection' do
20
+ RequestLogAnalyzer::Database.should_receive(:new).and_return(@database)
21
+ @database_inserter.prepare
22
+ end
23
+
24
+ it "should set the file_format" do
25
+ @database.should_receive(:file_format=).with(testing_format)
26
+ @database_inserter.prepare
27
+ end
28
+
29
+ it 'should create the database schema during preparation' do
30
+ @database.should_receive(:create_database_schema!)
31
+ @database_inserter.prepare
32
+ end
33
+
34
+ it 'should not drop the database schema during preparation if not requested' do
35
+ @database.should_not_receive(:drop_database_schema!)
36
+ @database_inserter.prepare
37
+ end
38
+
39
+ it 'should drop the database schema during preparation if requested' do
40
+ @database_inserter.options[:reset_database] = true
41
+ @database.should_receive(:drop_database_schema!)
42
+ @database_inserter.prepare
43
+ end
44
+ end
45
+
46
+ test_databases.each do |name, connection|
47
+
48
+ context "using a #{name} database" do
49
+
50
+ before(:each) do
51
+ @database_inserter = RequestLogAnalyzer::Aggregator::DatabaseInserter.new(@log_parser, :database => connection, :reset_database => true)
52
+ @database_inserter.prepare
53
+
54
+ @incomplete_request = testing_format.request( {:line_type => :first, :request_no => 564})
55
+ @completed_request = testing_format.request( {:line_type => :first, :request_no => 564},
56
+ {:line_type => :test, :test_capture => "awesome"},
57
+ {:line_type => :test, :test_capture => "indeed"},
58
+ {:line_type => :eval, :evaluated => { :greating => 'howdy'}, :greating => 'howdy' },
59
+ {:line_type => :last, :request_no => 564})
60
+ end
61
+
62
+ after(:each) do
63
+ @database_inserter.database.send :remove_orm_classes!
64
+ end
65
+
66
+ it "should insert a record in the request table" do
67
+ lambda {
68
+ @database_inserter.aggregate(@incomplete_request)
69
+ }.should change(@database_inserter.database.request_class, :count).from(0).to(1)
70
+ end
71
+
72
+ it "should insert a record in the first_lines table" do
73
+ lambda {
74
+ @database_inserter.aggregate(@incomplete_request)
75
+ }.should change(@database_inserter.database.get_class(:first), :count).from(0).to(1)
76
+ end
77
+
78
+ it "should insert records in all relevant line tables" do
79
+ @database_inserter.aggregate(@completed_request)
80
+ request = @database_inserter.database.request_class.first
81
+ request.should have(2).test_lines
82
+ request.should have(1).first_lines
83
+ request.should have(1).eval_lines
84
+ request.should have(1).last_lines
85
+ end
86
+
87
+ it "should log a warning in the warnings table" do
88
+ @database_inserter.database.warning_class.should_receive(:create!).with(hash_including(:warning_type => 'test_warning'))
89
+ @database_inserter.warning(:test_warning, "Testing the warning system", 12)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,190 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RequestLogAnalyzer::Database::Base do
4
+
5
+ describe '.subclass_from_line_definition' do
6
+ before(:all) do
7
+ @line_definition = RequestLogAnalyzer::LineDefinition.new(:test, { :regexp => /Testing (\w+), tries\: (\d+)/,
8
+ :captures => [{ :name => :what, :type => :string }, { :name => :tries, :type => :integer },
9
+ { :name => :evaluated, :type => :hash, :provides => {:evaluated_field => :duration} }]})
10
+ end
11
+
12
+ before(:each) do
13
+ @orm_class = mock('Line ActiveRecord::Base class')
14
+ @orm_class.stub!(:set_table_name)
15
+ @orm_class.stub!(:belongs_to)
16
+ @orm_class.stub!(:serialize)
17
+ @orm_class.stub!(:line_definition=)
18
+ Class.stub!(:new).with(RequestLogAnalyzer::Database::Base).and_return(@orm_class)
19
+
20
+ @request_class = mock('Request ActiveRecord::Base class')
21
+ @request_class.stub!(:has_many)
22
+ @source_class = mock('Source ActiveRecord::Base class')
23
+ @source_class.stub!(:has_many)
24
+
25
+ @database = mock_database
26
+ @database.stub!(:request_class).and_return(@request_class)
27
+ @database.stub!(:source_class).and_return(@source_class)
28
+ RequestLogAnalyzer::Database::Base.stub!(:database).and_return(@database)
29
+ end
30
+
31
+ it "should create a new subclass using the Base class as parent" do
32
+ Class.should_receive(:new).with(RequestLogAnalyzer::Database::Base).and_return(@orm_class)
33
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
34
+ end
35
+
36
+ it "should store the LineDefinition" do
37
+ @orm_class.should_receive(:line_definition=).with(@line_definition)
38
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
39
+ end
40
+
41
+ it "should set the table name for the subclass" do
42
+ @orm_class.should_receive(:set_table_name).with('test_lines')
43
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
44
+ end
45
+
46
+ it "should set the :belongs_to relationship with the Request class" do
47
+ @orm_class.should_receive(:belongs_to).with(:request)
48
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
49
+ end
50
+
51
+ it "should set a :has_many relationship in the request class" do
52
+ @request_class.should_receive(:has_many).with(:test_lines)
53
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
54
+ end
55
+
56
+ it "should set a :has_many relationship in the source class" do
57
+ @source_class.should_receive(:has_many).with(:test_lines)
58
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
59
+ end
60
+
61
+ it "should set the :belongs_to relationship with the Source class" do
62
+ @orm_class.should_receive(:belongs_to).with(:source)
63
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
64
+ end
65
+
66
+ it "should serialize a complex field" do
67
+ @orm_class.should_receive(:serialize).with(:evaluated, Hash)
68
+ RequestLogAnalyzer::Database::Base.subclass_from_line_definition(@line_definition)
69
+ end
70
+
71
+ end
72
+
73
+ describe '.subclass_from_table' do
74
+ before(:each) do
75
+
76
+ @request_class = mock('Request ActiveRecord::Base class')
77
+ @request_class.stub!(:has_many)
78
+ @source_class = mock('Source ActiveRecord::Base class')
79
+ @source_class.stub!(:has_many)
80
+
81
+ @database = mock_database
82
+ @database.stub!(:request_class).and_return(@request_class)
83
+ @database.stub!(:source_class).and_return(@source_class)
84
+ @database.connection.stub!(:table_exists?).and_return(true)
85
+ RequestLogAnalyzer::Database::Base.stub!(:database).and_return(@database)
86
+
87
+ @klass = mock('ActiveRecord ORM class')
88
+ @klass.stub!(:column_names).and_return(['id', 'request_id', 'source_id', 'lineno', 'duration'])
89
+ @klass.stub!(:set_table_name)
90
+ @klass.stub!(:belongs_to)
91
+ Class.stub!(:new).with(RequestLogAnalyzer::Database::Base).and_return(@klass)
92
+ end
93
+
94
+ it "should create a new subclass using the Base class as parent" do
95
+ Class.should_receive(:new).with(RequestLogAnalyzer::Database::Base).and_return(@klass)
96
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
97
+ end
98
+
99
+ it "should set the table name" do
100
+ @klass.should_receive(:set_table_name).with('completed_lines')
101
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
102
+ end
103
+
104
+ it "should create the :belongs_to relation to the request class" do
105
+ @klass.should_receive(:belongs_to).with(:request)
106
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
107
+ end
108
+
109
+ it "should create the :has_many relation in the request class" do
110
+ @request_class.should_receive(:has_many).with(:completed_lines)
111
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
112
+ end
113
+
114
+ it "should create the :belongs_to relation to the source class" do
115
+ @klass.should_receive(:belongs_to).with(:source)
116
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
117
+ end
118
+
119
+ it "should create the :has_many relation in the request class" do
120
+ @source_class.should_receive(:has_many).with(:completed_lines)
121
+ RequestLogAnalyzer::Database::Base.subclass_from_table('completed_lines')
122
+ end
123
+
124
+ end
125
+
126
+ describe '#create_table' do
127
+
128
+ before(:all) do
129
+ @line_definition = RequestLogAnalyzer::LineDefinition.new(:test, { :regexp => /Testing (\w+), tries\: (\d+)/,
130
+ :captures => [{ :name => :what, :type => :string }, { :name => :tries, :type => :integer },
131
+ { :name => :evaluated, :type => :hash, :provides => {:evaluated_field => :duration} }]})
132
+ end
133
+
134
+ before(:each) do
135
+ @database = RequestLogAnalyzer::Database.new
136
+ @database.stub!(:connection).and_return(mock_connection)
137
+ @klass = @database.load_activerecord_class(@line_definition)
138
+ @klass.stub!(:table_exists?).and_return(false)
139
+ end
140
+
141
+ after(:each) do
142
+ @klass.drop_table!
143
+ @database.remove_orm_classes!
144
+ end
145
+
146
+ it "should call create_table with the correct table name" do
147
+ @database.connection.should_receive(:create_table).with(:test_lines)
148
+ @klass.create_table!
149
+ end
150
+
151
+ it "should not create a table based on the line type name if it already exists" do
152
+ @klass.stub!(:table_exists?).and_return(true)
153
+ @database.connection.should_not_receive(:create_table).with(:test_lines)
154
+ @klass.create_table!
155
+ end
156
+
157
+ it "should create an index on the request_id field" do
158
+ @database.connection.should_receive(:add_index).with(:test_lines, [:request_id])
159
+ @klass.create_table!
160
+ end
161
+
162
+ it "should create an index on the source_id field" do
163
+ @database.connection.should_receive(:add_index).with(:test_lines, [:source_id])
164
+ @klass.create_table!
165
+ end
166
+
167
+ it "should create a request_id field to link the requests together" do
168
+ @database.connection.table_creator.should_receive(:column).with(:request_id, :integer)
169
+ @klass.create_table!
170
+ end
171
+
172
+ it "should create a lineno field to save the location of the line in the original file" do
173
+ @database.connection.table_creator.should_receive(:column).with(:lineno, :integer)
174
+ @klass.create_table!
175
+ end
176
+
177
+ it "should create a field of the correct type for every defined capture field" do
178
+ @database.connection.table_creator.should_receive(:column).with(:what, :string)
179
+ @database.connection.table_creator.should_receive(:column).with(:tries, :integer)
180
+ @database.connection.table_creator.should_receive(:column).with(:evaluated, :text)
181
+ @klass.create_table!
182
+ end
183
+
184
+ it "should create a field of the correct type for every provided field" do
185
+ @database.connection.table_creator.should_receive(:column).with(:evaluated_field, :double)
186
+ @klass.create_table!
187
+ end
188
+ end
189
+ end
190
+
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RequestLogAnalyzer::Database::Connection do
4
+ describe '.from_string' do
5
+
6
+ it "should parse a name-value based string" do
7
+ string = 'adapter=sqlite3;database=filename.db'
8
+ RequestLogAnalyzer::Database::Connection.from_string(string).should == {:adapter => 'sqlite3', :database => 'filename.db'}
9
+ end
10
+
11
+ it "should parse an URI-based string for SQLite3" do
12
+ string = 'sqlite3://filename.db'
13
+ RequestLogAnalyzer::Database::Connection.from_string(string).should == {:adapter => 'sqlite3', :database => 'filename.db'}
14
+ end
15
+
16
+ it "should parse an URI-based string for MySQL" do
17
+ string = 'mysql://localhost.local/database'
18
+ RequestLogAnalyzer::Database::Connection.from_string(string).should ==
19
+ { :adapter => 'mysql', :database => 'database', :host => 'localhost.local' }
20
+ end
21
+
22
+ it "should parse an URI-based string for MySQL with only username" do
23
+ string = 'mysql://username@localhost.local/database'
24
+ RequestLogAnalyzer::Database::Connection.from_string(string).should ==
25
+ { :adapter => 'mysql', :database => 'database', :host => 'localhost.local', :username => 'username' }
26
+ end
27
+
28
+ it "should parse an URI-based string for MySQL with username and password" do
29
+ string = 'mysql://username:password@localhost.local/database'
30
+ RequestLogAnalyzer::Database::Connection.from_string(string).should ==
31
+ { :adapter => 'mysql', :database => 'database', :host => 'localhost.local', :username => 'username', :password => 'password' }
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,138 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe RequestLogAnalyzer::Database do
4
+
5
+ describe '#load_database_schema!' do
6
+
7
+ context 'for a Rails request database' do
8
+ before(:each) do
9
+ @database = RequestLogAnalyzer::Database.new(log_fixture(:rails, :db))
10
+ @database.load_database_schema!
11
+ end
12
+
13
+ after(:each) { @database.remove_orm_classes! }
14
+
15
+ # FileFormat-agnostic classes
16
+ default_orm_class_names.each do |const|
17
+ it "should create the default #{const} constant" do
18
+ Object.const_defined?(const).should be_true
19
+ end
20
+
21
+ it "should create the default #{const} class inheriting from ActiveRecord::Base and RequestLogAnalyzer::Database::Base" do
22
+ Object.const_get(const).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
23
+ end
24
+ end
25
+
26
+ # Some Fileformat-specific classes
27
+ ['CompletedLine', 'ProcessingLine'].each do |const|
28
+ it "should create the #{const} constant" do
29
+ Object.const_defined?(const).should be_true
30
+ end
31
+
32
+ it "should create the #{const} class inheriting from ActiveRecord::Base and RequestLogAnalyzer::Database::Base" do
33
+ Object.const_get(const).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
34
+ end
35
+
36
+ it "should create a :belongs_to relation from the #{const} class to Request and Source" do
37
+ Object.const_get(const).send(:reflections).should include(:request, :source)
38
+ end
39
+
40
+ it "should create a :has_many relation from the Request and Source class to the #{const} class" do
41
+ @database.request_class.send(:reflections).should include(const.underscore.pluralize.to_sym)
42
+ @database.source_class.send(:reflections).should include(const.underscore.pluralize.to_sym)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#create_database_schema!' do
49
+
50
+ before(:each) do
51
+ @database = RequestLogAnalyzer::Database.new
52
+ @database.file_format = testing_format
53
+ @database.stub!(:connection).and_return(mock_connection)
54
+
55
+ # Stub the expected method calls for the preparation, these will be tested separately
56
+ @mock_class = Class.new(RequestLogAnalyzer::Database::Base)
57
+ @mock_class.stub!(:create_table!)
58
+ end
59
+
60
+ after(:each) { @database.remove_orm_classes! }
61
+
62
+ default_orm_class_names.each do |klass|
63
+ it "should create a table for the default #{klass} class" do
64
+ @database.connection.should_receive(:create_table).with(klass.underscore.pluralize.to_sym)
65
+ @database.send :create_database_schema!
66
+ end
67
+
68
+ it "should create a #{klass} class inheriting from ActiveRecord and the base class of the ORM module" do
69
+ @database.send :create_database_schema!
70
+ @database.send("#{klass.underscore}_class".to_sym).ancestors.should include(ActiveRecord::Base, RequestLogAnalyzer::Database::Base)
71
+ end
72
+ end
73
+
74
+ testing_format.line_definitions.each do |name, definition|
75
+
76
+ it "should create the #{(name.to_s + '_line').camelize} class for #{name.inspect} lines" do
77
+ @database.send :create_database_schema!
78
+ Object.const_defined?("#{name}_line".camelize).should be_true
79
+ end
80
+
81
+ it "should create the #{name.to_s + '_lines'} table for the parsed #{name.inspect} lines" do
82
+ @database.connection.should_receive(:create_table).with("#{name}_lines".to_sym)
83
+ @database.send :create_database_schema!
84
+ end
85
+ end
86
+ end
87
+
88
+ describe '#load_activerecord_class' do
89
+
90
+ before(:each) do
91
+ @database = RequestLogAnalyzer::Database.new
92
+ @connection = mock_connection
93
+ @database.stub!(:connection).and_return(@connection)
94
+
95
+ # Mock the request ORM class
96
+ @request_class = mock('Request ActiveRecord::Base class')
97
+ @request_class.stub!(:has_many)
98
+
99
+ @source_class = mock('Source ActiveRecord::Base class')
100
+ @source_class.stub!(:has_many)
101
+
102
+ @database.stub!(:request_class).and_return(@request_class)
103
+ @database.stub!(:source_class).and_return(@source_class)
104
+
105
+ @mock_class = Class.new(RequestLogAnalyzer::Database::Base)
106
+
107
+ RequestLogAnalyzer::Database::Base.stub!(:subclass_from_table).and_return(@mock_class)
108
+ RequestLogAnalyzer::Database::Base.stub!(:subclass_from_line_definition).and_return(@mock_class)
109
+ end
110
+
111
+ after(:each) { @database.remove_orm_classes! }
112
+
113
+ it "should call :subclass_from_table when a table name is given as string" do
114
+ RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_table).and_return(@mock_class)
115
+ @database.load_activerecord_class('test_lines')
116
+ end
117
+
118
+ it "should call :subclass_from_table when a table name is given as symbol" do
119
+ RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_table).and_return(@mock_class)
120
+ @database.load_activerecord_class(:test_lines)
121
+ end
122
+
123
+ it "should call :subclass_from_table when a LineDefinition is given" do
124
+ RequestLogAnalyzer::Database::Base.should_receive(:subclass_from_line_definition).and_return(@mock_class)
125
+ @database.load_activerecord_class(RequestLogAnalyzer::LineDefinition.new(:test))
126
+ end
127
+
128
+ it "should define the class in the ORM module" do
129
+ @database.load_activerecord_class(:test_lines)
130
+ Object.const_defined?('TestLine').should be_true
131
+ end
132
+
133
+ it "should add the class to the line_classes array of the database" do
134
+ @database.load_activerecord_class(:test_lines)
135
+ @database.line_classes.should include(TestLine)
136
+ end
137
+ end
138
+ end
@@ -14,6 +14,18 @@ describe RequestLogAnalyzer::Source::LogParser, :requests do
14
14
  @log_parser.file_format.should be_valid
15
15
  end
16
16
 
17
+ it "should set the :source for every parsed line" do
18
+ @log_parser.parse_file(log_fixture(:rails_22)) do |request|
19
+ request.lines.all? { |line| line[:source] == log_fixture(:rails_22) }.should be_true
20
+ end
21
+ end
22
+
23
+ it "should set the :lineno for every parsed line" do
24
+ @log_parser.parse_file(log_fixture(:rails_22)) do |request|
25
+ request.lines.all? { |line| line.has_key?(:lineno) }.should be_true
26
+ end
27
+ end
28
+
17
29
  it "should parse more lines than requests" do
18
30
  @log_parser.should_receive(:handle_request).with(an_instance_of(TestingFormat::Request)).twice
19
31
  @log_parser.parse_file(log_fixture(:test_language_combined))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wvanbergen-request-log-analyzer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.9
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-09-08 00:00:00 -07:00
13
+ date: 2009-09-12 00:00:00 -07:00
14
14
  default_executable: request-log-analyzer
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -33,7 +33,7 @@ dependencies:
33
33
  - !ruby/object:Gem::Version
34
34
  version: 1.1.0
35
35
  version:
36
- description: Request log analyzer's purpose is to find ot how your web application is being used and to focus your optimization efforts. This tool will parse all requests in the application's log file and aggregate the information. Once it is finished parsing the log file(s), it will show the requests that take op most server time using various metrics. It can also insert all parsed request information into a database so you can roll your own analysis. It supports Rails- and Merb-based applications out of the box, but file formats of other applications can easily be supported by supplying an easy to write log file format definition.
36
+ description: Request log analyzer's purpose is to find ot how your web application is being used and to focus your optimization efforts. This tool will parse all requests in the application's log file and aggregate the information. Once it is finished parsing the log file(s), it will show the requests that take op most server time using various metrics. It can also insert all parsed request information into a database so you can roll your own analysis. It supports Rails- and Merb-based applications and Apache access log files out of the box, but file formats of other applications can easily be supported by supplying an easy to write log file format definition.
37
37
  email:
38
38
  - willem@railsdoctors.com
39
39
  - bart@railsdoctors.com
@@ -49,8 +49,8 @@ files:
49
49
  - lib/request_log_analyzer/output/html.rb
50
50
  - lib/request_log_analyzer/controller.rb
51
51
  - spec/fixtures/rails_22_cached.log
52
- - lib/request_log_analyzer/file_format/rails_development.rb
53
52
  - spec/lib/macros.rb
53
+ - lib/request_log_analyzer/file_format/rails_development.rb
54
54
  - spec/fixtures/apache_combined.log
55
55
  - spec/fixtures/apache_common.log
56
56
  - spec/fixtures/merb_prefixed.log
@@ -58,6 +58,7 @@ files:
58
58
  - spec/unit/file_format/file_format_api_spec.rb
59
59
  - spec/unit/file_format/apache_format_spec.rb
60
60
  - spec/integration/command_line_usage_spec.rb
61
+ - lib/request_log_analyzer/database.rb
61
62
  - spec/fixtures/decompression.log.bz2
62
63
  - lib/request_log_analyzer/log_processor.rb
63
64
  - lib/request_log_analyzer/tracker.rb
@@ -67,18 +68,22 @@ files:
67
68
  - request-log-analyzer.gemspec
68
69
  - DESIGN.rdoc
69
70
  - spec/unit/filter/timespan_filter_spec.rb
71
+ - spec/unit/aggregator/database_inserter_spec.rb
72
+ - spec/lib/matchers.rb
70
73
  - lib/request_log_analyzer/filter/field.rb
71
74
  - lib/request_log_analyzer/tracker/frequency.rb
72
75
  - spec/fixtures/decompression.log.gz
73
76
  - spec/fixtures/decompression.log
74
- - spec/lib/matchers.rb
77
+ - spec/lib/testing_format.rb
75
78
  - spec/fixtures/test_order.log
79
+ - spec/fixtures/rails.db
76
80
  - lib/request_log_analyzer/output/fixed_width.rb
77
81
  - lib/request_log_analyzer/filter/anonymize.rb
78
- - spec/lib/testing_format.rb
79
82
  - lib/request_log_analyzer/tracker/timespan.rb
83
+ - lib/request_log_analyzer/database/base.rb
80
84
  - lib/request_log_analyzer/aggregator.rb
81
85
  - lib/cli/progressbar.rb
86
+ - lib/request_log_analyzer/mailer.rb
82
87
  - README.rdoc
83
88
  - spec/fixtures/merb.log
84
89
  - lib/request_log_analyzer/tracker/hourly_spread.rb
@@ -89,15 +94,17 @@ files:
89
94
  - spec/unit/controller/log_processor_spec.rb
90
95
  - spec/spec_helper.rb
91
96
  - lib/request_log_analyzer.rb
97
+ - spec/database.yml
92
98
  - Rakefile
99
+ - lib/request_log_analyzer/database/connection.rb
93
100
  - spec/unit/filter/filter_spec.rb
101
+ - spec/fixtures/test_language_combined.log
102
+ - lib/request_log_analyzer/aggregator/database_inserter.rb
94
103
  - lib/request_log_analyzer/aggregator/summarizer.rb
95
104
  - lib/request_log_analyzer/file_format/rails.rb
96
- - spec/fixtures/test_language_combined.log
97
105
  - spec/fixtures/decompression.tar.gz
98
106
  - spec/unit/filter/field_filter_spec.rb
99
- - spec/spec.opts
100
- - lib/request_log_analyzer/aggregator/database.rb
107
+ - spec/unit/database/base_class_spec.rb
101
108
  - lib/request_log_analyzer/filter/timespan.rb
102
109
  - lib/request_log_analyzer/source/log_parser.rb
103
110
  - spec/fixtures/decompression.tgz
@@ -111,19 +118,21 @@ files:
111
118
  - spec/unit/file_format/line_definition_spec.rb
112
119
  - lib/request_log_analyzer/source.rb
113
120
  - lib/request_log_analyzer/request.rb
121
+ - lib/cli/database_console.rb
122
+ - spec/unit/database/connection_spec.rb
114
123
  - spec/unit/controller/controller_spec.rb
124
+ - spec/lib/mocks.rb
125
+ - spec/lib/helpers.rb
126
+ - lib/cli/database_console_init.rb
115
127
  - lib/request_log_analyzer/output.rb
116
128
  - lib/request_log_analyzer/file_format/apache.rb
117
- - spec/lib/helpers.rb
118
129
  - spec/fixtures/rails_1x.log
119
- - spec/lib/mocks.rb
120
130
  - spec/fixtures/decompression.log.zip
121
131
  - spec/unit/source/request_spec.rb
122
132
  - spec/unit/source/log_parser_spec.rb
123
- - spec/unit/aggregator/database_spec.rb
124
133
  - spec/fixtures/test_file_format.log
125
- - lib/request_log_analyzer/source/database.rb
126
134
  - tasks/github-gem.rake
135
+ - spec/unit/database/database_spec.rb
127
136
  - lib/request_log_analyzer/tracker/duration.rb
128
137
  - lib/request_log_analyzer/file_format.rb
129
138
  - spec/unit/aggregator/summarizer_spec.rb
@@ -131,12 +140,12 @@ files:
131
140
  - spec/fixtures/multiple_files_2.log
132
141
  - spec/fixtures/syslog_1x.log
133
142
  - LICENSE
143
+ - lib/request_log_analyzer/source/database_loader.rb
134
144
  - spec/unit/tracker/frequency_tracker_spec.rb
135
145
  - spec/unit/file_format/rails_format_spec.rb
136
146
  - lib/cli/command_line_arguments.rb
137
147
  has_rdoc: false
138
148
  homepage: http://railsdoctors.com
139
- licenses:
140
149
  post_install_message:
141
150
  rdoc_options:
142
151
  - --title
@@ -162,29 +171,32 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
171
  requirements:
163
172
  - To use the database inserter, ActiveRecord and an appropriate database adapter are required.
164
173
  rubyforge_project: r-l-a
165
- rubygems_version: 1.3.5
174
+ rubygems_version: 1.2.0
166
175
  signing_key:
167
176
  specification_version: 2
168
- summary: A command line tool to analyze request logs for Rails, Merb and other application servers
177
+ summary: A command line tool to analyze request logs for Apache, Rails, Merb and other application servers
169
178
  test_files:
170
179
  - spec/unit/filter/anonymize_filter_spec.rb
171
180
  - spec/unit/file_format/file_format_api_spec.rb
172
181
  - spec/unit/file_format/apache_format_spec.rb
173
182
  - spec/integration/command_line_usage_spec.rb
174
183
  - spec/unit/filter/timespan_filter_spec.rb
184
+ - spec/unit/aggregator/database_inserter_spec.rb
175
185
  - spec/unit/tracker/tracker_api_spec.rb
176
186
  - spec/unit/tracker/duration_tracker_spec.rb
177
187
  - spec/unit/controller/log_processor_spec.rb
178
188
  - spec/unit/filter/filter_spec.rb
179
189
  - spec/unit/filter/field_filter_spec.rb
190
+ - spec/unit/database/base_class_spec.rb
180
191
  - spec/unit/tracker/timespan_tracker_spec.rb
181
192
  - spec/unit/tracker/hourly_spread_spec.rb
182
193
  - spec/unit/file_format/merb_format_spec.rb
183
194
  - spec/unit/file_format/line_definition_spec.rb
195
+ - spec/unit/database/connection_spec.rb
184
196
  - spec/unit/controller/controller_spec.rb
185
197
  - spec/unit/source/request_spec.rb
186
198
  - spec/unit/source/log_parser_spec.rb
187
- - spec/unit/aggregator/database_spec.rb
199
+ - spec/unit/database/database_spec.rb
188
200
  - spec/unit/aggregator/summarizer_spec.rb
189
201
  - spec/unit/tracker/frequency_tracker_spec.rb
190
202
  - spec/unit/file_format/rails_format_spec.rb