request-log-analyzer 1.13.1 → 1.13.3

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/bin/console +17 -0
  4. data/lib/cli/command_line_arguments.rb +29 -36
  5. data/lib/cli/database_console.rb +1 -3
  6. data/lib/cli/database_console_init.rb +11 -11
  7. data/lib/cli/progressbar.rb +30 -32
  8. data/lib/cli/tools.rb +20 -23
  9. data/lib/request_log_analyzer.rb +8 -8
  10. data/lib/request_log_analyzer/aggregator.rb +4 -7
  11. data/lib/request_log_analyzer/aggregator/database_inserter.rb +10 -13
  12. data/lib/request_log_analyzer/aggregator/echo.rb +5 -7
  13. data/lib/request_log_analyzer/aggregator/summarizer.rb +15 -18
  14. data/lib/request_log_analyzer/class_level_inheritable_attributes.rb +23 -0
  15. data/lib/request_log_analyzer/controller.rb +36 -42
  16. data/lib/request_log_analyzer/database.rb +4 -6
  17. data/lib/request_log_analyzer/database/base.rb +39 -41
  18. data/lib/request_log_analyzer/database/connection.rb +8 -10
  19. data/lib/request_log_analyzer/database/request.rb +1 -3
  20. data/lib/request_log_analyzer/database/source.rb +0 -2
  21. data/lib/request_log_analyzer/database/warning.rb +4 -6
  22. data/lib/request_log_analyzer/file_format.rb +46 -49
  23. data/lib/request_log_analyzer/file_format/amazon_s3.rb +15 -19
  24. data/lib/request_log_analyzer/file_format/apache.rb +42 -45
  25. data/lib/request_log_analyzer/file_format/delayed_job.rb +13 -15
  26. data/lib/request_log_analyzer/file_format/delayed_job2.rb +9 -11
  27. data/lib/request_log_analyzer/file_format/delayed_job21.rb +9 -11
  28. data/lib/request_log_analyzer/file_format/delayed_job3.rb +5 -8
  29. data/lib/request_log_analyzer/file_format/delayed_job4.rb +5 -8
  30. data/lib/request_log_analyzer/file_format/haproxy.rb +44 -48
  31. data/lib/request_log_analyzer/file_format/merb.rb +13 -17
  32. data/lib/request_log_analyzer/file_format/mysql.rb +21 -25
  33. data/lib/request_log_analyzer/file_format/nginx.rb +0 -2
  34. data/lib/request_log_analyzer/file_format/oink.rb +30 -31
  35. data/lib/request_log_analyzer/file_format/postgresql.rb +11 -15
  36. data/lib/request_log_analyzer/file_format/rack.rb +0 -2
  37. data/lib/request_log_analyzer/file_format/rails.rb +100 -104
  38. data/lib/request_log_analyzer/file_format/rails3.rb +19 -23
  39. data/lib/request_log_analyzer/file_format/rails_development.rb +0 -1
  40. data/lib/request_log_analyzer/file_format/w3c.rb +16 -18
  41. data/lib/request_log_analyzer/filter.rb +0 -2
  42. data/lib/request_log_analyzer/filter/anonymize.rb +4 -7
  43. data/lib/request_log_analyzer/filter/field.rb +3 -6
  44. data/lib/request_log_analyzer/filter/timespan.rb +2 -6
  45. data/lib/request_log_analyzer/line_definition.rb +16 -19
  46. data/lib/request_log_analyzer/log_processor.rb +10 -14
  47. data/lib/request_log_analyzer/mailer.rb +9 -12
  48. data/lib/request_log_analyzer/output.rb +12 -14
  49. data/lib/request_log_analyzer/output/fixed_width.rb +21 -28
  50. data/lib/request_log_analyzer/output/html.rb +11 -14
  51. data/lib/request_log_analyzer/request.rb +53 -33
  52. data/lib/request_log_analyzer/source.rb +2 -5
  53. data/lib/request_log_analyzer/source/log_parser.rb +9 -16
  54. data/lib/request_log_analyzer/tracker.rb +10 -12
  55. data/lib/request_log_analyzer/tracker/duration.rb +4 -6
  56. data/lib/request_log_analyzer/tracker/frequency.rb +9 -11
  57. data/lib/request_log_analyzer/tracker/hourly_spread.rb +8 -11
  58. data/lib/request_log_analyzer/tracker/numeric_value.rb +40 -44
  59. data/lib/request_log_analyzer/tracker/timespan.rb +5 -8
  60. data/lib/request_log_analyzer/tracker/traffic.rb +8 -10
  61. data/lib/request_log_analyzer/version.rb +1 -1
  62. data/request-log-analyzer.gemspec +6 -6
  63. data/spec/integration/command_line_usage_spec.rb +33 -33
  64. data/spec/integration/mailer_spec.rb +181 -185
  65. data/spec/integration/munin_plugins_rails_spec.rb +20 -20
  66. data/spec/integration/scout_spec.rb +40 -41
  67. data/spec/lib/helpers.rb +8 -9
  68. data/spec/lib/macros.rb +2 -4
  69. data/spec/lib/matchers.rb +20 -25
  70. data/spec/lib/mocks.rb +10 -11
  71. data/spec/lib/testing_format.rb +8 -10
  72. data/spec/spec_helper.rb +5 -1
  73. data/spec/unit/aggregator/database_inserter_spec.rb +23 -23
  74. data/spec/unit/aggregator/summarizer_spec.rb +7 -7
  75. data/spec/unit/controller/controller_spec.rb +14 -14
  76. data/spec/unit/controller/log_processor_spec.rb +3 -3
  77. data/spec/unit/database/base_class_spec.rb +36 -37
  78. data/spec/unit/database/connection_spec.rb +10 -10
  79. data/spec/unit/database/database_spec.rb +11 -11
  80. data/spec/unit/file_format/amazon_s3_format_spec.rb +66 -62
  81. data/spec/unit/file_format/apache_format_spec.rb +57 -52
  82. data/spec/unit/file_format/common_regular_expressions_spec.rb +18 -21
  83. data/spec/unit/file_format/delayed_job21_format_spec.rb +22 -16
  84. data/spec/unit/file_format/delayed_job2_format_spec.rb +22 -16
  85. data/spec/unit/file_format/delayed_job3_format_spec.rb +14 -10
  86. data/spec/unit/file_format/delayed_job4_format_spec.rb +14 -10
  87. data/spec/unit/file_format/delayed_job_format_spec.rb +12 -12
  88. data/spec/unit/file_format/file_format_api_spec.rb +19 -19
  89. data/spec/unit/file_format/format_autodetection_spec.rb +7 -7
  90. data/spec/unit/file_format/haproxy_format_spec.rb +53 -49
  91. data/spec/unit/file_format/inheritance_spec.rb +13 -0
  92. data/spec/unit/file_format/line_definition_spec.rb +35 -33
  93. data/spec/unit/file_format/merb_format_spec.rb +13 -11
  94. data/spec/unit/file_format/mysql_format_spec.rb +24 -24
  95. data/spec/unit/file_format/oink_format_spec.rb +29 -29
  96. data/spec/unit/file_format/postgresql_format_spec.rb +9 -9
  97. data/spec/unit/file_format/rack_format_spec.rb +36 -31
  98. data/spec/unit/file_format/rails3_format_spec.rb +46 -46
  99. data/spec/unit/file_format/rails_format_spec.rb +52 -53
  100. data/spec/unit/file_format/w3c_format_spec.rb +27 -24
  101. data/spec/unit/filter/anonymize_filter_spec.rb +7 -7
  102. data/spec/unit/filter/field_filter_spec.rb +26 -26
  103. data/spec/unit/filter/filter_spec.rb +4 -4
  104. data/spec/unit/filter/timespan_filter_spec.rb +22 -22
  105. data/spec/unit/mailer_spec.rb +21 -21
  106. data/spec/unit/request_spec.rb +29 -29
  107. data/spec/unit/source/log_parser_spec.rb +5 -5
  108. data/spec/unit/tracker/duration_tracker_spec.rb +23 -23
  109. data/spec/unit/tracker/frequency_tracker_spec.rb +29 -30
  110. data/spec/unit/tracker/hourly_spread_spec.rb +35 -35
  111. data/spec/unit/tracker/numeric_value_tracker_spec.rb +71 -72
  112. data/spec/unit/tracker/timespan_tracker_spec.rb +31 -31
  113. data/spec/unit/tracker/tracker_api_spec.rb +43 -44
  114. data/spec/unit/tracker/traffic_tracker_spec.rb +7 -7
  115. metadata +38 -35
@@ -6,27 +6,24 @@ module CommandLine
6
6
  # If it is not possible to to so, it returns the default_width.
7
7
  # <tt>default_width</tt> Defaults to 81
8
8
  def terminal_width(default_width = 81, out = STDOUT)
9
-
9
+ tiocgwinsz = 0x5413
10
+ data = [0, 0, 0, 0].pack('SSSS')
11
+ if !RUBY_PLATFORM.include?('java') && out.ioctl(tiocgwinsz, data) >= 0 # JRuby crashes on ioctl
12
+ _, cols, _, _ = data.unpack('SSSS')
13
+ fail unless cols > 0
14
+ cols
15
+ else
16
+ fail
17
+ end
18
+ rescue
10
19
  begin
11
- tiocgwinsz = 0x5413
12
- data = [0, 0, 0, 0].pack("SSSS")
13
- if !RUBY_PLATFORM.include?('java') && out.ioctl(tiocgwinsz, data) >= 0 # JRuby crashes on ioctl
14
- _, cols, _, _ = data.unpack("SSSS")
15
- raise unless cols > 0
16
- cols
17
- else
18
- raise
20
+ IO.popen('stty -a 2>&1') do |pipe|
21
+ column_line = pipe.find { |line| /(\d+) columns/ =~ line }
22
+ fail unless column_line
23
+ Regexp.last_match[1].to_i
19
24
  end
20
25
  rescue
21
- begin
22
- IO.popen('stty -a 2>&1') do |pipe|
23
- column_line = pipe.detect { |line| /(\d+) columns/ =~ line }
24
- raise unless column_line
25
- $1.to_i
26
- end
27
- rescue
28
- default_width
29
- end
26
+ default_width
30
27
  end
31
28
  end
32
29
 
@@ -40,14 +37,14 @@ module CommandLine
40
37
  if File.directory?('./lib/tasks/')
41
38
  task_file = File.expand_path('../../tasks/request_log_analyzer.rake', File.dirname(__FILE__))
42
39
  FileUtils.copy(task_file, './lib/tasks/request_log_analyze.rake')
43
- puts "Installed rake tasks."
44
- puts "To use, run: rake rla:report"
40
+ puts 'Installed rake tasks.'
41
+ puts 'To use, run: rake rla:report'
45
42
  else
46
- puts "Cannot find /lib/tasks folder. Are you in your Rails directory?"
47
- puts "Installation aborted."
43
+ puts 'Cannot find /lib/tasks folder. Are you in your Rails directory?'
44
+ puts 'Installation aborted.'
48
45
  end
49
46
  else
50
- raise "Cannot perform this install type! (#{install_type.to_s})"
47
+ fail "Cannot perform this install type! (#{install_type})"
51
48
  end
52
49
  end
53
50
  end
@@ -1,37 +1,37 @@
1
1
  require 'date'
2
2
 
3
3
  # RequestLogAnalyzer is the base namespace in which all functionality of RequestLogAnalyzer is implemented.
4
- # This module itselfs contains some functions to help with class and source file loading. The actual
4
+ # This module itself contains some functions to help with class and source file loading. The actual
5
5
  # application startup code resides in the {RequestLogAnalyzer::Controller} class.
6
6
  #
7
7
  # The {RequestLogAnalyzer::VERSION} constant can be used to determine what version of request-log-analyzer
8
8
  # is running.
9
9
  module RequestLogAnalyzer
10
-
11
- # Convert a string/symbol in camelcase ({RequestLogAnalyzer::Controller}) to underscores
12
- # (<tt>request_log_analyzer/controller</tt>). This function can be used to load the file (using
10
+ # Convert a string/symbol in camel case ({RequestLogAnalyzer::Controller}) to underscores
11
+ # (<tt>request_log_analyzer/controller</tt>). This function can be used to load the file (using
13
12
  # <tt>require</tt>) in which the given constant is defined.
14
13
  #
15
14
  # @param [#to_s] str The string-like to convert in the following format: <tt>ModuleName::ClassName</tt>.
16
15
  # @return [String] The input string converted to underscore form.
17
16
  def self.to_underscore(str)
18
- str.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
17
+ str.to_s.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
19
18
  end
20
19
 
21
20
  # Convert a string/symbol in underscores (<tt>request_log_analyzer/controller</tt>) to camelcase
22
- # ({RequestLogAnalyzer::Controller}). This can be used to find the class that is defined in a given
21
+ # ({RequestLogAnalyzer::Controller}). This can be used to find the class that is defined in a given
23
22
  # filename.
24
23
  #
25
24
  # @param [#to_s] str The string-like to convert in the f`ollowing format: <tt>module_name/class_name</tt>.
26
- # @return [String] The input string converted to camelcase form.
25
+ # @return [String] The input string converted to camelcase form.
27
26
  def self.to_camelcase(str)
28
- str.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
27
+ str.to_s.gsub(/\/(.?)/) { '::' + Regexp.last_match[1].upcase }.gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase }
29
28
  end
30
29
  end
31
30
 
32
31
  require 'request_log_analyzer/version'
33
32
  require 'request_log_analyzer/controller'
34
33
  require 'request_log_analyzer/aggregator'
34
+ require 'request_log_analyzer/class_level_inheritable_attributes'
35
35
  require 'request_log_analyzer/file_format'
36
36
  require 'request_log_analyzer/filter'
37
37
  require 'request_log_analyzer/line_definition'
@@ -1,9 +1,7 @@
1
1
  module RequestLogAnalyzer::Aggregator
2
-
3
2
  # The base class of an aggregator. This class provides the interface to which
4
3
  # every aggregator should comply (by simply subclassing this class).
5
4
  class Base
6
-
7
5
  attr_reader :options, :source
8
6
 
9
7
  # Intializes a new RequestLogAnalyzer::Aggregator::Base instance
@@ -20,7 +18,7 @@ module RequestLogAnalyzer::Aggregator
20
18
 
21
19
  # The aggregate function is called for every request.
22
20
  # Implement the aggregating functionality in this method
23
- def aggregate(request)
21
+ def aggregate(_request)
24
22
  end
25
23
 
26
24
  # The finalize function is called after all sources are parsed and no more
@@ -29,18 +27,17 @@ module RequestLogAnalyzer::Aggregator
29
27
  end
30
28
 
31
29
  # The warning method is called if the parser eits a warning.
32
- def warning(type, message, lineno)
30
+ def warning(_type, _message, _lineno)
33
31
  end
34
32
 
35
33
  # The report function is called at the end. Implement any result reporting
36
34
  # in this function.
37
- def report(output)
35
+ def report(_output)
38
36
  end
39
37
 
40
38
  # The source_change function gets called when handling a source is started or finished.
41
- def source_change(change, filename)
39
+ def source_change(_change, _filename)
42
40
  end
43
-
44
41
  end
45
42
  end
46
43
 
@@ -1,5 +1,4 @@
1
1
  module RequestLogAnalyzer::Aggregator
2
-
3
2
  # The database aggregator will create an SQLite3 database with all parsed request information.
4
3
  #
5
4
  # The prepare method will create a database schema according to the file format definitions.
@@ -12,14 +11,13 @@ module RequestLogAnalyzer::Aggregator
12
11
  # the request record, and a field for every parsed value. Finally, a warnings table will be
13
12
  # created to log all parse warnings.
14
13
  class DatabaseInserter < Base
15
-
16
14
  attr_reader :request_count, :sources, :database
17
15
 
18
16
  # Establishes a connection to the database and creates the necessary database schema for the
19
17
  # current file format
20
18
  def prepare
21
19
  require 'request_log_analyzer/database'
22
-
20
+
23
21
  @sources = {}
24
22
  @database = RequestLogAnalyzer::Database.new(options[:database])
25
23
  @database.file_format = source.file_format
@@ -32,14 +30,14 @@ module RequestLogAnalyzer::Aggregator
32
30
  # This will create a record in the requests table and create a record for every line that has been parsed,
33
31
  # in which the captured values will be stored.
34
32
  def aggregate(request)
35
- @request_object = RequestLogAnalyzer::Database::Request.new(:first_lineno => request.first_lineno, :last_lineno => request.last_lineno)
33
+ @request_object = RequestLogAnalyzer::Database::Request.new(first_lineno: request.first_lineno, last_lineno: request.last_lineno)
36
34
  request.lines.each do |line|
37
- class_columns = database.get_class(line[:line_type]).column_names.reject { |column| ['id', 'source_id', 'request_id'].include?(column) }
38
- attributes = Hash[*line.select { |(key, _)| class_columns.include?(key.to_s)}.flatten]
39
-
35
+ class_columns = database.get_class(line[:line_type]).column_names.reject { |column| %w(id source_id request_id).include?(column) }
36
+ attributes = Hash[*line.select { |(key, _)| class_columns.include?(key.to_s) }.flatten]
37
+
40
38
  # Fix encoding patch for 1.9.2
41
- attributes.each do |k,v|
42
- attributes[k] = v.force_encoding("UTF-8") if v.is_a?(String)
39
+ attributes.each do |k, v|
40
+ attributes[k] = v.force_encoding('UTF-8') if v.is_a?(String)
43
41
  end
44
42
 
45
43
  @request_object.send("#{line[:line_type]}_lines").build(attributes)
@@ -58,7 +56,7 @@ module RequestLogAnalyzer::Aggregator
58
56
 
59
57
  # Records w warining in the warnings table.
60
58
  def warning(type, message, lineno)
61
- RequestLogAnalyzer::Database::Warning.create!(:warning_type => type.to_s, :message => message, :lineno => lineno)
59
+ RequestLogAnalyzer::Database::Warning.create!(warning_type: type.to_s, message: message, lineno: lineno)
62
60
  end
63
61
 
64
62
  # Records source changes in the sources table
@@ -66,9 +64,9 @@ module RequestLogAnalyzer::Aggregator
66
64
  if File.exist?(filename)
67
65
  case change
68
66
  when :started
69
- @sources[filename] = RequestLogAnalyzer::Database::Source.create!(:filename => filename)
67
+ @sources[filename] = RequestLogAnalyzer::Database::Source.create!(filename: filename)
70
68
  when :finished
71
- @sources[filename].update_attributes!(:filesize => File.size(filename), :mtime => File.mtime(filename))
69
+ @sources[filename].update_attributes!(filesize: File.size(filename), mtime: File.mtime(filename))
72
70
  end
73
71
  end
74
72
  end
@@ -84,6 +82,5 @@ module RequestLogAnalyzer::Aggregator
84
82
  output << output.colorize(" $ request-log-analyzer console -d #{options[:database]}\n", :bold)
85
83
  output << "\n"
86
84
  end
87
-
88
85
  end
89
86
  end
@@ -1,8 +1,6 @@
1
1
  module RequestLogAnalyzer::Aggregator
2
-
3
2
  # Echo Aggregator. Writes everything to the screen when it is passed to this aggregator
4
3
  class Echo < Base
5
-
6
4
  attr_accessor :warnings
7
5
 
8
6
  def prepare
@@ -11,8 +9,9 @@ module RequestLogAnalyzer::Aggregator
11
9
 
12
10
  # Display every parsed line immediately to the terminal
13
11
  def aggregate(request)
14
- puts "\nRequest: \n" + request.lines.map { |l|
15
- "\t#{l[:lineno]}:#{l[:line_type]}: #{l.reject { |(k,_)| [:lineno, :line_type].include?(k) }.inspect}" }.join("\n")
12
+ puts "\nRequest: \n" + request.lines.map do |l|
13
+ "\t#{l[:lineno]}:#{l[:line_type]}: #{l.reject { |(k, _)| [:lineno, :line_type].include?(k) }.inspect}"
14
+ end.join("\n")
16
15
  end
17
16
 
18
17
  # Capture all warnings during parsing
@@ -22,9 +21,8 @@ module RequestLogAnalyzer::Aggregator
22
21
 
23
22
  # Display every warning in the report when finished parsing
24
23
  def report(output)
25
- output.title("Warnings during parsing")
24
+ output.title('Warnings during parsing')
26
25
  @warnings.each { |w| output.puts(w) }
27
26
  end
28
-
29
27
  end
30
- end
28
+ end
@@ -1,9 +1,6 @@
1
1
  module RequestLogAnalyzer::Aggregator
2
-
3
2
  class Summarizer < Base
4
-
5
3
  class Definer
6
-
7
4
  attr_reader :trackers
8
5
 
9
6
  # Initialize tracker array
@@ -31,8 +28,8 @@ module RequestLogAnalyzer::Aggregator
31
28
  # <tt>tracker_class</tt> The class to include
32
29
  # <tt>optiont</tt> The options to pass to the trackers.
33
30
  def track(tracker_klass, value_field = {}, other_options = {})
34
- options = value_field.kind_of?(Symbol) ? other_options.merge(:value => value_field) : value_field.merge(other_options)
35
- tracker_klass = RequestLogAnalyzer::Tracker.const_get(RequestLogAnalyzer.to_camelcase(tracker_klass)) if tracker_klass.kind_of?(Symbol)
31
+ options = value_field.is_a?(Symbol) ? other_options.merge(value: value_field) : value_field.merge(other_options)
32
+ tracker_klass = RequestLogAnalyzer::Tracker.const_get(RequestLogAnalyzer.to_camelcase(tracker_klass)) if tracker_klass.is_a?(Symbol)
36
33
  @trackers << tracker_klass.new(options)
37
34
  end
38
35
  end
@@ -54,7 +51,7 @@ module RequestLogAnalyzer::Aggregator
54
51
 
55
52
  # Call prepare on all trackers.
56
53
  def prepare
57
- raise "No trackers set up in Summarizer!" if @trackers.nil? || @trackers.empty?
54
+ fail 'No trackers set up in Summarizer!' if @trackers.nil? || @trackers.empty?
58
55
  @trackers.each { |tracker| tracker.prepare }
59
56
  end
60
57
 
@@ -82,7 +79,7 @@ module RequestLogAnalyzer::Aggregator
82
79
  # for every tracker and combines these into a single YAML export.
83
80
  def to_yaml
84
81
  require 'yaml'
85
- trackers_export = @trackers.inject({}) do |export, tracker|
82
+ trackers_export = @trackers.reduce({}) do |export, tracker|
86
83
  export[tracker.title] = tracker.to_yaml_object; export
87
84
  end
88
85
  YAML.dump(trackers_export)
@@ -104,10 +101,10 @@ module RequestLogAnalyzer::Aggregator
104
101
  # Generate report header.
105
102
  # <tt>output</tt> RequestLogAnalyzer::Output object to output to
106
103
  def report_header(output)
107
- output.title("Request summary")
104
+ output.title('Request summary')
108
105
 
109
- output.with_style(:cell_separator => false) do
110
- output.table({:width => 20}, {:font => :bold}) do |rows|
106
+ output.with_style(cell_separator: false) do
107
+ output.table({ width: 20 }, { font: :bold }) do |rows|
111
108
  source.processed_files.each do |f|
112
109
  rows << ['Processed File:', f]
113
110
  end
@@ -115,7 +112,7 @@ module RequestLogAnalyzer::Aggregator
115
112
  rows << ['Skipped lines:', source.skipped_lines]
116
113
  rows << ['Parsed requests:', source.parsed_requests]
117
114
  rows << ['Skipped requests:', source.skipped_requests]
118
- rows << ["Warnings:", @warnings_encountered.map { |(key, value)| "#{key}: #{value}" }.join(', ')] if has_warnings?
115
+ rows << ['Warnings:', @warnings_encountered.map { |(key, value)| "#{key}: #{value}" }.join(', ')] if has_warnings?
119
116
  end
120
117
  end
121
118
  output << "\n"
@@ -125,19 +122,19 @@ module RequestLogAnalyzer::Aggregator
125
122
  # <tt>output</tt> RequestLogAnalyzer::Output object to output to
126
123
  def report_footer(output)
127
124
  if has_log_ordering_warnings?
128
- output.title("Parse warnings")
125
+ output.title('Parse warnings')
129
126
 
130
- output.puts "Parsable lines were encountered without a header line before it. It"
131
- output.puts "could be that logging is not setup correctly for your application."
132
- output.puts "Visit this website for logging configuration tips:"
133
- output.puts output.link("http://github.com/wvanbergen/request-log-analyzer/wikis/configure-logging")
127
+ output.puts 'Parsable lines were encountered without a header line before it. It'
128
+ output.puts 'could be that logging is not setup correctly for your application.'
129
+ output.puts 'Visit this website for logging configuration tips:'
130
+ output.puts output.link('http://github.com/wvanbergen/request-log-analyzer/wikis/configure-logging')
134
131
  output.puts
135
132
  end
136
133
  end
137
134
 
138
135
  # Returns true if there were any warnings generated by the trackers
139
136
  def has_warnings?
140
- @warnings_encountered.inject(0) { |result, (_, value)| result += value } > 0
137
+ @warnings_encountered.reduce(0) { |result, (_, value)| result += value } > 0
141
138
  end
142
139
 
143
140
  # Returns true if there were any log ordering warnings
@@ -149,7 +146,7 @@ module RequestLogAnalyzer::Aggregator
149
146
  # <tt>type</tt> Type of warning
150
147
  # <tt>message</tt> Warning message
151
148
  # <tt>lineno</tt> The line on which the error was encountered
152
- def warning(type, message, lineno)
149
+ def warning(type, _message, _lineno)
153
150
  @warnings_encountered[type] ||= 0
154
151
  @warnings_encountered[type] += 1
155
152
  end
@@ -0,0 +1,23 @@
1
+ module RequestLogAnalyzer
2
+ module ClassLevelInheritableAttributes
3
+ def inheritable_attributes(*args)
4
+ @inheritable_attributes ||= [:inheritable_attributes]
5
+ @inheritable_attributes += args
6
+ args.each do |arg|
7
+ class_eval %(
8
+ class << self; attr_accessor :#{arg} end
9
+ )
10
+ end
11
+ @inheritable_attributes
12
+ end
13
+
14
+ def inherited(subclass)
15
+ @inheritable_attributes.each do |inheritable_attribute|
16
+ instance_var = "@#{inheritable_attribute}"
17
+ subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
18
+ end
19
+
20
+ super
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,4 @@
1
1
  module RequestLogAnalyzer
2
-
3
2
  # The RequestLogAnalyzer::Controller class creates a LogParser instance for the
4
3
  # requested file format and connect it with sources and aggregators.
5
4
  #
@@ -14,13 +13,11 @@ module RequestLogAnalyzer
14
13
  # sources are registered in the correct order. This can be helpful to parse requests
15
14
  # from several logrotated log files.
16
15
  class Controller
17
-
18
16
  attr_reader :source, :filters, :aggregators, :output, :options
19
17
 
20
18
  # Builds a RequestLogAnalyzer::Controller given parsed command line arguments
21
19
  # <tt>arguments<tt> A CommandLine::Arguments hash containing parsed commandline parameters.
22
20
  def self.build_from_arguments(arguments)
23
-
24
21
  options = {}
25
22
 
26
23
  # Copy fields
@@ -51,9 +48,9 @@ module RequestLogAnalyzer
51
48
 
52
49
  # Apache format workaround
53
50
  if arguments[:rails_format]
54
- options[:format] = {:rails => arguments[:rails_format]}
51
+ options[:format] = { rails: arguments[:rails_format] }
55
52
  elsif arguments[:apache_format]
56
- options[:format] = {:apache => arguments[:apache_format]}
53
+ options[:format] = { apache: arguments[:apache_format] }
57
54
  end
58
55
 
59
56
  # Handle output format casing
@@ -149,7 +146,7 @@ module RequestLogAnalyzer
149
146
 
150
147
  # Deprecation warnings
151
148
  if options[:dump]
152
- warn "[DEPRECATION] `:dump` is deprecated. Please use `:yaml` instead."
149
+ warn '[DEPRECATION] `:dump` is deprecated. Please use `:yaml` instead.'
153
150
  options[:yaml] = options[:dump]
154
151
  end
155
152
 
@@ -166,21 +163,21 @@ module RequestLogAnalyzer
166
163
  output_amount = options[:report_amount] == 'all' ? :all : options[:report_amount].to_i
167
164
 
168
165
  if options[:file]
169
- output_object = %w[File StringIO].include?(options[:file].class.name) ? options[:file] : File.new(options[:file], "w+")
170
- output_args = {:width => 80, :color => false, :characters => :ascii, :sort => output_sort, :amount => output_amount }
166
+ output_object = %w( File StringIO ).include?(options[:file].class.name) ? options[:file] : File.new(options[:file], 'w+')
167
+ output_args = { width: 80, color: false, characters: :ascii, sort: output_sort, amount: output_amount }
171
168
  elsif options[:mail]
172
- output_object = RequestLogAnalyzer::Mailer.new(options[:mail], options[:mailhost], :subject => options[:mailsubject], :from => options[:mailfrom], :from_alias => options[:mailfrom_name])
173
- output_args = {:width => 80, :color => false, :characters => :ascii, :sort => output_sort, :amount => output_amount }
169
+ output_object = RequestLogAnalyzer::Mailer.new(options[:mail], options[:mailhost], subject: options[:mailsubject], from: options[:mailfrom], from_alias: options[:mailfrom_name])
170
+ output_args = { width: 80, color: false, characters: :ascii, sort: output_sort, amount: output_amount }
174
171
  else
175
172
  output_object = STDOUT
176
- output_args = {:width => options[:report_width].to_i, :color => !options[:boring],
177
- :characters => (options[:boring] ? :ascii : :utf), :sort => output_sort, :amount => output_amount }
173
+ output_args = { width: options[:report_width].to_i, color: !options[:boring],
174
+ characters: (options[:boring] ? :ascii : :utf), sort: output_sort, amount: output_amount }
178
175
  end
179
176
 
180
177
  output_instance = output_class.new(output_object, output_args)
181
178
 
182
179
  # Create the controller with the correct file format
183
- if options[:format].kind_of?(Hash)
180
+ if options[:format].is_a?(Hash)
184
181
  file_format = RequestLogAnalyzer::FileFormat.load(options[:format].keys[0], options[:format].values[0])
185
182
  else
186
183
  file_format = RequestLogAnalyzer::FileFormat.load(options[:format])
@@ -189,15 +186,15 @@ module RequestLogAnalyzer
189
186
  # Kickstart the controller
190
187
  controller =
191
188
  Controller.new(options[:source].new(file_format,
192
- :source_files => options[:source_files],
193
- :parse_strategy => options[:parse_strategy]),
194
- { :output => output_instance,
195
- :database => options[:database], # FUGLY!
196
- :yaml => options[:yaml],
197
- :reset_database => options[:reset_database],
198
- :no_progress => options[:no_progress],
199
- :silent => options[:silent]
200
- })
189
+ source_files: options[:source_files],
190
+ parse_strategy: options[:parse_strategy]),
191
+ output: output_instance,
192
+ database: options[:database], # FUGLY!
193
+ yaml: options[:yaml],
194
+ reset_database: options[:reset_database],
195
+ no_progress: options[:no_progress],
196
+ silent: options[:silent]
197
+ )
201
198
 
202
199
  # register filters
203
200
  if options[:after] || options[:before]
@@ -215,13 +212,13 @@ module RequestLogAnalyzer
215
212
 
216
213
  if options[:reject]
217
214
  options[:reject].each do |(field, value)|
218
- controller.add_filter(:field, :mode => :reject, :field => field, :value => value)
215
+ controller.add_filter(:field, mode: :reject, field: field, value: value)
219
216
  end
220
217
  end
221
218
 
222
219
  if options[:select]
223
220
  options[:select].each do |(field, value)|
224
- controller.add_filter(:field, :mode => :select, :field => field, :value => value)
221
+ controller.add_filter(:field, mode: :select, field: field, value: value)
225
222
  end
226
223
  end
227
224
 
@@ -232,7 +229,7 @@ module RequestLogAnalyzer
232
229
  controller.add_aggregator(:database_inserter) if options[:database] && !options[:aggregator].include?('database')
233
230
 
234
231
  file_format.setup_environment(controller)
235
- return controller
232
+ controller
236
233
  end
237
234
 
238
235
  # Builds a new Controller for the given log file format.
@@ -244,7 +241,6 @@ module RequestLogAnalyzer
244
241
  # * <tt>:no_progress</tt> No progress bar
245
242
  # * <tt>:silent</tt> Minimal output, only error
246
243
  def initialize(source, options = {})
247
-
248
244
  @source = source
249
245
  @options = options
250
246
  @aggregators = []
@@ -253,7 +249,7 @@ module RequestLogAnalyzer
253
249
  @interrupted = false
254
250
 
255
251
  # Register the request format for this session after checking its validity
256
- raise "Invalid file format!" unless @source.file_format.valid?
252
+ fail 'Invalid file format!' unless @source.file_format.valid?
257
253
 
258
254
  # Install event handlers for wrnings, progress updates and source changes
259
255
  @source.warning = lambda { |type, message, lineno| @aggregators.each { |agg| agg.warning(type, message, lineno) } }
@@ -290,15 +286,15 @@ module RequestLogAnalyzer
290
286
  # Adds an aggregator to the controller. The aggregator will be called for every request
291
287
  # that is parsed from the provided sources (see add_source)
292
288
  def add_aggregator(agg)
293
- agg = RequestLogAnalyzer::Aggregator.const_get(RequestLogAnalyzer.to_camelcase(agg)) if agg.kind_of?(String) || agg.kind_of?(Symbol)
289
+ agg = RequestLogAnalyzer::Aggregator.const_get(RequestLogAnalyzer.to_camelcase(agg)) if agg.is_a?(String) || agg.is_a?(Symbol)
294
290
  @aggregators << agg.new(@source, @options)
295
291
  end
296
292
 
297
- alias :>> :add_aggregator
293
+ alias_method :>>, :add_aggregator
298
294
 
299
295
  # Adds a request filter to the controller.
300
296
  def add_filter(filter, filter_options = {})
301
- filter = RequestLogAnalyzer::Filter.const_get(RequestLogAnalyzer.to_camelcase(filter)) if filter.kind_of?(Symbol)
297
+ filter = RequestLogAnalyzer::Filter.const_get(RequestLogAnalyzer.to_camelcase(filter)) if filter.is_a?(Symbol)
302
298
  @filters << filter.new(source.file_format, @options.merge(filter_options))
303
299
  end
304
300
 
@@ -310,7 +306,7 @@ module RequestLogAnalyzer
310
306
  request = filter.filter(request)
311
307
  return nil if request.nil?
312
308
  end
313
- return request
309
+ request
314
310
  end
315
311
 
316
312
  # Push a request to all the aggregators (@aggregators).
@@ -318,7 +314,7 @@ module RequestLogAnalyzer
318
314
  def aggregate_request(request)
319
315
  return false unless request
320
316
  @aggregators.each { |agg| agg.aggregate(request) }
321
- return true
317
+ true
322
318
  end
323
319
 
324
320
  # Runs RequestLogAnalyzer
@@ -330,7 +326,6 @@ module RequestLogAnalyzer
330
326
  # 5. Call report on every aggregator
331
327
  # 6. Finalize Source
332
328
  def run!
333
-
334
329
  # @aggregators.each{|agg| p agg}
335
330
 
336
331
  @aggregators.each { |agg| agg.prepare }
@@ -349,27 +344,26 @@ module RequestLogAnalyzer
349
344
 
350
345
  @source.finalize
351
346
 
352
- if @output.io.kind_of?(File)
347
+ if @output.io.is_a?(File)
353
348
  unless @options[:silent]
354
349
  puts
355
- puts "Report written to: " + File.expand_path(@output.io.path)
356
- puts "Need an expert to analyze your application?"
357
- puts "Mail to contact@railsdoctors.com or visit us at http://railsdoctors.com"
358
- puts "Thanks for using request-log-analyzer!"
350
+ puts 'Report written to: ' + File.expand_path(@output.io.path)
351
+ puts 'Need an expert to analyze your application?'
352
+ puts 'Mail to contact@railsdoctors.com or visit us at http://railsdoctors.com'
353
+ puts 'Thanks for using request-log-analyzer!'
359
354
  end
360
355
  @output.io.close
361
- elsif @output.io.kind_of?(RequestLogAnalyzer::Mailer)
356
+ elsif @output.io.is_a?(RequestLogAnalyzer::Mailer)
362
357
  @output.io.mail
363
358
  end
364
359
  end
365
360
 
366
361
  def install_signal_handlers
367
- Signal.trap("INT") do
362
+ Signal.trap('INT') do
368
363
  handle_progress(:interrupted)
369
- puts "Caught interrupt! Stopping parsing..."
364
+ puts 'Caught interrupt! Stopping parsing...'
370
365
  @interrupted = true
371
366
  end
372
367
  end
373
-
374
368
  end
375
369
  end