request-log-analyzer 1.13.1 → 1.13.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -2,7 +2,6 @@ require 'rubygems'
2
2
  require 'active_record'
3
3
 
4
4
  class RequestLogAnalyzer::Database
5
-
6
5
  require 'request_log_analyzer/database/connection'
7
6
  include RequestLogAnalyzer::Database::Connection
8
7
 
@@ -45,7 +44,6 @@ class RequestLogAnalyzer::Database
45
44
  # Loads an ActiveRecord-based class that correspond to the given parameter, which can either be
46
45
  # a table name or a LineDefinition instance.
47
46
  def load_activerecord_class(linedefinition_or_table)
48
-
49
47
  case linedefinition_or_table
50
48
  when String, Symbol
51
49
  klass_name = linedefinition_or_table.to_s.singularize.camelize
@@ -58,13 +56,13 @@ class RequestLogAnalyzer::Database
58
56
  Object.const_set(klass_name, klass)
59
57
  klass = Object.const_get(klass_name)
60
58
  @line_classes << klass
61
- return klass
59
+ klass
62
60
  end
63
61
 
64
62
  def fileformat_classes
65
- raise "No file_format provided!" unless file_format
66
- line_classes = file_format.line_definitions.map { |(name, definition)| load_activerecord_class(definition) }
67
- return default_classes + line_classes
63
+ fail 'No file_format provided!' unless file_format
64
+ line_classes = file_format.line_definitions.map { |(_name, definition)| load_activerecord_class(definition) }
65
+ default_classes + line_classes
68
66
  end
69
67
 
70
68
  # Creates the database schema and related ActiveRecord::Base subclasses that correspond to the
@@ -1,5 +1,4 @@
1
1
  class RequestLogAnalyzer::Database::Base < ActiveRecord::Base
2
-
3
2
  self.abstract_class = true
4
3
 
5
4
  def <=>(other)
@@ -9,14 +8,14 @@ class RequestLogAnalyzer::Database::Base < ActiveRecord::Base
9
8
  source_comparison
10
9
  end
11
10
  end
12
-
11
+
13
12
  # Handle format manually, because it is prohibidado in Rails 3.2.1
14
13
  def format=(arg)
15
- self.attributes[:format] = arg
14
+ attributes[:format] = arg
16
15
  end
17
-
18
- def format(arg)
19
- self.attributes[:format]
16
+
17
+ def format(_arg)
18
+ attributes[:format]
20
19
  end
21
20
 
22
21
  def line_type
@@ -32,46 +31,46 @@ class RequestLogAnalyzer::Database::Base < ActiveRecord::Base
32
31
  klass.line_definition = definition
33
32
 
34
33
  # Set relations with requests and sources table
35
- klass.belongs_to :request, :class_name => RequestLogAnalyzer::Database::Request.name
36
- klass.belongs_to :source, :class_name => RequestLogAnalyzer::Database::Source.name
34
+ klass.belongs_to :request, class_name: RequestLogAnalyzer::Database::Request.name
35
+ klass.belongs_to :source, class_name: RequestLogAnalyzer::Database::Source.name
37
36
 
38
37
  # Serialize complex fields into the database
39
- definition.captures.select { |c| c.has_key?(:provides) }.each do |capture|
38
+ definition.captures.select { |c| c.key?(:provides) }.each do |capture|
40
39
  klass.send(:serialize, capture[:name], Hash)
41
40
  end
42
41
 
43
- RequestLogAnalyzer::Database::Request.has_many "#{definition.name}_lines".to_sym
44
- RequestLogAnalyzer::Database::Source.has_many "#{definition.name}_lines".to_sym
42
+ RequestLogAnalyzer::Database::Request.has_many "#{definition.name}_lines".to_sym
43
+ RequestLogAnalyzer::Database::Source.has_many "#{definition.name}_lines".to_sym
45
44
 
46
- return klass
45
+ klass
47
46
  end
48
47
 
49
48
  def self.subclass_from_table(table, klass = Class.new(RequestLogAnalyzer::Database::Base))
50
- raise "Table #{table} not found!" unless database.connection.table_exists?(table)
51
-
49
+ fail "Table #{table} not found!" unless database.connection.table_exists?(table)
50
+
52
51
  klass.table_name = table
53
52
 
54
53
  if klass.column_names.include?('request_id')
55
- klass.belongs_to :request, :class_name => RequestLogAnalyzer::Database::Request.name
54
+ klass.belongs_to :request, class_name: RequestLogAnalyzer::Database::Request.name
56
55
  RequestLogAnalyzer::Database::Request.has_many table.to_sym
57
56
  end
58
57
 
59
58
  if klass.column_names.include?('source_id')
60
- klass.belongs_to :source, :class_name => RequestLogAnalyzer::Database::Source.name
59
+ klass.belongs_to :source, class_name: RequestLogAnalyzer::Database::Source.name
61
60
  RequestLogAnalyzer::Database::Source.has_many table.to_sym
62
61
  end
63
62
 
64
- return klass
63
+ klass
65
64
  end
66
65
 
67
66
  def self.drop_table!
68
- database.connection.remove_index(self.table_name, [:source_id]) rescue nil
69
- database.connection.remove_index(self.table_name, [:request_id]) rescue nil
70
- database.connection.drop_table(self.table_name) if database.connection.table_exists?(self.table_name)
67
+ database.connection.remove_index(table_name, [:source_id]) rescue nil
68
+ database.connection.remove_index(table_name, [:request_id]) rescue nil
69
+ database.connection.drop_table(table_name) if database.connection.table_exists?(table_name)
71
70
  end
72
71
 
73
72
  def self.create_table!
74
- raise "No line_definition available to base table schema on!" unless self.line_definition
73
+ fail 'No line_definition available to base table schema on!' unless line_definition
75
74
 
76
75
  unless table_exists?
77
76
  database.connection.create_table(table_name.to_sym) do |t|
@@ -88,13 +87,13 @@ class RequestLogAnalyzer::Database::Base < ActiveRecord::Base
88
87
  t.column(column_name, column_type(capture[:type]))
89
88
 
90
89
  # If the capture provides other field as well, create columns for them, too
91
- capture[:provides].each { |field, field_type| t.column(field, column_type(field_type)) } if capture[:provides].kind_of?(Hash)
90
+ capture[:provides].each { |field, field_type| t.column(field, column_type(field_type)) } if capture[:provides].is_a?(Hash)
92
91
  end
93
92
  end
94
-
93
+
95
94
  # Add indices to table for more speedy querying
96
- database.connection.add_index(self.table_name.to_sym, [:request_id]) # rescue
97
- database.connection.add_index(self.table_name.to_sym, [:source_id]) # rescue
95
+ database.connection.add_index(table_name.to_sym, [:request_id]) # rescue
96
+ database.connection.add_index(table_name.to_sym, [:source_id]) # rescue
98
97
  end
99
98
  end
100
99
 
@@ -102,22 +101,21 @@ class RequestLogAnalyzer::Database::Base < ActiveRecord::Base
102
101
  # TODO: make more robust / include in file-format definition
103
102
  def self.column_type(type_indicator)
104
103
  case type_indicator
105
- when :eval; :text
106
- when :hash; :text
107
- when :text; :text
108
- when :string; :string
109
- when :sec; :float
110
- when :msec; :float
111
- when :duration; :float
112
- when :float; :float
113
- when :double; :float
114
- when :integer; :integer
115
- when :int; :int
116
- when :timestamp; :datetime
117
- when :datetime; :datetime
118
- when :date; :date
104
+ when :eval then :text
105
+ when :hash then :text
106
+ when :text then :text
107
+ when :string then :string
108
+ when :sec then :float
109
+ when :msec then :float
110
+ when :duration then :float
111
+ when :float then :float
112
+ when :double then :float
113
+ when :integer then :integer
114
+ when :int then :int
115
+ when :timestamp then :datetime
116
+ when :datetime then :datetime
117
+ when :date then :date
119
118
  else :string
120
119
  end
121
120
  end
122
-
123
- end
121
+ end
@@ -1,29 +1,28 @@
1
1
  module RequestLogAnalyzer::Database::Connection
2
-
3
2
  def self.from_string(string)
4
3
  hash = {}
5
4
  if string =~ /^(?:\w+=(?:[^;])*;)*\w+=(?:[^;])*$/
6
5
  string.scan(/(\w+)=([^;]*);?/) { |variable, value| hash[variable.to_sym] = value }
7
6
  elsif string =~ /^(\w+)\:\/\/(?:(?:([^:]+)(?:\:([^:]+))?\@)?([\w\.-]+)\/)?([\w\:\-\.\/]+)$/
8
- hash[:adapter], hash[:username], hash[:password], hash[:host], hash[:database] = $1, $2, $3, $4, $5
9
- hash.delete_if { |k, v| v.nil? }
7
+ hash[:adapter], hash[:username], hash[:password], hash[:host], hash[:database] = Regexp.last_match[1], Regexp.last_match[2], Regexp.last_match[3], Regexp.last_match[4], Regexp.last_match[5]
8
+ hash.delete_if { |_k, v| v.nil? }
10
9
  end
11
- return hash.empty? ? nil : hash
10
+ hash.empty? ? nil : hash
12
11
  end
13
12
 
14
13
  def connect(connection_identifier)
15
- if connection_identifier.kind_of?(Hash)
14
+ if connection_identifier.is_a?(Hash)
16
15
  ActiveRecord::Base.establish_connection(connection_identifier)
17
16
  elsif connection_identifier == ':memory:'
18
- ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
17
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
19
18
  elsif connection_hash = RequestLogAnalyzer::Database::Connection.from_string(connection_identifier)
20
19
  ActiveRecord::Base.establish_connection(connection_hash)
21
- elsif connection_identifier.kind_of?(String) # Normal SQLite 3 database file
22
- ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => connection_identifier)
20
+ elsif connection_identifier.is_a?(String) # Normal SQLite 3 database file
21
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: connection_identifier)
23
22
  elsif connection_identifier.nil?
24
23
  nil
25
24
  else
26
- raise "Cannot connect with this connection_identifier: #{connection_identifier.inspect}"
25
+ fail "Cannot connect with this connection_identifier: #{connection_identifier.inspect}"
27
26
  end
28
27
  end
29
28
 
@@ -34,5 +33,4 @@ module RequestLogAnalyzer::Database::Connection
34
33
  def connection
35
34
  RequestLogAnalyzer::Database::Base.connection
36
35
  end
37
-
38
36
  end
@@ -1,10 +1,9 @@
1
1
  class RequestLogAnalyzer::Database::Request < RequestLogAnalyzer::Database::Base
2
-
3
2
  # Returns an array of all the Line objects of this request in the correct order.
4
3
  def lines
5
4
  @lines ||= begin
6
5
  lines = []
7
- self.class.reflections.each { |r, d| lines += self.send(r).all }
6
+ self.class.reflections.each { |r, _d| lines += send(r).all }
8
7
  lines.sort
9
8
  end
10
9
  end
@@ -18,5 +17,4 @@ class RequestLogAnalyzer::Database::Request < RequestLogAnalyzer::Database::Base
18
17
  end
19
18
  end
20
19
  end
21
-
22
20
  end
@@ -1,5 +1,4 @@
1
1
  class RequestLogAnalyzer::Database::Source < RequestLogAnalyzer::Database::Base
2
-
3
2
  def self.create_table!
4
3
  unless database.connection.table_exists?(:sources)
5
4
  database.connection.create_table(:sources) do |t|
@@ -9,5 +8,4 @@ class RequestLogAnalyzer::Database::Source < RequestLogAnalyzer::Database::Base
9
8
  end
10
9
  end
11
10
  end
12
-
13
11
  end
@@ -1,14 +1,12 @@
1
1
  class RequestLogAnalyzer::Database::Warning < RequestLogAnalyzer::Database::Base
2
-
3
2
  def self.create_table!
4
3
  unless database.connection.table_exists?(:warnings)
5
4
  database.connection.create_table(:warnings) do |t|
6
- t.column :warning_type, :string, :limit => 30, :null => false
7
- t.column :message, :string
8
- t.column :source_id, :integer
9
- t.column :lineno, :integer
5
+ t.column :warning_type, :string, limit: 30, null: false
6
+ t.column :message, :string
7
+ t.column :source_id, :integer
8
+ t.column :lineno, :integer
10
9
  end
11
10
  end
12
11
  end
13
-
14
12
  end
@@ -1,7 +1,6 @@
1
1
  require 'request_log_analyzer/request'
2
2
 
3
3
  module RequestLogAnalyzer::FileFormat
4
-
5
4
  autoload :Rails, 'request_log_analyzer/file_format/rails'
6
5
  autoload :Rails3, 'request_log_analyzer/file_format/rails3'
7
6
  autoload :RailsDevelopment, 'request_log_analyzer/file_format/rails_development'
@@ -29,15 +28,15 @@ module RequestLogAnalyzer::FileFormat
29
28
  # * A symbol of a built-in file format (e.g. :rails)
30
29
  def self.load(file_format, *args)
31
30
  klass = nil
32
- if file_format.kind_of?(RequestLogAnalyzer::FileFormat::Base)
31
+ if file_format.is_a?(RequestLogAnalyzer::FileFormat::Base)
33
32
  # this already is a file format! return itself
34
33
  return @current_file_format = file_format
35
34
 
36
- elsif file_format.kind_of?(Class) && file_format.ancestors.include?(RequestLogAnalyzer::FileFormat::Base)
35
+ elsif file_format.is_a?(Class) && file_format.ancestors.include?(RequestLogAnalyzer::FileFormat::Base)
37
36
  # a usable class is provided. Use this format class.
38
37
  klass = file_format
39
38
 
40
- elsif file_format.kind_of?(String) && File.exist?(file_format) && File.file?(file_format)
39
+ elsif file_format.is_a?(String) && File.exist?(file_format) && File.file?(file_format)
41
40
  # load a format from a ruby file
42
41
  require File.expand_path(file_format)
43
42
 
@@ -47,7 +46,7 @@ module RequestLogAnalyzer::FileFormat
47
46
  elsif Object.const_defined?(const)
48
47
  klass = Object.const_get(const)
49
48
  else
50
- raise "Cannot load class #{const} from #{file_format}!"
49
+ fail "Cannot load class #{const} from #{file_format}!"
51
50
  end
52
51
 
53
52
  else
@@ -56,19 +55,19 @@ module RequestLogAnalyzer::FileFormat
56
55
  end
57
56
 
58
57
  # check the returned klass to see if it can be used
59
- raise "Could not load a file format from #{file_format.inspect}" if klass.nil?
60
- raise "Invalid FileFormat class from #{file_format.inspect}" unless klass.kind_of?(Class) && klass.ancestors.include?(RequestLogAnalyzer::FileFormat::Base)
58
+ fail "Could not load a file format from #{file_format.inspect}" if klass.nil?
59
+ fail "Invalid FileFormat class from #{file_format.inspect}" unless klass.is_a?(Class) && klass.ancestors.include?(RequestLogAnalyzer::FileFormat::Base)
61
60
 
62
61
  @current_file_format = klass.create(*args) # return an instance of the class
63
62
  end
64
-
63
+
65
64
  # Returns an array of all FileFormat instances that are shipped with request-log-analyzer by default.
66
65
  def self.all_formats
67
- @all_formats ||= Dir[File.expand_path('file_format/*.rb', File.dirname(__FILE__))].map do |file|
68
- self.load(File.basename(file, '.rb'))
66
+ @all_formats ||= Dir[File.expand_path('file_format/*.rb', File.dirname(__FILE__))].map do |file|
67
+ load(File.basename(file, '.rb'))
69
68
  end
70
69
  end
71
-
70
+
72
71
  # Autodetects the filetype of a given file.
73
72
  #
74
73
  # Returns a FileFormat instance, by parsing the first couple of lines of the provided file
@@ -78,18 +77,17 @@ module RequestLogAnalyzer::FileFormat
78
77
  # <tt>file</tt>:: The file to detect the file format for.
79
78
  # <tt>line_count</tt>:: The number of lines to take into consideration
80
79
  def self.autodetect(file, line_count = 50)
81
-
82
- parsers = all_formats.map { |f| RequestLogAnalyzer::Source::LogParser.new(f, :parse_strategy => 'cautious') }
83
-
80
+ parsers = all_formats.map { |f| RequestLogAnalyzer::Source::LogParser.new(f, parse_strategy: 'cautious') }
81
+
84
82
  File.open(file, 'rb') do |io|
85
83
  while io.lineno < line_count && (line = io.gets)
86
- parsers.each { |parser| parser.parse_line(line) }
84
+ parsers.each { |parser| parser.parse_line(line) }
87
85
  end
88
86
  end
89
-
87
+
90
88
  parsers.select { |p| autodetect_score(p) > 0 }.max { |a, b| autodetect_score(a) <=> autodetect_score(b) }.file_format rescue nil
91
89
  end
92
-
90
+
93
91
  # Calculates a file format auto detection score based on the parser statistics.
94
92
  #
95
93
  # This method returns a score as an integer. Usually, the score will increase as more
@@ -113,10 +111,9 @@ module RequestLogAnalyzer::FileFormat
113
111
  # This module contains some methods to construct regular expressions for log fragments
114
112
  # that are commonly used, like IP addresses and timestamp.
115
113
  #
116
- # You need to extend (or include in an unlikely case) this module in your file format
114
+ # You need to extend (or include in an unlikely case) this module in your file format
117
115
  # to use these regular expression constructors.
118
116
  module CommonRegularExpressions
119
-
120
117
  TIMESTAMP_PARTS = {
121
118
  'a' => '(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)',
122
119
  'b' => '(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)',
@@ -126,13 +123,13 @@ module RequestLogAnalyzer::FileFormat
126
123
  'Z' => '(?:[+-]\d{4}|[A-Z]{3,4})',
127
124
  '%' => '%'
128
125
  }
129
-
126
+
130
127
  # Creates a regular expression to match a hostname
131
128
  def hostname(blank = false)
132
129
  regexp = /(?:(?:[a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*(?:[A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])/
133
130
  add_blank_option(regexp, blank)
134
131
  end
135
-
132
+
136
133
  # Creates a regular expression to match a hostname or ip address
137
134
  def hostname_or_ip_address(blank = false)
138
135
  regexp = Regexp.union(hostname, ip_address)
@@ -148,10 +145,10 @@ module RequestLogAnalyzer::FileFormat
148
145
  format_string.scan(/([^%]*)(?:%([A-Za-z%]))?/) do |literal, variable|
149
146
  regexp << Regexp.quote(literal)
150
147
  if variable
151
- if TIMESTAMP_PARTS.has_key?(variable)
148
+ if TIMESTAMP_PARTS.key?(variable)
152
149
  regexp << TIMESTAMP_PARTS[variable]
153
150
  else
154
- raise "Unknown variable: %#{variable}"
151
+ fail "Unknown variable: %#{variable}"
155
152
  end
156
153
  end
157
154
  end
@@ -161,11 +158,10 @@ module RequestLogAnalyzer::FileFormat
161
158
 
162
159
  # Construct a regular expression to parse IPv4 and IPv6 addresses.
163
160
  #
164
- # Allow nil values if the blank option is given. This can be true to
161
+ # Allow nil values if the blank option is given. This can be true to
165
162
  # allow an empty string or to a string substitute for the nil value.
166
163
  def ip_address(blank = false)
167
-
168
- # IP address regexp copied from Resolv::IPv4 and Resolv::IPv6,
164
+ # IP address regexp copied from Resolv::IPv4 and Resolv::IPv6,
169
165
  # but adjusted to work for the purpose of request-log-analyzer.
170
166
  ipv4_regexp = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
171
167
  ipv6_regex_8_hex = /(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}/
@@ -176,19 +172,19 @@ module RequestLogAnalyzer::FileFormat
176
172
 
177
173
  add_blank_option(Regexp.union(ipv4_regexp, ipv6_regexp), blank)
178
174
  end
179
-
175
+
180
176
  def anchored(regexp)
181
177
  /^#{regexp}$/
182
178
  end
183
-
179
+
184
180
  protected
185
-
186
- # Allow the field to be blank if this option is given. This can be true to
181
+
182
+ # Allow the field to be blank if this option is given. This can be true to
187
183
  # allow an empty string or a string alternative for the nil value.
188
184
  def add_blank_option(regexp, blank)
189
185
  case blank
190
- when String; Regexp.union(regexp, Regexp.new(Regexp.quote(blank)))
191
- when true; Regexp.union(regexp, //)
186
+ when String then Regexp.union(regexp, Regexp.new(Regexp.quote(blank)))
187
+ when true then Regexp.union(regexp, //)
192
188
  else regexp
193
189
  end
194
190
  end
@@ -200,6 +196,8 @@ module RequestLogAnalyzer::FileFormat
200
196
  # A subclass of this class is instantiated when request-log-analyzer is started and this instance
201
197
  # is shared with all components of the application so they can act on the specifics of the format
202
198
  class Base
199
+ extend RequestLogAnalyzer::ClassLevelInheritableAttributes
200
+ inheritable_attributes :line_definer, :report_definer
203
201
 
204
202
  attr_reader :line_definitions, :report_trackers
205
203
 
@@ -213,18 +211,18 @@ module RequestLogAnalyzer::FileFormat
213
211
  end
214
212
 
215
213
  # Specifies multiple line definitions at once using a block
216
- def self.format_definition(&block)
214
+ def self.format_definition(&_block)
217
215
  if block_given?
218
- yield self.line_definer
216
+ yield line_definer
219
217
  else
220
- return self.line_definer
218
+ return line_definer
221
219
  end
222
220
  end
223
221
 
224
222
  # Specifies the summary report using a block.
225
- def self.report(mode = :append, &block)
226
- self.report_definer.reset! if mode == :overwrite
227
- yield(self.report_definer)
223
+ def self.report(mode = :append, &_block)
224
+ report_definer.reset! if mode == :overwrite
225
+ yield(report_definer)
228
226
  end
229
227
 
230
228
  # Setup the default line definer.
@@ -244,9 +242,9 @@ module RequestLogAnalyzer::FileFormat
244
242
  # Instantiation
245
243
  ####################################################################################
246
244
 
247
- def self.create(*args)
245
+ def self.create(*_args)
248
246
  # Ignore arguments
249
- return self.new(line_definer.line_definitions, report_definer.trackers)
247
+ new(line_definer.line_definitions, report_definer.trackers)
250
248
  end
251
249
 
252
250
  def initialize(line_definitions = {}, report_trackers = [])
@@ -271,16 +269,15 @@ module RequestLogAnalyzer::FileFormat
271
269
  def well_formed?
272
270
  valid_line_definitions? && valid_request_class?
273
271
  end
274
-
272
+
275
273
  alias_method :valid?, :well_formed?
276
-
277
274
 
278
275
  # Checks whether the line definitions form a valid language.
279
- # A file format should have at least a header and a footer line type
276
+ # A file format should have at least a header and a footer line type
280
277
  def valid_line_definitions?
281
278
  line_definitions.any? { |(_, ld)| ld.header } && line_definitions.any? { |(_, ld)| ld.footer }
282
279
  end
283
-
280
+
284
281
  # Checks whether the request class inherits from the base Request class.
285
282
  def valid_request_class?
286
283
  request_class.ancestors.include?(RequestLogAnalyzer::Request)
@@ -293,24 +290,24 @@ module RequestLogAnalyzer::FileFormat
293
290
 
294
291
  # Function that a file format con implement to monkey patch the environment.
295
292
  # * <tt>controller</tt> The environment is provided as a controller instance
296
- def setup_environment(controller)
293
+ def setup_environment(_controller)
297
294
  end
298
295
 
299
296
  # Parses a line by trying to parse it using every line definition in this file format
300
297
  def parse_line(line, &warning_handler)
301
- self.line_definitions.each do |lt, definition|
298
+ line_definitions.each do |_lt, definition|
302
299
  match = definition.matches(line, &warning_handler)
303
300
  return match if match
304
301
  end
305
302
 
306
- return nil
303
+ nil
307
304
  end
308
-
305
+
309
306
  # Returns the max line length for this file format if any.
310
307
  def max_line_length
311
308
  self.class.const_get(MAX_LINE_LENGTH) if self.class.const_defined?(:MAX_LINE_LENGTH)
312
309
  end
313
-
310
+
314
311
  def line_divider
315
312
  self.class.const_get(LINE_DIVIDER) if self.class.const_defined?(:LINE_DIVIDER)
316
313
  end