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.
- 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
|