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.
- data/LICENSE +3 -3
- data/README.rdoc +1 -1
- data/bin/request-log-analyzer +17 -14
- data/lib/cli/command_line_arguments.rb +51 -51
- data/lib/cli/database_console.rb +3 -3
- data/lib/cli/database_console_init.rb +2 -2
- data/lib/cli/progressbar.rb +10 -10
- data/lib/cli/tools.rb +3 -3
- data/lib/request_log_analyzer.rb +4 -4
- data/lib/request_log_analyzer/aggregator.rb +10 -10
- data/lib/request_log_analyzer/aggregator/database_inserter.rb +9 -9
- data/lib/request_log_analyzer/aggregator/echo.rb +14 -9
- data/lib/request_log_analyzer/aggregator/summarizer.rb +26 -26
- data/lib/request_log_analyzer/controller.rb +153 -69
- data/lib/request_log_analyzer/database.rb +13 -13
- data/lib/request_log_analyzer/database/base.rb +17 -17
- data/lib/request_log_analyzer/database/connection.rb +3 -3
- data/lib/request_log_analyzer/database/request.rb +2 -2
- data/lib/request_log_analyzer/database/source.rb +1 -1
- data/lib/request_log_analyzer/file_format.rb +15 -15
- data/lib/request_log_analyzer/file_format/amazon_s3.rb +16 -16
- data/lib/request_log_analyzer/file_format/apache.rb +20 -19
- data/lib/request_log_analyzer/file_format/merb.rb +12 -12
- data/lib/request_log_analyzer/file_format/rack.rb +4 -4
- data/lib/request_log_analyzer/file_format/rails.rb +146 -70
- data/lib/request_log_analyzer/file_format/rails_development.rb +4 -49
- data/lib/request_log_analyzer/filter.rb +6 -6
- data/lib/request_log_analyzer/filter/anonymize.rb +6 -6
- data/lib/request_log_analyzer/filter/field.rb +9 -9
- data/lib/request_log_analyzer/filter/timespan.rb +12 -10
- data/lib/request_log_analyzer/line_definition.rb +15 -14
- data/lib/request_log_analyzer/log_processor.rb +22 -22
- data/lib/request_log_analyzer/mailer.rb +15 -9
- data/lib/request_log_analyzer/output.rb +53 -12
- data/lib/request_log_analyzer/output/fixed_width.rb +40 -41
- data/lib/request_log_analyzer/output/html.rb +20 -20
- data/lib/request_log_analyzer/request.rb +35 -36
- data/lib/request_log_analyzer/source.rb +7 -7
- data/lib/request_log_analyzer/source/database_loader.rb +7 -7
- data/lib/request_log_analyzer/source/log_parser.rb +48 -43
- data/lib/request_log_analyzer/tracker.rb +128 -14
- data/lib/request_log_analyzer/tracker/duration.rb +39 -132
- data/lib/request_log_analyzer/tracker/frequency.rb +31 -32
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +20 -19
- data/lib/request_log_analyzer/tracker/timespan.rb +17 -17
- data/lib/request_log_analyzer/tracker/traffic.rb +36 -116
- data/request-log-analyzer.gemspec +19 -15
- data/spec/fixtures/rails_22.log +1 -1
- data/spec/integration/command_line_usage_spec.rb +1 -1
- data/spec/lib/helpers.rb +7 -7
- data/spec/lib/macros.rb +3 -3
- data/spec/lib/matchers.rb +41 -27
- data/spec/lib/mocks.rb +15 -14
- data/spec/lib/testing_format.rb +9 -9
- data/spec/spec_helper.rb +6 -6
- data/spec/unit/aggregator/database_inserter_spec.rb +13 -13
- data/spec/unit/aggregator/summarizer_spec.rb +4 -4
- data/spec/unit/controller/controller_spec.rb +2 -2
- data/spec/unit/controller/log_processor_spec.rb +1 -1
- data/spec/unit/database/base_class_spec.rb +19 -19
- data/spec/unit/database/connection_spec.rb +3 -3
- data/spec/unit/database/database_spec.rb +25 -25
- data/spec/unit/file_format/amazon_s3_format_spec.rb +5 -5
- data/spec/unit/file_format/apache_format_spec.rb +13 -13
- data/spec/unit/file_format/file_format_api_spec.rb +13 -13
- data/spec/unit/file_format/line_definition_spec.rb +24 -17
- data/spec/unit/file_format/merb_format_spec.rb +41 -45
- data/spec/unit/file_format/rails_format_spec.rb +157 -117
- data/spec/unit/filter/anonymize_filter_spec.rb +2 -2
- data/spec/unit/filter/field_filter_spec.rb +13 -13
- data/spec/unit/filter/filter_spec.rb +1 -1
- data/spec/unit/filter/timespan_filter_spec.rb +15 -15
- data/spec/unit/mailer_spec.rb +30 -0
- data/spec/unit/{source/request_spec.rb → request_spec.rb} +30 -30
- data/spec/unit/source/log_parser_spec.rb +27 -27
- data/spec/unit/tracker/duration_tracker_spec.rb +115 -78
- data/spec/unit/tracker/frequency_tracker_spec.rb +74 -63
- data/spec/unit/tracker/hourly_spread_spec.rb +28 -20
- data/spec/unit/tracker/timespan_tracker_spec.rb +25 -13
- data/spec/unit/tracker/tracker_api_spec.rb +13 -13
- data/spec/unit/tracker/traffic_tracker_spec.rb +81 -79
- data/tasks/github-gem.rake +125 -75
- data/tasks/request_log_analyzer.rake +2 -2
- 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)] =
|
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
|