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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/bin/console +17 -0
- data/lib/cli/command_line_arguments.rb +29 -36
- data/lib/cli/database_console.rb +1 -3
- data/lib/cli/database_console_init.rb +11 -11
- data/lib/cli/progressbar.rb +30 -32
- data/lib/cli/tools.rb +20 -23
- data/lib/request_log_analyzer.rb +8 -8
- data/lib/request_log_analyzer/aggregator.rb +4 -7
- data/lib/request_log_analyzer/aggregator/database_inserter.rb +10 -13
- data/lib/request_log_analyzer/aggregator/echo.rb +5 -7
- data/lib/request_log_analyzer/aggregator/summarizer.rb +15 -18
- data/lib/request_log_analyzer/class_level_inheritable_attributes.rb +23 -0
- data/lib/request_log_analyzer/controller.rb +36 -42
- data/lib/request_log_analyzer/database.rb +4 -6
- data/lib/request_log_analyzer/database/base.rb +39 -41
- data/lib/request_log_analyzer/database/connection.rb +8 -10
- data/lib/request_log_analyzer/database/request.rb +1 -3
- data/lib/request_log_analyzer/database/source.rb +0 -2
- data/lib/request_log_analyzer/database/warning.rb +4 -6
- data/lib/request_log_analyzer/file_format.rb +46 -49
- data/lib/request_log_analyzer/file_format/amazon_s3.rb +15 -19
- data/lib/request_log_analyzer/file_format/apache.rb +42 -45
- data/lib/request_log_analyzer/file_format/delayed_job.rb +13 -15
- data/lib/request_log_analyzer/file_format/delayed_job2.rb +9 -11
- data/lib/request_log_analyzer/file_format/delayed_job21.rb +9 -11
- data/lib/request_log_analyzer/file_format/delayed_job3.rb +5 -8
- data/lib/request_log_analyzer/file_format/delayed_job4.rb +5 -8
- data/lib/request_log_analyzer/file_format/haproxy.rb +44 -48
- data/lib/request_log_analyzer/file_format/merb.rb +13 -17
- data/lib/request_log_analyzer/file_format/mysql.rb +21 -25
- data/lib/request_log_analyzer/file_format/nginx.rb +0 -2
- data/lib/request_log_analyzer/file_format/oink.rb +30 -31
- data/lib/request_log_analyzer/file_format/postgresql.rb +11 -15
- data/lib/request_log_analyzer/file_format/rack.rb +0 -2
- data/lib/request_log_analyzer/file_format/rails.rb +100 -104
- data/lib/request_log_analyzer/file_format/rails3.rb +19 -23
- data/lib/request_log_analyzer/file_format/rails_development.rb +0 -1
- data/lib/request_log_analyzer/file_format/w3c.rb +16 -18
- data/lib/request_log_analyzer/filter.rb +0 -2
- data/lib/request_log_analyzer/filter/anonymize.rb +4 -7
- data/lib/request_log_analyzer/filter/field.rb +3 -6
- data/lib/request_log_analyzer/filter/timespan.rb +2 -6
- data/lib/request_log_analyzer/line_definition.rb +16 -19
- data/lib/request_log_analyzer/log_processor.rb +10 -14
- data/lib/request_log_analyzer/mailer.rb +9 -12
- data/lib/request_log_analyzer/output.rb +12 -14
- data/lib/request_log_analyzer/output/fixed_width.rb +21 -28
- data/lib/request_log_analyzer/output/html.rb +11 -14
- data/lib/request_log_analyzer/request.rb +53 -33
- data/lib/request_log_analyzer/source.rb +2 -5
- data/lib/request_log_analyzer/source/log_parser.rb +9 -16
- data/lib/request_log_analyzer/tracker.rb +10 -12
- data/lib/request_log_analyzer/tracker/duration.rb +4 -6
- data/lib/request_log_analyzer/tracker/frequency.rb +9 -11
- data/lib/request_log_analyzer/tracker/hourly_spread.rb +8 -11
- data/lib/request_log_analyzer/tracker/numeric_value.rb +40 -44
- data/lib/request_log_analyzer/tracker/timespan.rb +5 -8
- data/lib/request_log_analyzer/tracker/traffic.rb +8 -10
- data/lib/request_log_analyzer/version.rb +1 -1
- data/request-log-analyzer.gemspec +6 -6
- data/spec/integration/command_line_usage_spec.rb +33 -33
- data/spec/integration/mailer_spec.rb +181 -185
- data/spec/integration/munin_plugins_rails_spec.rb +20 -20
- data/spec/integration/scout_spec.rb +40 -41
- data/spec/lib/helpers.rb +8 -9
- data/spec/lib/macros.rb +2 -4
- data/spec/lib/matchers.rb +20 -25
- data/spec/lib/mocks.rb +10 -11
- data/spec/lib/testing_format.rb +8 -10
- data/spec/spec_helper.rb +5 -1
- data/spec/unit/aggregator/database_inserter_spec.rb +23 -23
- data/spec/unit/aggregator/summarizer_spec.rb +7 -7
- data/spec/unit/controller/controller_spec.rb +14 -14
- data/spec/unit/controller/log_processor_spec.rb +3 -3
- data/spec/unit/database/base_class_spec.rb +36 -37
- data/spec/unit/database/connection_spec.rb +10 -10
- data/spec/unit/database/database_spec.rb +11 -11
- data/spec/unit/file_format/amazon_s3_format_spec.rb +66 -62
- data/spec/unit/file_format/apache_format_spec.rb +57 -52
- data/spec/unit/file_format/common_regular_expressions_spec.rb +18 -21
- data/spec/unit/file_format/delayed_job21_format_spec.rb +22 -16
- data/spec/unit/file_format/delayed_job2_format_spec.rb +22 -16
- data/spec/unit/file_format/delayed_job3_format_spec.rb +14 -10
- data/spec/unit/file_format/delayed_job4_format_spec.rb +14 -10
- data/spec/unit/file_format/delayed_job_format_spec.rb +12 -12
- data/spec/unit/file_format/file_format_api_spec.rb +19 -19
- data/spec/unit/file_format/format_autodetection_spec.rb +7 -7
- data/spec/unit/file_format/haproxy_format_spec.rb +53 -49
- data/spec/unit/file_format/inheritance_spec.rb +13 -0
- data/spec/unit/file_format/line_definition_spec.rb +35 -33
- data/spec/unit/file_format/merb_format_spec.rb +13 -11
- data/spec/unit/file_format/mysql_format_spec.rb +24 -24
- data/spec/unit/file_format/oink_format_spec.rb +29 -29
- data/spec/unit/file_format/postgresql_format_spec.rb +9 -9
- data/spec/unit/file_format/rack_format_spec.rb +36 -31
- data/spec/unit/file_format/rails3_format_spec.rb +46 -46
- data/spec/unit/file_format/rails_format_spec.rb +52 -53
- data/spec/unit/file_format/w3c_format_spec.rb +27 -24
- data/spec/unit/filter/anonymize_filter_spec.rb +7 -7
- data/spec/unit/filter/field_filter_spec.rb +26 -26
- data/spec/unit/filter/filter_spec.rb +4 -4
- data/spec/unit/filter/timespan_filter_spec.rb +22 -22
- data/spec/unit/mailer_spec.rb +21 -21
- data/spec/unit/request_spec.rb +29 -29
- data/spec/unit/source/log_parser_spec.rb +5 -5
- data/spec/unit/tracker/duration_tracker_spec.rb +23 -23
- data/spec/unit/tracker/frequency_tracker_spec.rb +29 -30
- data/spec/unit/tracker/hourly_spread_spec.rb +35 -35
- data/spec/unit/tracker/numeric_value_tracker_spec.rb +71 -72
- data/spec/unit/tracker/timespan_tracker_spec.rb +31 -31
- data/spec/unit/tracker/tracker_api_spec.rb +43 -44
- data/spec/unit/tracker/traffic_tracker_spec.rb +7 -7
- metadata +38 -35
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
module RequestLogAnalyzer::FileFormat
|
|
2
|
-
|
|
3
2
|
class Haproxy < RequestLogAnalyzer::FileFormat::Base
|
|
4
|
-
|
|
5
3
|
extend CommonRegularExpressions
|
|
6
4
|
|
|
7
5
|
# substitute version specific parts of the haproxy entry regexp.
|
|
@@ -46,13 +44,13 @@ module RequestLogAnalyzer::FileFormat
|
|
|
46
44
|
line.capture(:frontend_name).as(:string)
|
|
47
45
|
line.capture(:backend_name).as(:string)
|
|
48
46
|
line.capture(:server_name).as(:string)
|
|
49
|
-
line.capture(:tq).as(:nillable_duration, :
|
|
50
|
-
line.capture(:tw).as(:nillable_duration, :
|
|
51
|
-
line.capture(:tc).as(:nillable_duration, :
|
|
52
|
-
line.capture(:tr).as(:nillable_duration, :
|
|
53
|
-
line.capture(:tt).as(:duration, :
|
|
47
|
+
line.capture(:tq).as(:nillable_duration, unit: :msec)
|
|
48
|
+
line.capture(:tw).as(:nillable_duration, unit: :msec)
|
|
49
|
+
line.capture(:tc).as(:nillable_duration, unit: :msec)
|
|
50
|
+
line.capture(:tr).as(:nillable_duration, unit: :msec)
|
|
51
|
+
line.capture(:tt).as(:duration, unit: :msec)
|
|
54
52
|
line.capture(:status_code).as(:integer)
|
|
55
|
-
line.capture(:bytes_read).as(:traffic, :
|
|
53
|
+
line.capture(:bytes_read).as(:traffic, unit: :byte)
|
|
56
54
|
line.capture(:captured_request_cookie).as(:nillable_string)
|
|
57
55
|
line.capture(:captured_response_cookie).as(:nillable_string)
|
|
58
56
|
line.capture(:termination_event_code).as(:nillable_string)
|
|
@@ -89,13 +87,13 @@ module RequestLogAnalyzer::FileFormat
|
|
|
89
87
|
line.capture(:timestamp).as(:timestamp)
|
|
90
88
|
line.capture(:frontend_name).as(:string)
|
|
91
89
|
line.capture(:server_name).as(:string)
|
|
92
|
-
line.capture(:tq).as(:nillable_duration, :
|
|
93
|
-
line.capture(:tw).as(:nillable_duration, :
|
|
94
|
-
line.capture(:tc).as(:nillable_duration, :
|
|
95
|
-
line.capture(:tr).as(:nillable_duration, :
|
|
96
|
-
line.capture(:tt).as(:duration, :
|
|
90
|
+
line.capture(:tq).as(:nillable_duration, unit: :msec)
|
|
91
|
+
line.capture(:tw).as(:nillable_duration, unit: :msec)
|
|
92
|
+
line.capture(:tc).as(:nillable_duration, unit: :msec)
|
|
93
|
+
line.capture(:tr).as(:nillable_duration, unit: :msec)
|
|
94
|
+
line.capture(:tt).as(:duration, unit: :msec)
|
|
97
95
|
line.capture(:status_code).as(:integer)
|
|
98
|
-
line.capture(:bytes_read).as(:traffic, :
|
|
96
|
+
line.capture(:bytes_read).as(:traffic, unit: :byte)
|
|
99
97
|
line.capture(:captured_request_cookie).as(:nillable_string)
|
|
100
98
|
line.capture(:captured_response_cookie).as(:nillable_string)
|
|
101
99
|
line.capture(:termination_event_code).as(:nillable_string)
|
|
@@ -130,12 +128,12 @@ module RequestLogAnalyzer::FileFormat
|
|
|
130
128
|
line.capture(:timestamp).as(:timestamp)
|
|
131
129
|
line.capture(:frontend_name).as(:string)
|
|
132
130
|
line.capture(:server_name).as(:string)
|
|
133
|
-
line.capture(:tq).as(:nillable_duration, :
|
|
134
|
-
line.capture(:tc).as(:nillable_duration, :
|
|
135
|
-
line.capture(:tr).as(:nillable_duration, :
|
|
136
|
-
line.capture(:tt).as(:duration, :
|
|
131
|
+
line.capture(:tq).as(:nillable_duration, unit: :msec)
|
|
132
|
+
line.capture(:tc).as(:nillable_duration, unit: :msec)
|
|
133
|
+
line.capture(:tr).as(:nillable_duration, unit: :msec)
|
|
134
|
+
line.capture(:tt).as(:duration, unit: :msec)
|
|
137
135
|
line.capture(:status_code).as(:integer)
|
|
138
|
-
line.capture(:bytes_read).as(:traffic, :
|
|
136
|
+
line.capture(:bytes_read).as(:traffic, unit: :byte)
|
|
139
137
|
line.capture(:captured_request_cookie).as(:nillable_string)
|
|
140
138
|
line.capture(:captured_response_cookie).as(:nillable_string)
|
|
141
139
|
line.capture(:termination_event_code).as(:nillable_string)
|
|
@@ -153,72 +151,71 @@ module RequestLogAnalyzer::FileFormat
|
|
|
153
151
|
|
|
154
152
|
# Define the summary report
|
|
155
153
|
report do |analyze|
|
|
156
|
-
analyze.hourly_spread :
|
|
154
|
+
analyze.hourly_spread field: :timestamp
|
|
157
155
|
|
|
158
156
|
analyze.frequency :client_ip,
|
|
159
|
-
|
|
157
|
+
title: 'Hits per IP'
|
|
160
158
|
|
|
161
159
|
analyze.frequency :frontend_name,
|
|
162
|
-
|
|
160
|
+
title: 'Hits per frontend service'
|
|
163
161
|
|
|
164
162
|
analyze.frequency :backend_name,
|
|
165
|
-
|
|
163
|
+
title: 'Hits per backend service'
|
|
166
164
|
|
|
167
165
|
analyze.frequency :server_name,
|
|
168
|
-
|
|
166
|
+
title: 'Hits per backend server'
|
|
169
167
|
|
|
170
168
|
analyze.frequency :status_code,
|
|
171
|
-
|
|
169
|
+
title: 'HTTP response code frequency'
|
|
172
170
|
|
|
173
171
|
analyze.frequency :http_request,
|
|
174
|
-
|
|
172
|
+
title: 'Most popular requests'
|
|
175
173
|
|
|
176
174
|
analyze.frequency :http_request,
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
175
|
+
title: 'Most frequent HTTP 40x errors',
|
|
176
|
+
category: lambda { |r| "#{r[:http_request]}" },
|
|
177
|
+
if: lambda { |r| r[:status_code] >= 400 && r[:status_code] <= 417 }
|
|
180
178
|
|
|
181
179
|
analyze.frequency :http_request,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
title: 'Most frequent HTTP 50x errors',
|
|
181
|
+
category: lambda { |r| "#{r[:http_request]}" },
|
|
182
|
+
if: lambda { |r| r[:status_code] >= 500 && r[:status_code] <= 505 }
|
|
185
183
|
|
|
186
184
|
analyze.traffic :bytes_read,
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
title: 'Traffic per frontend service',
|
|
186
|
+
category: lambda { |r| "#{r[:frontend_name]}" }
|
|
189
187
|
|
|
190
188
|
analyze.traffic :bytes_read,
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
title: 'Traffic per backend service',
|
|
190
|
+
category: lambda { |r| "#{r[:backend_name]}" }
|
|
193
191
|
|
|
194
192
|
analyze.traffic :bytes_read,
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
title: 'Traffic per backend server',
|
|
194
|
+
category: lambda { |r| "#{r[:server_name]}" }
|
|
197
195
|
|
|
198
196
|
analyze.duration :tr,
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
title: 'Time waiting for backend response',
|
|
198
|
+
category: lambda { |r| "#{r[:http_request]}" }
|
|
201
199
|
|
|
202
200
|
analyze.duration :tt,
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
title: 'Total time spent on request',
|
|
202
|
+
category: lambda { |r| "#{r[:http_request]}" }
|
|
205
203
|
end
|
|
206
204
|
|
|
207
205
|
# Define a custom Request class for the HAProxy file format to speed up
|
|
208
206
|
# timestamp handling. Shamelessly copied from apache.rb
|
|
209
207
|
class Request < RequestLogAnalyzer::Request
|
|
210
|
-
|
|
211
|
-
MONTHS = {'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
|
|
208
|
+
MONTHS = { 'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
|
|
212
209
|
'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' }
|
|
213
210
|
|
|
214
211
|
# Do not use DateTime.parse, but parse the timestamp ourselves to return
|
|
215
212
|
# a integer to speed up parsing.
|
|
216
|
-
def convert_timestamp(value,
|
|
217
|
-
"#{value[7,4]}#{MONTHS[value[3,3]]}#{value[0,2]}#{value[12,2]}#{value[15,2]}#{value[18,2]}".to_i
|
|
213
|
+
def convert_timestamp(value, _definition)
|
|
214
|
+
"#{value[7, 4]}#{MONTHS[value[3, 3]]}#{value[0, 2]}#{value[12, 2]}#{value[15, 2]}#{value[18, 2]}".to_i
|
|
218
215
|
end
|
|
219
216
|
|
|
220
217
|
# Make sure that the strings '-' or '{}' or '' are parsed as a nil value.
|
|
221
|
-
def convert_nillable_string(value,
|
|
218
|
+
def convert_nillable_string(value, _definition)
|
|
222
219
|
value =~ /-|\{\}|^$/ ? nil : value
|
|
223
220
|
end
|
|
224
221
|
|
|
@@ -226,7 +223,6 @@ module RequestLogAnalyzer::FileFormat
|
|
|
226
223
|
def convert_nillable_duration(value, definition)
|
|
227
224
|
value == '-1' ? nil : convert_duration(value, definition)
|
|
228
225
|
end
|
|
229
|
-
|
|
230
226
|
end
|
|
231
227
|
end
|
|
232
228
|
end
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
module RequestLogAnalyzer::FileFormat
|
|
2
|
-
|
|
3
2
|
# The Merb file format parses the request header with the timestamp, the params line
|
|
4
3
|
# with the most important request information and the durations line which contains
|
|
5
4
|
# the different request durations that can be used for analysis.
|
|
6
5
|
class Merb < Base
|
|
7
|
-
|
|
8
6
|
extend CommonRegularExpressions
|
|
9
7
|
|
|
10
8
|
# ~ Started request handling: Fri Aug 29 11:10:23 +0200 2008
|
|
@@ -12,7 +10,7 @@ module RequestLogAnalyzer::FileFormat
|
|
|
12
10
|
line.header = true
|
|
13
11
|
line.teaser = /Started request handling\:/
|
|
14
12
|
line.regexp = /Started request handling\:\ (#{timestamp('%a %b %d %H:%M:%S %z %Y')})/
|
|
15
|
-
line.captures << { :
|
|
13
|
+
line.captures << { name: :timestamp, type: :timestamp }
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
# ~ Params: {"action"=>"create", "controller"=>"session"}
|
|
@@ -20,8 +18,8 @@ module RequestLogAnalyzer::FileFormat
|
|
|
20
18
|
line_definition :params do |line|
|
|
21
19
|
line.teaser = /Params\:\ /
|
|
22
20
|
line.regexp = /Params\:\ (\{.+\})/
|
|
23
|
-
line.captures << { :
|
|
24
|
-
|
|
21
|
+
line.captures << { name: :params, type: :eval, provides: {
|
|
22
|
+
namespace: :string, controller: :string, action: :string, format: :string, method: :string } }
|
|
25
23
|
end
|
|
26
24
|
|
|
27
25
|
# ~ {:dispatch_time=>0.006117, :after_filters_time=>6.1e-05, :before_filters_time=>0.000712, :action_time=>0.005833}
|
|
@@ -29,12 +27,12 @@ module RequestLogAnalyzer::FileFormat
|
|
|
29
27
|
line.footer = true
|
|
30
28
|
# line.teaser = Regexp.new(Regexp.quote('~ {:'))
|
|
31
29
|
line.regexp = /(\{.*\:dispatch_time\s*=>\s*\d+\.\d+.*\})/
|
|
32
|
-
line.captures << { :
|
|
33
|
-
|
|
34
|
-
:
|
|
30
|
+
line.captures << { name: :times_hash, type: :eval, provides: {
|
|
31
|
+
dispatch_time: :duration, after_filters_time: :duration,
|
|
32
|
+
before_filters_time: :duration, action_time: :duration } }
|
|
35
33
|
end
|
|
36
34
|
|
|
37
|
-
REQUEST_CATEGORIZER =
|
|
35
|
+
REQUEST_CATEGORIZER = proc do |request|
|
|
38
36
|
category = "#{request[:controller]}##{request[:action]}"
|
|
39
37
|
category = "#{request[:namespace]}::#{category}" if request[:namespace]
|
|
40
38
|
category = "#{category}.#{request[:format]}" if request[:format]
|
|
@@ -46,8 +44,8 @@ module RequestLogAnalyzer::FileFormat
|
|
|
46
44
|
analyze.timespan
|
|
47
45
|
analyze.hourly_spread
|
|
48
46
|
|
|
49
|
-
analyze.frequency :
|
|
50
|
-
analyze.duration :dispatch_time, :
|
|
47
|
+
analyze.frequency category: REQUEST_CATEGORIZER, title: 'Top 20 by hits'
|
|
48
|
+
analyze.duration :dispatch_time, category: REQUEST_CATEGORIZER, title: 'Request dispatch duration'
|
|
51
49
|
|
|
52
50
|
# analyze.duration :action_time, :category => REQUEST_CATEGORIZER, :title => 'Request action duration'
|
|
53
51
|
# analyze.duration :after_filters_time, :category => REQUEST_CATEGORIZER, :title => 'Request after_filter duration'
|
|
@@ -55,15 +53,13 @@ module RequestLogAnalyzer::FileFormat
|
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
class Request < RequestLogAnalyzer::Request
|
|
58
|
-
|
|
59
|
-
MONTHS = {'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
|
|
56
|
+
MONTHS = { 'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06',
|
|
60
57
|
'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' }
|
|
61
58
|
|
|
62
59
|
# Speed up timestamp conversion
|
|
63
|
-
def convert_timestamp(value,
|
|
64
|
-
"#{value[26,4]}#{MONTHS[value[4,3]]}#{value[8,2]}#{value[11,2]}#{value[14,2]}#{value[17,2]}".to_i
|
|
60
|
+
def convert_timestamp(value, _definition)
|
|
61
|
+
"#{value[26, 4]}#{MONTHS[value[4, 3]]}#{value[8, 2]}#{value[11, 2]}#{value[14, 2]}#{value[17, 2]}".to_i
|
|
65
62
|
end
|
|
66
63
|
end
|
|
67
64
|
end
|
|
68
|
-
|
|
69
|
-
end
|
|
65
|
+
end
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
module RequestLogAnalyzer::FileFormat
|
|
2
|
-
|
|
3
2
|
class Mysql < Base
|
|
4
|
-
|
|
5
3
|
extend CommonRegularExpressions
|
|
6
4
|
|
|
7
5
|
line_definition :time do |line|
|
|
8
6
|
line.header = :alternative
|
|
9
7
|
line.teaser = /\# Time: /
|
|
10
8
|
line.regexp = /\# Time: (#{timestamp('%y%m%d %k:%M:%S')})/
|
|
11
|
-
|
|
9
|
+
|
|
12
10
|
line.capture(:timestamp).as(:timestamp)
|
|
13
11
|
end
|
|
14
12
|
|
|
@@ -16,7 +14,7 @@ module RequestLogAnalyzer::FileFormat
|
|
|
16
14
|
line.header = :alternative
|
|
17
15
|
line.teaser = /\# User\@Host\: /
|
|
18
16
|
line.regexp = /\# User\@Host\: ([\w-]+)\[[\w-]+\] \@ (#{hostname(true)}) \[(#{ip_address(true)})\]/
|
|
19
|
-
|
|
17
|
+
|
|
20
18
|
line.capture(:user)
|
|
21
19
|
line.capture(:host)
|
|
22
20
|
line.capture(:ip)
|
|
@@ -26,9 +24,9 @@ module RequestLogAnalyzer::FileFormat
|
|
|
26
24
|
line.header = :alternative
|
|
27
25
|
line.teaser = /\# Query_time: /
|
|
28
26
|
line.regexp = /\# Query_time: (\d+(?:\.\d+)?)\s+Lock_time: (\d+(?:\.\d+)?)\s+Rows_sent: (\d+)\s+Rows_examined: (\d+)/
|
|
29
|
-
|
|
30
|
-
line.capture(:query_time).as(:duration, :
|
|
31
|
-
line.capture(:lock_time).as(:duration, :
|
|
27
|
+
|
|
28
|
+
line.capture(:query_time).as(:duration, unit: :sec)
|
|
29
|
+
line.capture(:lock_time).as(:duration, unit: :sec)
|
|
32
30
|
line.capture(:rows_sent).as(:integer)
|
|
33
31
|
line.capture(:rows_examined).as(:integer)
|
|
34
32
|
end
|
|
@@ -51,25 +49,23 @@ module RequestLogAnalyzer::FileFormat
|
|
|
51
49
|
|
|
52
50
|
PER_USER = :user
|
|
53
51
|
PER_QUERY = :query
|
|
54
|
-
PER_USER_QUERY =
|
|
52
|
+
PER_USER_QUERY = proc { |request| "#{request[:user]}@#{request.host}: #{request[:query]}" }
|
|
55
53
|
|
|
56
54
|
report do |analyze|
|
|
57
|
-
analyze.timespan :
|
|
58
|
-
analyze.frequency :user, :
|
|
59
|
-
analyze.duration :query_time, :
|
|
60
|
-
analyze.duration :query_time, :
|
|
61
|
-
|
|
62
|
-
analyze.duration :lock_time, :category => PER_USER_QUERY, :title => 'Lock time',
|
|
63
|
-
:if => lambda { |request| request[:lock_time] > 0.0 }
|
|
64
|
-
|
|
65
|
-
analyze.numeric_value :rows_examined, :category => PER_USER_QUERY, :title => "Rows examined"
|
|
66
|
-
analyze.numeric_value :rows_sent, :category => PER_USER_QUERY, :title => "Rows sent"
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
class Request < RequestLogAnalyzer::Request
|
|
55
|
+
analyze.timespan line_type: :time
|
|
56
|
+
analyze.frequency :user, title: 'Users with most queries'
|
|
57
|
+
analyze.duration :query_time, category: PER_USER, title: 'Query time per user'
|
|
58
|
+
analyze.duration :query_time, category: PER_USER_QUERY, title: 'Query time'
|
|
70
59
|
|
|
71
|
-
|
|
60
|
+
analyze.duration :lock_time, category: PER_USER_QUERY, title: 'Lock time',
|
|
61
|
+
if: lambda { |request| request[:lock_time] > 0.0 }
|
|
72
62
|
|
|
63
|
+
analyze.numeric_value :rows_examined, category: PER_USER_QUERY, title: 'Rows examined'
|
|
64
|
+
analyze.numeric_value :rows_sent, category: PER_USER_QUERY, title: 'Rows sent'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Request < RequestLogAnalyzer::Request
|
|
68
|
+
def convert_sql(value, _definition)
|
|
73
69
|
# Recreate the full SQL query by joining all the previous parts and this last line
|
|
74
70
|
sql = every(:query_fragment).join("\n") + value
|
|
75
71
|
|
|
@@ -84,7 +80,7 @@ module RequestLogAnalyzer::FileFormat
|
|
|
84
80
|
sql.gsub!(/(:int,)+:int/, ':ints') # replace multiple ints by a list
|
|
85
81
|
sql.gsub!(/(:string,)+:string/, ':strings') # replace multiple strings by a list
|
|
86
82
|
|
|
87
|
-
|
|
83
|
+
sql.strip
|
|
88
84
|
end
|
|
89
85
|
|
|
90
86
|
def host
|
|
@@ -92,9 +88,9 @@ module RequestLogAnalyzer::FileFormat
|
|
|
92
88
|
end
|
|
93
89
|
|
|
94
90
|
# Convert the timestamp to an integer
|
|
95
|
-
def convert_timestamp(value,
|
|
91
|
+
def convert_timestamp(value, _definition)
|
|
96
92
|
_, y, m, d, h, i, s = value.split(/(\d\d)(\d\d)(\d\d)\s+(\d?\d):(\d\d):(\d\d)/)
|
|
97
|
-
('20%s%s%s%s%s%s' % [y,m,d,h.rjust(2, '0'),i,s]).to_i
|
|
93
|
+
('20%s%s%s%s%s%s' % [y, m, d, h.rjust(2, '0'), i, s]).to_i
|
|
98
94
|
end
|
|
99
95
|
end
|
|
100
96
|
end
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
class RequestLogAnalyzer::FileFormat::Oink < RequestLogAnalyzer::FileFormat::Rails
|
|
2
2
|
# capture the PID
|
|
3
3
|
HODEL3000_PROCESSING = /\[(\d+)\]: Processing ((?:\w+::)*\w+)#(\w+)(?: to (\w+))? \(for (#{ip_address}) at (#{timestamp('%Y-%m-%d %H:%M:%S')})\) \[([A-Z]+)\]/
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
# TODO: fix me!
|
|
6
6
|
line_definition :processing do |line|
|
|
7
7
|
line.header = true
|
|
8
|
-
line.regexp = Regexp.union(LINE_DEFINITIONS[:processing].regexp,HODEL3000_PROCESSING)
|
|
9
|
-
line.captures = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
8
|
+
line.regexp = Regexp.union(LINE_DEFINITIONS[:processing].regexp, HODEL3000_PROCESSING)
|
|
9
|
+
line.captures = [{ name: :controller, type: :string }, # Default Rails Processing
|
|
10
|
+
{ name: :action, type: :string },
|
|
11
|
+
{ name: :format, type: :string, default: 'html' },
|
|
12
|
+
{ name: :ip, type: :string },
|
|
13
|
+
{ name: :timestamp, type: :timestamp },
|
|
14
|
+
{ name: :method, type: :string },
|
|
15
|
+
{ name: :pid, type: :integer }, # Hodel 3000 Processing w/PID
|
|
16
|
+
{ name: :controller, type: :string },
|
|
17
|
+
{ name: :action, type: :string },
|
|
18
|
+
{ name: :format, type: :string, default: 'html' },
|
|
19
|
+
{ name: :ip, type: :string },
|
|
20
|
+
{ name: :timestamp, type: :timestamp },
|
|
21
|
+
{ name: :method, type: :string }]
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
line_definition :memory_usage do |line|
|
|
25
25
|
line.regexp = /\[(\d+)\]: Memory usage: (\d+)/
|
|
26
26
|
line.capture(:pid).as(:integer)
|
|
@@ -29,14 +29,14 @@ class RequestLogAnalyzer::FileFormat::Oink < RequestLogAnalyzer::FileFormat::Rai
|
|
|
29
29
|
|
|
30
30
|
line_definition :instance_type_counter do |line|
|
|
31
31
|
line.regexp = /\[(\d+)\]: Instantiation Breakdown: (.*)$/
|
|
32
|
-
line.capture(:pid).as(:integer)
|
|
32
|
+
line.capture(:pid).as(:integer)
|
|
33
33
|
line.capture(:instance_counts).as(:pipe_separated_counts)
|
|
34
34
|
end
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
report(:append) do |analyze|
|
|
37
|
-
analyze.traffic :memory_diff, :
|
|
37
|
+
analyze.traffic :memory_diff, category: REQUEST_CATEGORIZER, title: 'Largest Memory Increases', line_type: :memory_usage
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
# Keep a record of PIDs and their memory usage when validating requests.
|
|
41
41
|
def pids
|
|
42
42
|
@pids ||= {}
|
|
@@ -48,20 +48,20 @@ class RequestLogAnalyzer::FileFormat::Oink < RequestLogAnalyzer::FileFormat::Rai
|
|
|
48
48
|
update_pids
|
|
49
49
|
super
|
|
50
50
|
end
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
# Accessor for memory information associated with the specified request PID. If no memory exists
|
|
53
53
|
# for this request's :pid, the memory tracking is initialized.
|
|
54
54
|
def pid_memory
|
|
55
|
-
file_format.pids[self[:pid]] ||= { :
|
|
55
|
+
file_format.pids[self[:pid]] ||= { last_memory_reading: -1, current_memory_reading: -1 }
|
|
56
56
|
end
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
# Calculates :memory_diff for each request based on the last completed request that was not a failure.
|
|
59
59
|
def update_pids
|
|
60
60
|
# memory isn't recorded with exceptions. need to set #last_memory_reading+ to -1 as
|
|
61
61
|
# the memory used could have changed. for the next request the memory change will not be recorded.
|
|
62
62
|
#
|
|
63
63
|
# NOTE - the failure regex was not matching with a Rails Development log file.
|
|
64
|
-
if has_line_type?(:failure)
|
|
64
|
+
if has_line_type?(:failure) && processing = has_line_type?(:processing)
|
|
65
65
|
pid_memory[:last_memory_reading] = -1
|
|
66
66
|
elsif mem_line = has_line_type?(:memory_usage)
|
|
67
67
|
memory_reading = mem_line[:memory]
|
|
@@ -69,28 +69,27 @@ class RequestLogAnalyzer::FileFormat::Oink < RequestLogAnalyzer::FileFormat::Rai
|
|
|
69
69
|
# calcuate the change in memory
|
|
70
70
|
unless pid_memory[:current_memory_reading] == -1 || pid_memory[:last_memory_reading] == -1
|
|
71
71
|
# logged as kB, need to convert to bytes for the :traffic Tracker
|
|
72
|
-
memory_diff = (pid_memory[:current_memory_reading] - pid_memory[:last_memory_reading])*1024
|
|
72
|
+
memory_diff = (pid_memory[:current_memory_reading] - pid_memory[:last_memory_reading]) * 1024
|
|
73
73
|
if memory_diff > 0
|
|
74
|
-
|
|
74
|
+
attributes[:memory_diff] = memory_diff
|
|
75
75
|
end # if memory_diff > 0
|
|
76
76
|
end # unless
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
pid_memory[:last_memory_reading] = pid_memory[:current_memory_reading]
|
|
79
79
|
pid_memory[:current_memory_reading] = -1
|
|
80
80
|
end # if mem_line
|
|
81
|
-
|
|
81
|
+
true
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
def convert_pipe_separated_counts(value,
|
|
84
|
+
def convert_pipe_separated_counts(value, _capture_definition)
|
|
85
85
|
count_strings = value.split(' | ')
|
|
86
86
|
count_arrays = count_strings.map do |count_string|
|
|
87
87
|
if count_string =~ /^(\w+): (\d+)/
|
|
88
|
-
[
|
|
88
|
+
[Regexp.last_match[1], Regexp.last_match[2].to_i]
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
Hash[count_arrays]
|
|
93
93
|
end
|
|
94
|
-
|
|
95
94
|
end # class Request
|
|
96
95
|
end
|