request-log-analyzer 1.3.7 → 1.4.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 (84) hide show
  1. data/LICENSE +3 -3
  2. data/README.rdoc +1 -1
  3. data/bin/request-log-analyzer +17 -14
  4. data/lib/cli/command_line_arguments.rb +51 -51
  5. data/lib/cli/database_console.rb +3 -3
  6. data/lib/cli/database_console_init.rb +2 -2
  7. data/lib/cli/progressbar.rb +10 -10
  8. data/lib/cli/tools.rb +3 -3
  9. data/lib/request_log_analyzer.rb +4 -4
  10. data/lib/request_log_analyzer/aggregator.rb +10 -10
  11. data/lib/request_log_analyzer/aggregator/database_inserter.rb +9 -9
  12. data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
  13. data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
  14. data/lib/request_log_analyzer/controller.rb +153 -69
  15. data/lib/request_log_analyzer/database.rb +13 -13
  16. data/lib/request_log_analyzer/database/base.rb +17 -17
  17. data/lib/request_log_analyzer/database/connection.rb +3 -3
  18. data/lib/request_log_analyzer/database/request.rb +2 -2
  19. data/lib/request_log_analyzer/database/source.rb +1 -1
  20. data/lib/request_log_analyzer/file_format.rb +15 -15
  21. data/lib/request_log_analyzer/file_format/amazon_s3.rb +16 -16
  22. data/lib/request_log_analyzer/file_format/apache.rb +20 -19
  23. data/lib/request_log_analyzer/file_format/merb.rb +12 -12
  24. data/lib/request_log_analyzer/file_format/rack.rb +4 -4
  25. data/lib/request_log_analyzer/file_format/rails.rb +146 -70
  26. data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
  27. data/lib/request_log_analyzer/filter.rb +6 -6
  28. data/lib/request_log_analyzer/filter/anonymize.rb +6 -6
  29. data/lib/request_log_analyzer/filter/field.rb +9 -9
  30. data/lib/request_log_analyzer/filter/timespan.rb +12 -10
  31. data/lib/request_log_analyzer/line_definition.rb +15 -14
  32. data/lib/request_log_analyzer/log_processor.rb +22 -22
  33. data/lib/request_log_analyzer/mailer.rb +15 -9
  34. data/lib/request_log_analyzer/output.rb +53 -12
  35. data/lib/request_log_analyzer/output/fixed_width.rb +40 -41
  36. data/lib/request_log_analyzer/output/html.rb +20 -20
  37. data/lib/request_log_analyzer/request.rb +35 -36
  38. data/lib/request_log_analyzer/source.rb +7 -7
  39. data/lib/request_log_analyzer/source/database_loader.rb +7 -7
  40. data/lib/request_log_analyzer/source/log_parser.rb +48 -43
  41. data/lib/request_log_analyzer/tracker.rb +128 -14
  42. data/lib/request_log_analyzer/tracker/duration.rb +39 -132
  43. data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
  44. data/lib/request_log_analyzer/tracker/hourly_spread.rb +20 -19
  45. data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
  46. data/lib/request_log_analyzer/tracker/traffic.rb +36 -116
  47. data/request-log-analyzer.gemspec +19 -15
  48. data/spec/fixtures/rails_22.log +1 -1
  49. data/spec/integration/command_line_usage_spec.rb +1 -1
  50. data/spec/lib/helpers.rb +7 -7
  51. data/spec/lib/macros.rb +3 -3
  52. data/spec/lib/matchers.rb +41 -27
  53. data/spec/lib/mocks.rb +15 -14
  54. data/spec/lib/testing_format.rb +9 -9
  55. data/spec/spec_helper.rb +6 -6
  56. data/spec/unit/aggregator/database_inserter_spec.rb +13 -13
  57. data/spec/unit/aggregator/summarizer_spec.rb +4 -4
  58. data/spec/unit/controller/controller_spec.rb +2 -2
  59. data/spec/unit/controller/log_processor_spec.rb +1 -1
  60. data/spec/unit/database/base_class_spec.rb +19 -19
  61. data/spec/unit/database/connection_spec.rb +3 -3
  62. data/spec/unit/database/database_spec.rb +25 -25
  63. data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
  64. data/spec/unit/file_format/apache_format_spec.rb +13 -13
  65. data/spec/unit/file_format/file_format_api_spec.rb +13 -13
  66. data/spec/unit/file_format/line_definition_spec.rb +24 -17
  67. data/spec/unit/file_format/merb_format_spec.rb +41 -45
  68. data/spec/unit/file_format/rails_format_spec.rb +157 -117
  69. data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
  70. data/spec/unit/filter/field_filter_spec.rb +13 -13
  71. data/spec/unit/filter/filter_spec.rb +1 -1
  72. data/spec/unit/filter/timespan_filter_spec.rb +15 -15
  73. data/spec/unit/mailer_spec.rb +30 -0
  74. data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
  75. data/spec/unit/source/log_parser_spec.rb +27 -27
  76. data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
  77. data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
  78. data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
  79. data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
  80. data/spec/unit/tracker/tracker_api_spec.rb +13 -13
  81. data/spec/unit/tracker/traffic_tracker_spec.rb +81 -79
  82. data/tasks/github-gem.rake +125 -75
  83. data/tasks/request_log_analyzer.rake +2 -2
  84. metadata +8 -6
@@ -1,23 +1,23 @@
1
1
  # coding: utf-8
2
2
  module RequestLogAnalyzer::Output
3
-
3
+
4
4
  # Fixed Width output class.
5
5
  # Outputs a fixed width ASCII or UF8 report.
6
6
  class FixedWidth < Base
7
-
7
+
8
8
  # Mixin module. Will disable any colorizing.
9
9
  module Monochrome
10
10
  def colorize(text, *options)
11
11
  text
12
12
  end
13
13
  end
14
-
14
+
15
15
  # Colorize module
16
16
  module Color
17
-
17
+
18
18
  STYLES = { :normal => 0, :bold => 1, :underscore => 4, :blink => 5, :inverse => 7, :concealed => 8 }
19
19
  COLORS = { :black => 0, :blue => 4, :green => 2, :cyan => 6, :red => 1, :purple => 5, :brown => 3, :white => 7 }
20
-
20
+
21
21
  # Colorize text
22
22
  # <tt>text</tt> The text to colorize
23
23
  # Options
@@ -25,18 +25,18 @@ module RequestLogAnalyzer::Output
25
25
  # * <tt>:color</tt> The foreground color to paint. Defined in Color::COLORS
26
26
  # * <tt>:on</tt> Alias for :background
27
27
  # * <tt>:style</tt> Font style, defined in Color::STYLES
28
- #
28
+ #
29
29
  # Returns ASCII colored string
30
30
  def colorize(text, *options)
31
-
31
+
32
32
  font_style = ''
33
33
  foreground_color = '0'
34
34
  background_color = ''
35
-
35
+
36
36
  options.each do |option|
37
37
  if option.kind_of?(Symbol)
38
38
  foreground_color = "3#{COLORS[option]}" if COLORS.include?(option)
39
- font_style = "#{STYLES[option]};" if STYLES.include?(option)
39
+ font_style = "#{STYLES[option]};" if STYLES.include?(option)
40
40
  elsif option.kind_of?(Hash)
41
41
  options.each do |key, value|
42
42
  case key
@@ -50,16 +50,16 @@ module RequestLogAnalyzer::Output
50
50
  end
51
51
  return "\e[#{background_color}#{font_style}#{foreground_color}m#{text}\e[0m"
52
52
  end
53
-
53
+
54
54
  end
55
-
55
+
56
56
  attr_reader :characters
57
-
57
+
58
58
  CHARACTERS = {
59
59
  :ascii => { :horizontal_line => '-', :vertical_line => '|', :block => '=' },
60
60
  :utf => { :horizontal_line => '━', :vertical_line => '┃', :block => '░' }
61
61
  }
62
-
62
+
63
63
  # Initialize a report
64
64
  # <tt>io</tt> iO Object (file, STDOUT, etc.)
65
65
  # <tt>options</tt>
@@ -71,25 +71,25 @@ module RequestLogAnalyzer::Output
71
71
  @options[:width] ||= 80
72
72
  @options[:characters] ||= :utf
73
73
  @characters = CHARACTERS[@options[:characters]]
74
-
74
+
75
75
  color_module = @options[:color] ? Color : Monochrome
76
- (class << self; self; end).send(:include, color_module)
76
+ (class << self; self; end).send(:include, color_module)
77
77
  end
78
-
78
+
79
79
  # Write a string to the output object.
80
80
  # <tt>str</tt> The string to write.
81
81
  def print(str)
82
82
  @io << str
83
83
  end
84
-
84
+
85
85
  alias :<< :print
86
-
86
+
87
87
  # Write a string to the output object with a newline at the end.
88
88
  # <tt>str</tt> The string to write.
89
89
  def puts(str = '')
90
90
  @io << str << "\n"
91
91
  end
92
-
92
+
93
93
  # Write the title of a report
94
94
  # <tt>title</tt> The title to write
95
95
  def title(title)
@@ -97,9 +97,9 @@ module RequestLogAnalyzer::Output
97
97
  puts colorize(title, :bold, :white)
98
98
  line(:green)
99
99
  end
100
-
100
+
101
101
  # Write a line
102
- def line(*font)
102
+ def line(*font)
103
103
  puts colorize(characters[:horizontal_line] * @options[:width], *font)
104
104
  end
105
105
 
@@ -113,7 +113,7 @@ module RequestLogAnalyzer::Output
113
113
  "#{text} (#{colorize(url, :blue, :bold)})"
114
114
  end
115
115
  end
116
-
116
+
117
117
  # Generate a header for a report
118
118
  def header
119
119
  if io.kind_of?(File)
@@ -123,7 +123,7 @@ module RequestLogAnalyzer::Output
123
123
  puts "Website: #{link('http://github.com/wvanbergen/request-log-analyzer')}"
124
124
  end
125
125
  end
126
-
126
+
127
127
  # Generate a footer for a report
128
128
  def footer
129
129
  puts
@@ -132,12 +132,12 @@ module RequestLogAnalyzer::Output
132
132
  line(:green)
133
133
  puts "Thanks for using #{colorize('request-log-analyzer', :white, :bold)}!"
134
134
  end
135
-
135
+
136
136
  # Generate a report table and push it into the output object.
137
137
  # <tt>*colums<tt> Columns hash
138
138
  # <tt>&block</tt>: A block yeilding the rows.
139
139
  def table(*columns, &block)
140
-
140
+
141
141
  rows = Array.new
142
142
  yield(rows)
143
143
 
@@ -147,7 +147,7 @@ module RequestLogAnalyzer::Output
147
147
  result.each_with_index { |length, index| result[index] = ([length, lengths[index]].max rescue length) }
148
148
  end
149
149
  columns.each_with_index { |col, index| col[:actual_width] ||= max_cell_widths[index] }
150
-
150
+
151
151
  # determine actual column width
152
152
  column_widths = columns.map do |column|
153
153
  if column[:width] == :rest
@@ -162,29 +162,28 @@ module RequestLogAnalyzer::Output
162
162
  column[:actual_width]
163
163
  end
164
164
  end
165
-
165
+
166
166
  if column_widths.include?(nil)
167
167
  fill_column = columns[column_widths.index(nil)]
168
168
  width_left = options[:width] - ((columns.length - 1) * (style[:cell_separator] ? 3 : 1)) - column_widths.compact.inject(0) { |sum, col| sum + col}
169
- column_widths[column_widths.index(nil)] = case fill_column[:type]
170
- when :ratio; width_left # max out
171
- else; [width_left, fill_column[:actual_width]].min
172
- end
169
+ column_widths[column_widths.index(nil)] = width_left
173
170
  end
174
-
171
+
172
+ line(:green) if @style[:top_line]
173
+
175
174
  # Print table header
176
175
  if table_has_header?(columns)
177
176
  column_titles = []
178
177
  columns.each_with_index do |column, index|
179
- width = column_widths[index]
178
+ width = column_widths[index]
180
179
  alignment = (column[:align] == :right ? '' : '-')
181
180
  column_titles.push(colorize("%#{alignment}#{width}s" % column[:title].to_s[0...width], :bold))
182
181
  end
183
-
182
+
184
183
  puts column_titles.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
185
184
  line(:green)
186
185
  end
187
-
186
+
188
187
  # Print the rows
189
188
  rows.each do |row|
190
189
  row_values = []
@@ -195,12 +194,12 @@ module RequestLogAnalyzer::Output
195
194
  if width > 4
196
195
  if column[:treshold] && column[:treshold] < row[index].to_f
197
196
  bar = ''
198
- bar << characters[:block] * (width.to_f * column[:treshold]).round
199
- bar << colorize(characters[:block] * (width.to_f * (row[index].to_f - column[:treshold])).round, :red)
200
- row_values.push(bar)
197
+ bar << characters[:block] * (width.to_f * column[:treshold]).round
198
+ bar << colorize(characters[:block] * (width.to_f * (row[index].to_f - column[:treshold])).round, :red)
199
+ row_values.push(bar)
201
200
  else
202
201
  # Create a bar by combining block characters
203
- row_values.push(characters[:block] * (width.to_f * row[index].to_f).round)
202
+ row_values.push(characters[:block] * (width.to_f * row[index].to_f).round)
204
203
  end
205
204
  else
206
205
  # Too few characters for a ratio bar. Display nothing
@@ -213,9 +212,9 @@ module RequestLogAnalyzer::Output
213
212
  row_values.push(cell_value)
214
213
  end
215
214
  end
216
- puts row_values.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
215
+ puts row_values.join(style[:cell_separator] ? " #{characters[:vertical_line]} " : ' ')
217
216
  end
218
217
  end
219
-
218
+
220
219
  end
221
220
  end
@@ -1,12 +1,12 @@
1
1
  module RequestLogAnalyzer::Output
2
-
2
+
3
3
  # HTML Output class. Generated a HTML-formatted report, including CSS.
4
4
  class HTML < Base
5
-
5
+
6
6
  # def initialize(io, options = {})
7
7
  # super(io, options)
8
8
  # end
9
-
9
+
10
10
  # Print a string to the io object.
11
11
  def print(str)
12
12
  @io << str
@@ -26,10 +26,10 @@ module RequestLogAnalyzer::Output
26
26
 
27
27
  # Render a single line
28
28
  # <tt>*font</tt> The font.
29
- def line(*font)
29
+ def line(*font)
30
30
  @io.puts(tag(:hr))
31
31
  end
32
-
32
+
33
33
  # Write a link
34
34
  # <tt>text</tt> The text in the link
35
35
  # <tt>url</tt> The url to link to.
@@ -44,29 +44,29 @@ module RequestLogAnalyzer::Output
44
44
  def table(*columns, &block)
45
45
  rows = Array.new
46
46
  yield(rows)
47
-
47
+
48
48
  @io << tag(:table, {:id => 'mytable', :cellspacing => 0}) do |content|
49
49
  if table_has_header?(columns)
50
50
  content << tag(:tr) do
51
51
  columns.map { |col| tag(:th, col[:title]) }.join("\n")
52
52
  end
53
53
  end
54
-
54
+
55
55
  odd = false
56
56
  rows.each do |row|
57
57
  odd = !odd
58
58
  content << tag(:tr) do
59
59
  if odd
60
- row.map { |cell| tag(:td, cell, :class => 'alt') }.join("\n")
60
+ row.map { |cell| tag(:td, cell, :class => 'alt') }.join("\n")
61
61
  else
62
- row.map { |cell| tag(:td, cell) }.join("\n")
62
+ row.map { |cell| tag(:td, cell) }.join("\n")
63
63
  end
64
64
  end
65
65
  end
66
66
  end
67
-
67
+
68
68
  end
69
-
69
+
70
70
  # Genrate HTML header and associated stylesheet
71
71
  def header
72
72
  @io << "<html>"
@@ -85,13 +85,13 @@ module RequestLogAnalyzer::Output
85
85
  a {
86
86
  color: #c75f3e;
87
87
  }
88
-
88
+
89
89
  .color_bar {
90
90
  border: 1px solid;
91
91
  height:10px;
92
92
  background: #CAE8EA;
93
93
  }
94
-
94
+
95
95
  #mytable {
96
96
  width: 700px;
97
97
  padding: 0;
@@ -101,7 +101,7 @@ module RequestLogAnalyzer::Output
101
101
 
102
102
  caption {
103
103
  padding: 0 0 5px 0;
104
- width: 700px;
104
+ width: 700px;
105
105
  font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
106
106
  text-align: right;
107
107
  }
@@ -138,7 +138,7 @@ module RequestLogAnalyzer::Output
138
138
  @io << tag(:h1, 'Request-log-analyzer summary report')
139
139
  @io << tag(:p, "Version #{RequestLogAnalyzer::VERSION} - written by Willem van Bergen and Bart ten Brinke")
140
140
  end
141
-
141
+
142
142
  # Generate a footer for a report
143
143
  def footer
144
144
  @io << tag(:hr) << tag(:h2, 'Thanks for using request-log-analyzer')
@@ -146,9 +146,9 @@ module RequestLogAnalyzer::Output
146
146
  @io << tag(:p, 'If you need an expert who can analyze your application, mail to ' + link('contact@railsdoctors.com', 'mailto:contact@railsdoctors.com') + ' or visit us at ' + link('http://railsdoctors.com', 'http://railsdoctors.com') + '.')
147
147
  @io << "</body></html>\n"
148
148
  end
149
-
150
- protected
151
-
149
+
150
+ protected
151
+
152
152
  # HTML tag writer helper
153
153
  # <tt>tag</tt> The tag to generate
154
154
  # <tt>content</tt> The content inside the tag
@@ -158,7 +158,7 @@ module RequestLogAnalyzer::Output
158
158
  attributes = content.nil? ? '' : ' ' + content.map { |(key, value)| "#{key}=\"#{value}\"" }.join(' ')
159
159
  content_string = ''
160
160
  content = yield(content_string)
161
- content = content_string unless content_string.empty?
161
+ content = content_string unless content_string.empty?
162
162
  "<#{tag}#{attributes}>#{content}</#{tag}>"
163
163
  else
164
164
  attributes = attributes.nil? ? '' : ' ' + attributes.map { |(key, value)| "#{key}=\"#{value}\"" }.join(' ')
@@ -172,6 +172,6 @@ module RequestLogAnalyzer::Output
172
172
  end
173
173
  end
174
174
  end
175
- end
175
+ end
176
176
  end
177
177
  end
@@ -1,14 +1,14 @@
1
1
  module RequestLogAnalyzer
2
-
3
- # The Request class represents a parsed request from the log file.
2
+
3
+ # The Request class represents a parsed request from the log file.
4
4
  # Instances are created by the LogParser and are passed to the different aggregators, so they
5
- # can do their aggregating work.
5
+ # can do their aggregating work.
6
6
  #
7
7
  # This class provides several methods to access the data that was parsed from the log files.
8
8
  # Request#first(field_name) returns the first (only) value corresponding to the given field
9
9
  # Request#every(field_name) returns all values corresponding to the given field name as array.
10
10
  class Request
11
-
11
+
12
12
  module Converters
13
13
 
14
14
  # Default converter function, which converts the parsed strings to a native Ruby type
@@ -19,30 +19,29 @@ module RequestLogAnalyzer
19
19
  custom_converter_method = :"convert_#{capture_definition[:type]}"
20
20
  send(custom_converter_method, value, capture_definition)
21
21
  end
22
-
22
+
23
23
  def convert_string(value, capture_definition); value; end
24
- def convert_decimal(value, capture_definition); value.to_f; end
25
24
  def convert_float(value, capture_definition); value.to_f; end
26
25
  def convert_decimal(value, capture_definition); value.to_f; end
27
26
  def convert_int(value, capture_definition); value.to_i; end
28
27
  def convert_integer(value, capture_definition); value.to_i; end
29
28
  def convert_sym(value, capture_definition); value.to_sym; end
30
29
  def convert_symbol(value, capture_definition); value.to_sym; end
31
-
30
+
32
31
  # Converts :eval field, which should evaluate to a hash.
33
32
  def convert_eval(value, capture_definition)
34
- eval(value).inject({}) { |h, (k, v)| h[k.to_sym] = v; h}
33
+ eval(value).inject({}) { |h, (k, v)| h[k.to_sym] = v; h}
35
34
  rescue SyntaxError
36
35
  nil
37
36
  end
38
-
39
- # Slow default method to parse timestamps.
37
+
38
+ # Slow default method to parse timestamps.
40
39
  # Reimplement this function in a file format specific Request class
41
40
  # to improve the timestamp parsing speed.
42
41
  def convert_timestamp(value, capture_definition)
43
42
  DateTime.parse(value).strftime('%Y%m%d%H%M%S').to_i
44
43
  end
45
-
44
+
46
45
  # Converts traffic fields to (whole) bytes based on the given unit.
47
46
  def convert_traffic(value, capture_definition)
48
47
  case capture_definition[:unit]
@@ -56,7 +55,7 @@ module RequestLogAnalyzer
56
55
  else raise "Unknown traffic unit"
57
56
  end
58
57
  end
59
-
58
+
60
59
  # Convert duration fields to float, and make sure the values are in seconds.
61
60
  def convert_duration(value, capture_definition)
62
61
  case capture_definition[:unit]
@@ -72,15 +71,15 @@ module RequestLogAnalyzer
72
71
  include Converters
73
72
 
74
73
  attr_reader :lines, :attributes, :file_format
75
-
76
- # Initializes a new Request object.
74
+
75
+ # Initializes a new Request object.
77
76
  # It will apply the the provided FileFormat module to this instance.
78
77
  def initialize(file_format, attributes = {})
79
78
  @lines = []
80
79
  @attributes = attributes
81
80
  @file_format = file_format
82
81
  end
83
-
82
+
84
83
  # Creates a new request that was parsed from the log with the given FileFormat. The hashes
85
84
  # that are passed to this function are added as lines to this request.
86
85
  def self.create(file_format, *hashes)
@@ -88,7 +87,7 @@ module RequestLogAnalyzer
88
87
  hashes.flatten.each { |hash| request << hash }
89
88
  return request
90
89
  end
91
-
90
+
92
91
  # Adds another line to the request when it is parsed in the LogParser.
93
92
  #
94
93
  # The line should be provided as a hash with the attributes line_definition, :captures,
@@ -100,7 +99,7 @@ module RequestLogAnalyzer
100
99
  value_hash[:source] = parsed_line[:source]
101
100
  add_line_hash(value_hash)
102
101
  end
103
-
102
+
104
103
  # Adds another line to the request using a plain hash.
105
104
  #
106
105
  # The line should be provides as a hash of the fields parsed from the line.
@@ -108,67 +107,67 @@ module RequestLogAnalyzer
108
107
  @lines << value_hash
109
108
  @attributes = value_hash.merge(@attributes)
110
109
  end
111
-
110
+
112
111
  # Adds another line to the request. This method switches automatically between
113
112
  # the add_line_hash and add_parsed_line based on the keys of the provided hash.
114
113
  def <<(hash)
115
114
  hash[:line_definition] ? add_parsed_line(hash) : add_line_hash(hash)
116
115
  end
117
-
116
+
118
117
  # Checks whether the given line type was parsed from the log file for this request
119
118
  def has_line_type?(line_type)
120
119
  return true if @lines.length == 1 && @lines[0][:line_type] == line_type.to_sym
121
120
  @lines.detect { |l| l[:line_type] == line_type.to_sym }
122
121
  end
123
-
122
+
124
123
  alias :=~ :has_line_type?
125
-
124
+
126
125
  # Returns the value that was captured for the "field" of this request.
127
126
  # This function will return the first value that was captured if the field
128
127
  # was captured in multiple lines
129
128
  def first(field)
130
129
  @attributes[field]
131
130
  end
132
-
131
+
133
132
  alias :[] :first
134
-
133
+
135
134
  # Returns an array of all the "field" values that were captured for this request
136
135
  def every(field)
137
136
  @lines.inject([]) { |result, fields| result << fields[field] if fields.has_key?(field); result }
138
- end
139
-
140
- # Returns true if this request does not yet contain any parsed lines. This should only occur
137
+ end
138
+
139
+ # Returns true if this request does not yet contain any parsed lines. This should only occur
141
140
  # during parsing. An empty request should never be sent to the aggregators
142
141
  def empty?
143
142
  @lines.length == 0
144
143
  end
145
-
144
+
146
145
  # Checks whether this request is completed. A completed request contains both a parsed header
147
- # line and a parsed footer line. Not that calling this function in single line mode will always
146
+ # line and a parsed footer line. Not that calling this function in single line mode will always
148
147
  # return false.
149
148
  def completed?
150
149
  header_found, footer_found = false, false
151
- @lines.each do |line|
150
+ @lines.each do |line|
152
151
  line_def = file_format.line_definitions[line[:line_type]]
153
152
  header_found = true if line_def.header
154
- footer_found = true if line_def.footer
153
+ footer_found = true if line_def.footer
155
154
  end
156
- header_found && footer_found
155
+ header_found && footer_found
157
156
  end
158
-
157
+
159
158
  # This function is called before a Requests is yielded.
160
159
  def validate
161
160
  end
162
-
163
- # Returns the first timestamp encountered in a request.
161
+
162
+ # Returns the first timestamp encountered in a request.
164
163
  def timestamp
165
164
  first(:timestamp)
166
165
  end
167
-
166
+
168
167
  def first_lineno
169
168
  @lines.map { |line| line[:lineno] }.reject { |v| v.nil? }.min
170
169
  end
171
-
170
+
172
171
  def last_lineno
173
172
  @lines.map { |line| line[:lineno] }.reject { |v| v.nil? }.max
174
173
  end