request-log-analyzer 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. data/LICENSE +1 -1
  2. data/README.rdoc +19 -24
  3. data/bin/request-log-analyzer +10 -7
  4. data/lib/request_log_analyzer/aggregator/summarizer.rb +13 -2
  5. data/lib/request_log_analyzer/controller.rb +68 -36
  6. data/lib/request_log_analyzer/file_format/apache.rb +1 -1
  7. data/lib/request_log_analyzer/file_format/mysql.rb +93 -0
  8. data/lib/request_log_analyzer/file_format/rails_development.rb +1 -1
  9. data/lib/request_log_analyzer/file_format.rb +46 -2
  10. data/lib/request_log_analyzer/mailer.rb +25 -12
  11. data/lib/request_log_analyzer/output/fixed_width.rb +1 -1
  12. data/lib/request_log_analyzer/output/html.rb +2 -0
  13. data/lib/request_log_analyzer/request.rb +5 -0
  14. data/lib/request_log_analyzer/source/log_parser.rb +33 -10
  15. data/lib/request_log_analyzer/tracker/count.rb +93 -0
  16. data/lib/request_log_analyzer.rb +1 -1
  17. data/request-log-analyzer.gemspec +6 -6
  18. data/spec/fixtures/mysql_slow_query.log +110 -0
  19. data/spec/integration/command_line_usage_spec.rb +3 -3
  20. data/spec/integration/mailer_spec.rb +179 -0
  21. data/spec/integration/munin_plugins_rails_spec.rb +58 -0
  22. data/spec/integration/scout_spec.rb +152 -0
  23. data/spec/lib/helpers.rb +26 -1
  24. data/spec/lib/mocks.rb +3 -1
  25. data/spec/unit/file_format/apache_format_spec.rb +102 -95
  26. data/spec/unit/file_format/format_autodetection_spec.rb +35 -0
  27. data/spec/unit/file_format/mysql_format_spec.rb +155 -0
  28. data/spec/unit/file_format/rails_format_spec.rb +9 -12
  29. data/spec/unit/mailer_spec.rb +12 -0
  30. data/spec/unit/tracker/count_tracker_spec.rb +123 -0
  31. data/spec/unit/tracker/tracker_api_spec.rb +1 -1
  32. metadata +125 -110
@@ -20,6 +20,7 @@ module RequestLogAnalyzer::Source
20
20
  PARSE_STRATEGIES = ['cautious', 'assume-correct']
21
21
 
22
22
  attr_reader :source_files, :current_file, :current_lineno
23
+ attr_reader :warnings, :parsed_lines, :parsed_requests, :skipped_lines, :skipped_requests
23
24
 
24
25
  # Initializes the log file parser instance.
25
26
  # It will apply the language specific FileFormat module to this instance. It will use the line
@@ -29,6 +30,7 @@ module RequestLogAnalyzer::Source
29
30
  # <tt>options</tt>:: A hash of options that are used by the parser
30
31
  def initialize(format, options = {})
31
32
  super(format, options)
33
+ @warnings = 0
32
34
  @parsed_lines = 0
33
35
  @parsed_requests = 0
34
36
  @skipped_lines = 0
@@ -142,21 +144,27 @@ module RequestLogAnalyzer::Source
142
144
  # <tt>io</tt>:: The IO instance to use as source
143
145
  # <tt>options</tt>:: A hash of options that can be used by the parser.
144
146
  def parse_io(io, options = {}, &block) # :yields: request
145
- @current_lineno = 1
147
+ @current_lineno = 0
146
148
  while line = io.gets
147
- @progress_handler.call(:progress, io.pos) if @progress_handler && @current_lineno % 255 == 0
148
-
149
- if request_data = file_format.parse_line(line) { |wt, message| warn(wt, message) }
150
- @parsed_lines += 1
151
- update_current_request(request_data.merge(:source => @current_source, :lineno => @current_lineno), &block)
152
- end
153
-
154
149
  @current_lineno += 1
150
+ @progress_handler.call(:progress, io.pos) if @progress_handler && @current_lineno % 255 == 0
151
+ parse_line(line, &block)
155
152
  end
156
153
 
157
154
  warn(:unfinished_request_on_eof, "End of file reached, but last request was not completed!") unless @current_request.nil?
158
155
  @current_lineno = nil
159
156
  end
157
+
158
+ # Parses a single line using the current file format. If successful, use the parsed
159
+ # information to build a request
160
+ # <tt>line</tt>:: The line to parse
161
+ # <tt>block</tt>:: The block to send fully parsed requests to.
162
+ def parse_line(line, &block) # :yields: request
163
+ if request_data = file_format.parse_line(line) { |wt, message| warn(wt, message) }
164
+ @parsed_lines += 1
165
+ update_current_request(request_data.merge(:source => @current_source, :lineno => @current_lineno), &block)
166
+ end
167
+ end
160
168
 
161
169
  # Add a block to this method to install a progress handler while parsing.
162
170
  # <tt>proc</tt>:: The proc that will be called to handle progress update messages
@@ -186,6 +194,7 @@ module RequestLogAnalyzer::Source
186
194
  # <tt>type</tt>:: The warning type (a Symbol)
187
195
  # <tt>message</tt>:: A message explaining the warning
188
196
  def warn(type, message)
197
+ @warnings += 1
189
198
  @warning_handler.call(type, message, @current_lineno) if @warning_handler
190
199
  end
191
200
 
@@ -214,7 +223,13 @@ module RequestLogAnalyzer::Source
214
223
  #
215
224
  # <tt>request_data</tt>:: A hash of data that was parsed from the last line.
216
225
  def update_current_request(request_data, &block) # :yields: request
217
- if header_line?(request_data)
226
+ if alternative_header_line?(request_data)
227
+ if @current_request
228
+ @current_request << request_data
229
+ else
230
+ @current_request = @file_format.request(request_data)
231
+ end
232
+ elsif header_line?(request_data)
218
233
  if @current_request
219
234
  case options[:parse_strategy]
220
235
  when 'assume-correct'
@@ -258,10 +273,18 @@ module RequestLogAnalyzer::Source
258
273
  @skipped_requests += 1 unless accepted
259
274
  end
260
275
 
276
+
277
+ # Checks whether a given line hash is an alternative header line according to the current file format.
278
+ # <tt>hash</tt>:: A hash of data that was parsed from the line.
279
+ def alternative_header_line?(hash)
280
+ hash[:line_definition].header == :alternative
281
+ end
282
+
283
+
261
284
  # Checks whether a given line hash is a header line according to the current file format.
262
285
  # <tt>hash</tt>:: A hash of data that was parsed from the line.
263
286
  def header_line?(hash)
264
- hash[:line_definition].header
287
+ hash[:line_definition].header == true
265
288
  end
266
289
 
267
290
  # Checks whether a given line hash is a footer line according to the current file format.
@@ -0,0 +1,93 @@
1
+ module RequestLogAnalyzer::Tracker
2
+
3
+ # Get highest count of a specific attribute
4
+ class Count < Base
5
+
6
+ include RequestLogAnalyzer::Tracker::StatisticsTracking
7
+
8
+ attr_reader :categories
9
+
10
+ def prepare
11
+ raise "No categorizer set up for category tracker #{self.inspect}" unless options[:category]
12
+ raise "No field to count has been set up #{self.inspect}" unless options[:field]
13
+
14
+ @categorizer = create_lambda(options[:category])
15
+ @counter = create_lambda(options[:field])
16
+ @categories = {}
17
+ end
18
+
19
+ # Get the duration information fron the request and store it in the different categories.
20
+ # <tt>request</tt> The request.
21
+ def update(request)
22
+ category = @categorizer.call(request)
23
+ count = @counter.call(request)
24
+ update_statistics(category, count) if count.kind_of?(Numeric) && !category.nil?
25
+ end
26
+
27
+ def report(output)
28
+ sortings = output.options[:sort] || [:sum, :mean]
29
+
30
+ sortings.each do |report|
31
+ case report
32
+ when :mean
33
+ report_table(output, :mean, :title => "#{title} - sorted by mean")
34
+ when :stddev
35
+ report_table(output, :stddev, :title => "#{title} - sorted by standard deviation")
36
+ when :sum
37
+ report_table(output, :sum, :title => "#{title} - sorted by sum")
38
+ when :hits
39
+ report_table(output, :hits, :title => "#{title} - sorted by hits")
40
+ else
41
+ raise "Unknown duration report specified: #{report}!"
42
+ end
43
+ end
44
+ end
45
+
46
+ # Block function to build a result table using a provided sorting function.
47
+ # <tt>output</tt> The output object.
48
+ # <tt>amount</tt> The number of rows in the report table (default 10).
49
+ # === Options
50
+ # * </tt>:title</tt> The title of the table
51
+ # * </tt>:sort</tt> The key to sort on (:hits, :cumulative, :average, :min or :max)
52
+ def report_table(output, sort, options = {}, &block)
53
+ output.puts
54
+
55
+ top_categories = output.slice_results(sorted_by(sort))
56
+ output.with_style(:top_line => true) do
57
+ output.table(*statistics_header(:title => options[:title],:highlight => sort)) do |rows|
58
+ top_categories.each { |(cat, info)| rows.push(statistics_row(cat)) }
59
+ end
60
+ end
61
+ output.puts
62
+ end
63
+
64
+ # Format an int to a nice string with decimal seperation.
65
+ # Also see http://en.wikipedia.org/wiki/Terabyte
66
+ # <tt>count</tt> the value to reduce
67
+ def display_value(count)
68
+ return "- " if count.nil?
69
+ return "0 " if count.zero?
70
+
71
+ case Math.log10(count).floor
72
+ when 1...4 then '%d ' % count
73
+ when 4...7 then '%dk' % (count / 1000)
74
+ when 7...10 then '%dM' % (count / 1000_000)
75
+ when 10...13 then '%dG' % (count / 1000_000_000)
76
+ when 13...16 then '%dT' % (count / 1000_000_000_000)
77
+ else '%dP' % (count / 1000_000_000_000_000)
78
+ end
79
+
80
+ end
81
+
82
+ # Returns the title of this tracker for reports
83
+ def title
84
+ options[:title] || 'Total'
85
+ end
86
+
87
+ # Returns all the categories and the tracked duration as a hash than can be exported to YAML
88
+ def to_yaml_object
89
+ return nil if @categories.empty?
90
+ @categories
91
+ end
92
+ end
93
+ end
@@ -11,7 +11,7 @@ module RequestLogAnalyzer
11
11
 
12
12
  # The current version of request-log-analyzer.
13
13
  # Do not change the value by hand; it will be updated automatically by the gem release script.
14
- VERSION = "1.4.0"
14
+ VERSION = "1.5.0"
15
15
 
16
16
  # Loads constants in the RequestLogAnalyzer namespace using self.load_default_class_file(base, const)
17
17
  # <tt>const</tt>:: The constant that is not yet loaded in the RequestLogAnalyzer namespace. This should be passed as a string or symbol.
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
2
2
  s.name = "request-log-analyzer"
3
3
 
4
4
  # Do not set the version and date field manually, this is done by the release script
5
- s.version = "1.4.0"
6
- s.date = "2009-09-30"
5
+ s.version = "1.5.0"
6
+ s.date = "2009-11-18"
7
7
 
8
8
  s.rubyforge_project = 'r-l-a'
9
9
 
@@ -26,8 +26,8 @@ Gem::Specification.new do |s|
26
26
 
27
27
  s.requirements << "To use the database inserter, ActiveRecord and an appropriate database adapter are required."
28
28
 
29
- s.add_development_dependency('rspec', '>= 1.2.4')
30
- s.add_development_dependency('git', '>= 1.1.0')
29
+ s.add_development_dependency('rspec', '>= 1.2.4')
30
+ s.add_development_dependency('git', '>= 1.1.0')
31
31
 
32
32
  s.authors = ['Willem van Bergen', 'Bart ten Brinke']
33
33
  s.email = ['willem@railsdoctors.com', 'bart@railsdoctors.com']
@@ -35,6 +35,6 @@ Gem::Specification.new do |s|
35
35
 
36
36
  # The files and test_files directives are set automatically by the release script.
37
37
  # Do not change them by hand, but make sure to add the files to the git repository.
38
- s.files = %w(spec/unit/filter/anonymize_filter_spec.rb spec/fixtures/rails_22_cached.log lib/request_log_analyzer/line_definition.rb lib/request_log_analyzer/output/html.rb lib/request_log_analyzer/controller.rb spec/lib/macros.rb lib/request_log_analyzer/file_format/rails_development.rb spec/fixtures/apache_combined.log spec/fixtures/apache_common.log spec/fixtures/merb_prefixed.log lib/request_log_analyzer/file_format/amazon_s3.rb tasks/request_log_analyzer.rake spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/apache_format_spec.rb spec/integration/command_line_usage_spec.rb lib/request_log_analyzer/database.rb spec/fixtures/decompression.log.bz2 spec/fixtures/rails_unordered.log lib/request_log_analyzer/log_processor.rb lib/request_log_analyzer/tracker.rb lib/request_log_analyzer/filter.rb bin/request-log-analyzer request-log-analyzer.gemspec DESIGN.rdoc spec/unit/filter/timespan_filter_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/lib/matchers.rb lib/request_log_analyzer/filter/field.rb lib/request_log_analyzer/tracker/frequency.rb spec/fixtures/decompression.log.gz spec/fixtures/decompression.log spec/lib/testing_format.rb spec/fixtures/test_order.log spec/fixtures/rails.db lib/request_log_analyzer/output/fixed_width.rb lib/request_log_analyzer/filter/anonymize.rb lib/request_log_analyzer/tracker/timespan.rb lib/request_log_analyzer/database/base.rb lib/request_log_analyzer/aggregator.rb spec/unit/request_spec.rb lib/cli/progressbar.rb lib/request_log_analyzer/mailer.rb README.rdoc lib/request_log_analyzer/database/warning.rb spec/fixtures/merb.log lib/request_log_analyzer/tracker/hourly_spread.rb .gitignore spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb lib/request_log_analyzer/aggregator/echo.rb spec/unit/mailer_spec.rb spec/unit/controller/log_processor_spec.rb spec/spec_helper.rb lib/request_log_analyzer.rb spec/database.yml Rakefile lib/request_log_analyzer/database/connection.rb spec/unit/filter/filter_spec.rb spec/fixtures/test_language_combined.log lib/request_log_analyzer/aggregator/database_inserter.rb lib/request_log_analyzer/aggregator/summarizer.rb lib/request_log_analyzer/file_format/rack.rb lib/request_log_analyzer/database/source.rb lib/request_log_analyzer/file_format/rails.rb spec/fixtures/decompression.tar.gz spec/unit/tracker/traffic_tracker_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/database/base_class_spec.rb lib/request_log_analyzer/filter/timespan.rb lib/request_log_analyzer/source/log_parser.rb spec/fixtures/decompression.tgz spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/fixtures/header_and_footer.log lib/cli/tools.rb lib/request_log_analyzer/file_format/merb.rb spec/fixtures/multiple_files_1.log spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/line_definition_spec.rb lib/request_log_analyzer/source.rb lib/request_log_analyzer/request.rb lib/cli/database_console.rb spec/unit/database/connection_spec.rb spec/unit/controller/controller_spec.rb spec/lib/mocks.rb spec/lib/helpers.rb spec/fixtures/rails_1x.log lib/cli/database_console_init.rb lib/request_log_analyzer/output.rb lib/request_log_analyzer/file_format/apache.rb spec/fixtures/decompression.log.zip spec/unit/source/log_parser_spec.rb spec/fixtures/test_file_format.log tasks/github-gem.rake spec/unit/database/database_spec.rb lib/request_log_analyzer/tracker/duration.rb lib/request_log_analyzer/tracker/traffic.rb lib/request_log_analyzer/file_format.rb spec/unit/aggregator/summarizer_spec.rb spec/fixtures/syslog_1x.log spec/fixtures/rails_22.log lib/request_log_analyzer/database/request.rb spec/fixtures/multiple_files_2.log LICENSE lib/request_log_analyzer/source/database_loader.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/file_format/rails_format_spec.rb lib/cli/command_line_arguments.rb)
39
- s.test_files = %w(spec/unit/filter/anonymize_filter_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/unit/file_format/apache_format_spec.rb spec/integration/command_line_usage_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/request_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/mailer_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/filter/filter_spec.rb spec/unit/tracker/traffic_tracker_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/database/base_class_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/hourly_spread_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/database/connection_spec.rb spec/unit/controller/controller_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/database/database_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/file_format/rails_format_spec.rb)
38
+ s.files = %w(lib/request_log_analyzer/output/html.rb spec/unit/tracker/hourly_spread_spec.rb DESIGN.rdoc spec/fixtures/rails_unordered.log spec/fixtures/multiple_files_1.log lib/request_log_analyzer/database/source.rb README.rdoc spec/unit/file_format/amazon_s3_format_spec.rb lib/request_log_analyzer/file_format/rails_development.rb spec/fixtures/rails_22.log spec/fixtures/test_order.log spec/unit/database/base_class_spec.rb lib/request_log_analyzer/database/connection.rb lib/request_log_analyzer/aggregator.rb spec/fixtures/decompression.log lib/request_log_analyzer/file_format/apache.rb spec/fixtures/decompression.log.gz lib/request_log_analyzer/tracker/frequency.rb lib/request_log_analyzer/tracker/duration.rb tasks/github-gem.rake .gitignore spec/unit/filter/filter_spec.rb spec/lib/macros.rb spec/spec_helper.rb spec/unit/tracker/count_tracker_spec.rb spec/fixtures/decompression.log.bz2 spec/unit/database/connection_spec.rb lib/request_log_analyzer/filter.rb spec/integration/scout_spec.rb spec/fixtures/test_file_format.log lib/request_log_analyzer/tracker/traffic.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/file_format/file_format_api_spec.rb lib/request_log_analyzer/filter/field.rb lib/request_log_analyzer/file_format/merb.rb lib/request_log_analyzer/filter/anonymize.rb lib/request_log_analyzer/file_format/amazon_s3.rb lib/cli/database_console.rb spec/integration/mailer_spec.rb lib/request_log_analyzer/line_definition.rb spec/unit/tracker/frequency_tracker_spec.rb spec/fixtures/multiple_files_2.log spec/lib/mocks.rb spec/unit/file_format/apache_format_spec.rb spec/fixtures/syslog_1x.log spec/integration/munin_plugins_rails_spec.rb spec/lib/helpers.rb spec/fixtures/rails.db spec/unit/source/log_parser_spec.rb lib/request_log_analyzer/aggregator/database_inserter.rb spec/fixtures/header_and_footer.log spec/lib/testing_format.rb lib/request_log_analyzer/database.rb spec/unit/file_format/rails_format_spec.rb lib/request_log_analyzer/request.rb lib/request_log_analyzer/output/fixed_width.rb spec/integration/command_line_usage_spec.rb lib/request_log_analyzer/file_format/rack.rb spec/fixtures/test_language_combined.log lib/cli/command_line_arguments.rb lib/request_log_analyzer.rb spec/database.yml spec/unit/request_spec.rb lib/request_log_analyzer/database/base.rb spec/unit/aggregator/database_inserter_spec.rb lib/request_log_analyzer/database/request.rb lib/cli/database_console_init.rb lib/cli/progressbar.rb lib/request_log_analyzer/database/warning.rb spec/unit/filter/anonymize_filter_spec.rb spec/fixtures/apache_combined.log spec/fixtures/rails_22_cached.log lib/request_log_analyzer/aggregator/summarizer.rb spec/unit/tracker/duration_tracker_spec.rb spec/fixtures/rails_1x.log lib/request_log_analyzer/tracker/count.rb lib/request_log_analyzer/output.rb spec/unit/file_format/line_definition_spec.rb lib/request_log_analyzer/file_format/mysql.rb spec/unit/file_format/mysql_format_spec.rb request-log-analyzer.gemspec spec/fixtures/apache_common.log lib/request_log_analyzer/file_format/rails.rb Rakefile spec/unit/mailer_spec.rb lib/request_log_analyzer/tracker/hourly_spread.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/tracker/traffic_tracker_spec.rb lib/request_log_analyzer/tracker/timespan.rb spec/unit/controller/log_processor_spec.rb spec/unit/filter/field_filter_spec.rb spec/fixtures/merb_prefixed.log lib/request_log_analyzer/log_processor.rb lib/request_log_analyzer/filter/timespan.rb spec/unit/controller/controller_spec.rb lib/request_log_analyzer/mailer.rb lib/cli/tools.rb spec/fixtures/decompression.tar.gz spec/unit/tracker/timespan_tracker_spec.rb spec/lib/matchers.rb lib/request_log_analyzer/controller.rb spec/unit/tracker/tracker_api_spec.rb lib/request_log_analyzer/source/database_loader.rb spec/fixtures/merb.log LICENSE lib/request_log_analyzer/file_format.rb tasks/request_log_analyzer.rake spec/unit/database/database_spec.rb spec/fixtures/decompression.log.zip spec/fixtures/decompression.tgz bin/request-log-analyzer lib/request_log_analyzer/tracker.rb lib/request_log_analyzer/source.rb spec/fixtures/mysql_slow_query.log lib/request_log_analyzer/source/log_parser.rb lib/request_log_analyzer/aggregator/echo.rb)
39
+ s.test_files = %w(spec/unit/tracker/hourly_spread_spec.rb spec/unit/file_format/amazon_s3_format_spec.rb spec/unit/database/base_class_spec.rb spec/unit/filter/filter_spec.rb spec/unit/tracker/count_tracker_spec.rb spec/unit/database/connection_spec.rb spec/integration/scout_spec.rb spec/unit/file_format/merb_format_spec.rb spec/unit/file_format/format_autodetection_spec.rb spec/unit/filter/timespan_filter_spec.rb spec/unit/file_format/file_format_api_spec.rb spec/integration/mailer_spec.rb spec/unit/tracker/frequency_tracker_spec.rb spec/unit/file_format/apache_format_spec.rb spec/integration/munin_plugins_rails_spec.rb spec/unit/source/log_parser_spec.rb spec/unit/file_format/rails_format_spec.rb spec/integration/command_line_usage_spec.rb spec/unit/request_spec.rb spec/unit/aggregator/database_inserter_spec.rb spec/unit/filter/anonymize_filter_spec.rb spec/unit/tracker/duration_tracker_spec.rb spec/unit/file_format/line_definition_spec.rb spec/unit/file_format/mysql_format_spec.rb spec/unit/mailer_spec.rb spec/unit/aggregator/summarizer_spec.rb spec/unit/tracker/traffic_tracker_spec.rb spec/unit/controller/log_processor_spec.rb spec/unit/filter/field_filter_spec.rb spec/unit/controller/controller_spec.rb spec/unit/tracker/timespan_tracker_spec.rb spec/unit/tracker/tracker_api_spec.rb spec/unit/database/database_spec.rb)
40
40
  end
@@ -0,0 +1,110 @@
1
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
2
+ # Time: 091112 18:13:56
3
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
4
+ # Query_time: 10 Lock_time: 0 Rows_sent: 1191307 Rows_examined: 1191307
5
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
6
+ # Time: 091112 18:14:07
7
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
8
+ # Query_time: 9 Lock_time: 0 Rows_sent: 258841 Rows_examined: 258841
9
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `sessions`;
10
+ # Time: 091112 18:14:44
11
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
12
+ # Query_time: 6 Lock_time: 0 Rows_sent: 603732 Rows_examined: 603732
13
+ use sensire_s;
14
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
15
+ # Time: 091112 18:14:56
16
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
17
+ # Query_time: 12 Lock_time: 0 Rows_sent: 1068438 Rows_examined: 1068438
18
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
19
+ # Time: 091112 18:16:18
20
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
21
+ # Query_time: 17 Lock_time: 0 Rows_sent: 1822689 Rows_examined: 1822689
22
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
23
+ # Time: 091112 18:16:28
24
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
25
+ # Query_time: 10 Lock_time: 0 Rows_sent: 1113903 Rows_examined: 1113903
26
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
27
+ # Time: 091112 18:17:37
28
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
29
+ # Query_time: 19 Lock_time: 0 Rows_sent: 1631168 Rows_examined: 1631168
30
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
31
+ # Time: 091112 18:17:49
32
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
33
+ # Query_time: 11 Lock_time: 0 Rows_sent: 951103 Rows_examined: 951103
34
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
35
+ # Time: 091112 18:19:31
36
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
37
+ # Query_time: 7 Lock_time: 0 Rows_sent: 747129 Rows_examined: 747129
38
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
39
+ # Time: 091112 18:19:49
40
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
41
+ # Query_time: 17 Lock_time: 0 Rows_sent: 1904679 Rows_examined: 1904679
42
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
43
+ # Time: 091112 18:21:34
44
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
45
+ # Query_time: 59 Lock_time: 0 Rows_sent: 5013829 Rows_examined: 5013829
46
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
47
+ # Time: 091112 18:21:54
48
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
49
+ # Query_time: 20 Lock_time: 0 Rows_sent: 1634467 Rows_examined: 1634467
50
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
51
+ # Time: 091112 18:22:58
52
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
53
+ # Query_time: 5 Lock_time: 0 Rows_sent: 634683 Rows_examined: 634683
54
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
55
+ # Time: 091112 18:23:58
56
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
57
+ # Query_time: 5 Lock_time: 0 Rows_sent: 444697 Rows_examined: 444697
58
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
59
+ # Time: 091112 18:24:34
60
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
61
+ # Query_time: 7 Lock_time: 0 Rows_sent: 669623 Rows_examined: 669623
62
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
63
+ # Time: 091112 18:26:18
64
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
65
+ # Query_time: 27 Lock_time: 0 Rows_sent: 2727395 Rows_examined: 2727395
66
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
67
+ # Time: 091112 18:26:28
68
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
69
+ # Query_time: 10 Lock_time: 0 Rows_sent: 859164 Rows_examined: 859164
70
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
71
+ # Time: 091112 18:27:50
72
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
73
+ # Query_time: 29 Lock_time: 0 Rows_sent: 2607634 Rows_examined: 2607634
74
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
75
+ # Time: 091112 18:27:59
76
+ # User@Host: admin[admin] @ db1 [10.0.0.1]
77
+ # Query_time: 9 Lock_time: 0 Rows_sent: 766241 Rows_examined: 766241
78
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
79
+ # Time: 091112 18:30:39
80
+ # User@Host: user_1[user_1] @ rails1 [10.0.1.3]
81
+ # Query_time: 6 Lock_time: 0 Rows_sent: 0 Rows_examined: 1648536
82
+ SELECT * FROM `clients` WHERE (1=1
83
+ AND clients.valid_from < '2009-12-05' AND (clients.valid_to IS NULL or clients.valid_to > '2009-11-20')
84
+ AND clients.index > 0
85
+ ) AND (clients.deleted_at IS NULL);
86
+ # Time: 091112 20:15:16
87
+ # User@Host: user_2[user_2] @ rails1 [10.0.1.3]
88
+ # Query_time: 7 Lock_time: 0 Rows_sent: 796074 Rows_examined: 796074
89
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
90
+ # Time: 091112 20:15:29
91
+ # User@Host: user_2[user_2] @ rails1 [10.0.1.3]
92
+ # Query_time: 12 Lock_time: 0 Rows_sent: 1191307 Rows_examined: 1191307
93
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
94
+ # Time: 091112 20:15:45
95
+ # User@Host: user_2[user_2] @ rails1 [10.0.1.3]
96
+ # Query_time: 12 Lock_time: 0 Rows_sent: 259350 Rows_examined: 259350
97
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `sessions`;
98
+ # Time: 091112 20:18:50
99
+ # User@Host: user_1[user_1] @ rails1 [10.0.1.3]
100
+ # Query_time: 28 Lock_time: 0 Rows_sent: 2727404 Rows_examined: 2727404
101
+ use zuwe_p;
102
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `clients`;
103
+ # Time: 091112 20:19:18
104
+ # User@Host: user_1[user_1] @ rails1 [10.0.1.3]
105
+ # Query_time: 28 Lock_time: 0 Rows_sent: 859164 Rows_examined: 859164
106
+ SELECT /*!40001 SQL_NO_CACHE */ * FROM `events`;
107
+ # Time: 091112 20:19:40
108
+ # User@Host: user_1[user_1] @ db1 [10.1.1.178]
109
+ # Query_time: 6 Lock_time: 0 Rows_sent: 33 Rows_examined: 1648542
110
+ SELECT * FROM `clients` WHERE (valid_to IS NULL OR valid_to > '2009-12-12') AND ((`clients`.`deleted` = 1) AND (clients.deleted_at IS NULL));
@@ -72,9 +72,9 @@ describe RequestLogAnalyzer, 'running from command line' do
72
72
  end
73
73
 
74
74
  it "should dump the results to a YAML file" do
75
- run("#{log_fixture(:rails_1x)} --dump #{temp_output_file(:dump)}")
76
- File.exist?(temp_output_file(:dump)).should be_true
77
- YAML::load(File.read(temp_output_file(:dump))).should have_at_least(1).item
75
+ run("#{log_fixture(:rails_1x)} --dump #{temp_output_file(:yaml)}")
76
+ File.exist?(temp_output_file(:yaml)).should be_true
77
+ YAML::load(File.read(temp_output_file(:yaml))).should have_at_least(1).item
78
78
  end
79
79
 
80
80
  it "should parse 4 requests from the standard input" do
@@ -0,0 +1,179 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require 'socket'
3
+
4
+ describe RequestLogAnalyzer, 'running mailer integration' do
5
+
6
+ before(:each) do
7
+ @log_file = temp_output_file('mailtrap.log')
8
+
9
+ Process.fork {
10
+ Mailtrap.new('localhost', 2525, true, @log_file)
11
+ Process.exit! # Do not call rspec after exit hook!
12
+ }
13
+ end
14
+
15
+ after(:each) do
16
+ cleanup_temp_files!
17
+ end
18
+
19
+ it "should send plaintext mail" do
20
+ RequestLogAnalyzer::Controller.build(
21
+ :mail => 'root@localhost',
22
+ :mailhost => 'localhost:2525',
23
+ :source_files => log_fixture(:rails_1x),
24
+ :format => RequestLogAnalyzer::FileFormat::Rails,
25
+ :no_progress => true
26
+ ).run!
27
+
28
+ Process.wait # Wait for mailer to complete
29
+
30
+ find_string_in_file("From: <contact@railsdoctors.com>", @log_file).should_not be_nil
31
+ find_string_in_file("To: <root@localhost>", @log_file).should_not be_nil
32
+ find_string_in_file("From: Request-log-analyzer reporter <contact@railsdoctors.com>", @log_file).should_not be_nil
33
+ find_string_in_file("Request summary", @log_file).should_not be_nil
34
+ find_string_in_file("PeopleController#show.html [ | 1 | 0.29s | 0.29s | 0.00s | 0.29s | 0.29s", @log_file).should_not be_nil
35
+ end
36
+
37
+ it "should send html mail" do
38
+ RequestLogAnalyzer::Controller.build(
39
+ :output => 'HTML',
40
+ :mail => 'root@localhost',
41
+ :mailhost => 'localhost:2525',
42
+ :source_files => log_fixture(:rails_1x),
43
+ :format => RequestLogAnalyzer::FileFormat::Rails,
44
+ :no_progress => true
45
+ ).run!
46
+
47
+ Process.wait # Wait for mailer to complete
48
+
49
+ find_string_in_file("From: <contact@railsdoctors.com>", @log_file).should_not be_nil
50
+ find_string_in_file("To: <root@localhost>", @log_file).should_not be_nil
51
+ find_string_in_file("From: Request-log-analyzer reporter <contact@railsdoctors.com>", @log_file).should_not be_nil
52
+ find_string_in_file('<h1>Request-log-analyzer summary report</h1>', @log_file).should_not be_nil
53
+ find_string_in_file('<td class="alt">0.29s</td></tr><tr><td>DashboardController#index.html [GET]</td>', @log_file).should_not be_nil
54
+ end
55
+ end
56
+
57
+
58
+
59
+ # Mailtrap
60
+ # by Matt Mower <self@mattmower.com>
61
+ # http://matt.blogs.it/
62
+ #
63
+ # Included in RLA because original mailtrap puts anoying stuff when called
64
+ # through ruby.
65
+ #
66
+ # Mailtrap creates a TCP server that listens on a specified port for SMTP
67
+ # clients. Accepts the connection and talks just enough of the SMTP protocol
68
+ # for them to deliver a message which it writes to disk.
69
+ #
70
+ class Mailtrap
71
+ VERSION = '0.2.1'
72
+
73
+ # Create a new Mailtrap on the specified host:port. If once it true it
74
+ # will listen for one message then exit. Specify the msgdir where messages
75
+ # are written.
76
+ def initialize( host, port, once, msgfile )
77
+ @host = host
78
+ @port = port
79
+ @once = once
80
+ @msgfile = msgfile
81
+
82
+ File.open( @msgfile, "a" ) do |file|
83
+ file.puts "\n* Mailtrap started at #{@host}:#{port}\n"
84
+ end
85
+
86
+ service = TCPServer.new( @host, @port )
87
+ accept( service )
88
+ end
89
+
90
+ # Service one or more SMTP client connections
91
+ def accept( service )
92
+ while session = service.accept
93
+
94
+ class << session
95
+ def get_line
96
+ line = gets
97
+ line.chomp! unless line.nil?
98
+ line
99
+ end
100
+ end
101
+
102
+ begin
103
+ serve( session )
104
+ rescue Exception => e
105
+ end
106
+
107
+ break if @once
108
+ end
109
+ end
110
+
111
+ # Write a plain text dump of the incoming email to a text
112
+ # file. The file will be in the @msgdir folder and will
113
+ # be called smtp0001.msg, smtp0002.msg, and so on.
114
+ def write( from, to_list, message )
115
+
116
+ # Strip SMTP commands from To: and From:
117
+ from.gsub!( /MAIL FROM:\s*/, "" )
118
+ to_list = to_list.map { |to| to.gsub( /RCPT TO:\s*/, "" ) }
119
+
120
+ # Append to the end of the messages file
121
+ File.open( @msgfile, "a" ) do |file|
122
+ file.puts "* Message begins"
123
+ file.puts "From: #{from}"
124
+ file.puts "To: #{to_list.join(", ")}"
125
+ file.puts "Body:"
126
+ file.puts message
127
+ file.puts "\n* Message ends"
128
+ end
129
+
130
+ end
131
+
132
+ # Talk pidgeon-SMTP to the client to get them to hand over the message
133
+ # and go away.
134
+ def serve( connection )
135
+ connection.puts( "220 #{@host} MailTrap ready ESTMP" )
136
+ helo = connection.get_line # whoever they are
137
+
138
+ if helo =~ /^EHLO\s+/
139
+ connection.puts "250-#{@host} offers just ONE extension my pretty"
140
+ connection.puts "250 HELP"
141
+ end
142
+
143
+ # Accept MAIL FROM:
144
+ from = connection.get_line
145
+ connection.puts( "250 OK" )
146
+
147
+ to_list = []
148
+
149
+ # Accept RCPT TO: until we see DATA
150
+ loop do
151
+ to = connection.get_line
152
+ break if to.nil?
153
+
154
+ if to =~ /^DATA/
155
+ connection.puts( "354 Start your message" )
156
+ break
157
+ else
158
+ to_list << to
159
+ connection.puts( "250 OK" )
160
+ end
161
+ end
162
+
163
+ # Capture the message body terminated by <CR>.<CR>
164
+ lines = []
165
+ loop do
166
+ line = connection.get_line
167
+ break if line.nil? || line == "."
168
+ lines << line
169
+ end
170
+
171
+ # We expect the client will go away now
172
+ connection.puts( "250 OK" )
173
+ connection.gets # Quit
174
+ connection.puts "221 Seeya"
175
+ connection.close
176
+
177
+ write( from, to_list, lines.join( "\n" ) )
178
+ end
179
+ end
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe RequestLogAnalyzer, 'when harvesting like munin-plugins-rails the YAML output' do
4
+
5
+ before(:each) do
6
+ cleanup_temp_files!
7
+ run("#{log_fixture(:rails_1x)} --dump #{temp_output_file(:yaml)}")
8
+ @rla = YAML::load(File.read(temp_output_file(:yaml)))
9
+ end
10
+
11
+ after(:each) do
12
+ cleanup_temp_files!
13
+ end
14
+
15
+ it "should contain database times" do
16
+ @rla["Database time"].each do |item|
17
+ item[1][:min].should_not be_nil
18
+ item[1][:max].should_not be_nil
19
+ item[1][:hits].should_not be_nil
20
+ item[1][:sum].should_not be_nil
21
+ end
22
+ end
23
+
24
+ it "should contain request times" do
25
+ @rla["Request duration"].each do |item|
26
+ item[1][:min].should_not be_nil
27
+ item[1][:max].should_not be_nil
28
+ item[1][:hits].should_not be_nil
29
+ item[1][:sum].should_not be_nil
30
+ end
31
+ end
32
+
33
+ it "should contain failed requests" do
34
+ @rla.keys.should include("Failed requests")
35
+ end
36
+
37
+ it "should contain Process blockers" do
38
+ @rla.keys.should include("Process blockers (> 1 sec duration)")
39
+ end
40
+
41
+ it "should contain HTTP Methods" do
42
+ @rla["HTTP methods"]["GET"].should_not be_nil
43
+ end
44
+
45
+ it "should contain HTTP Methods" do
46
+ @rla["HTTP methods"]["GET"].should_not be_nil
47
+ end
48
+
49
+ it "should contain view rendering times" do
50
+ @rla["View rendering time"].each do |item|
51
+ item[1][:min].should_not be_nil
52
+ item[1][:max].should_not be_nil
53
+ item[1][:hits].should_not be_nil
54
+ item[1][:sum].should_not be_nil
55
+ end
56
+ end
57
+
58
+ end