production_log_analyzer 1.1.0 → 1.2.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/README +82 -46
- data/Rakefile +1 -1
- data/bin/pl_analyze +18 -33
- data/lib/production_log/analyzer.rb +162 -42
- data/test/test_analyzer.rb +237 -25
- metadata +3 -3
data/README
CHANGED
@@ -26,7 +26,7 @@ http://rubyforge.org/frs/?group_id=586
|
|
26
26
|
|
27
27
|
Either:
|
28
28
|
|
29
|
-
A syslogd that doesn't suck. This means that
|
29
|
+
A syslogd that doesn't suck. This means that syslog.conf(5) shows a
|
30
30
|
!prog specification. (FreeBSD's syslogd doesn't suck, but OS X's syslogd
|
31
31
|
does.)
|
32
32
|
|
@@ -62,60 +62,96 @@ If you want, you can run it from a cron something like this:
|
|
62
62
|
|
63
63
|
/usr/bin/gzip -dc /var/log/production.log.0.gz | /usr/local/bin/pl_analyze /dev/stdin
|
64
64
|
|
65
|
+
Or, have pl_analyze email you (which is preferred, because tabs get preserved):
|
66
|
+
|
67
|
+
/usr/bin/gzip -dc /var/log/production.log.0.gz | /usr/local/bin/pl_analyze /dev/stdin -e devnull@robotcoop.com -s "pl_analyze for `date -v-1d "+%D"`"
|
68
|
+
|
65
69
|
In the future, pl_analyze will be able to read from STDIN.
|
66
70
|
|
67
71
|
= Sample output
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
73
|
+
Request Times Summary: Count Avg Std Dev Min Max
|
74
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
75
|
+
|
76
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
77
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
78
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
79
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
80
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
81
|
+
|
82
|
+
Average Request Time: 0.634
|
83
|
+
Request Time Std Dev: 0.498
|
84
|
+
|
85
|
+
Slowest Request Times:
|
86
|
+
TeamsController#progress took 1.470s
|
87
|
+
ThingsController#view took 1.260s
|
88
|
+
PeopleController#view took 1.102s
|
89
|
+
PeopleController#progress took 0.977s
|
90
|
+
ThingsController#view took 0.492s
|
91
|
+
ThingsController#view took 0.396s
|
92
|
+
PeopleController#view took 0.360s
|
93
|
+
TeamsController#progress took 0.212s
|
94
|
+
RssController#uber took 0.035s
|
95
|
+
RssController#uber took 0.035s
|
96
|
+
|
97
|
+
------------------------------------------------------------------------
|
98
|
+
|
99
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
100
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
101
|
+
|
102
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
103
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
104
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
105
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
106
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
107
|
+
|
108
|
+
Average DB Time: 0.402
|
109
|
+
DB Time Std Dev: 0.394
|
110
|
+
|
111
|
+
Slowest Total DB Times:
|
112
|
+
TeamsController#progress took 1.144s
|
113
|
+
ThingsController#view took 0.914s
|
114
|
+
PeopleController#progress took 0.830s
|
115
|
+
PeopleController#view took 0.486s
|
116
|
+
PeopleController#view took 0.189s
|
117
|
+
ThingsController#view took 0.173s
|
118
|
+
TeamsController#progress took 0.149s
|
119
|
+
ThingsController#view took 0.122s
|
120
|
+
RssController#uber took 0.008s
|
121
|
+
RssController#uber took 0.008s
|
122
|
+
|
123
|
+
------------------------------------------------------------------------
|
124
|
+
|
125
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
126
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
127
|
+
|
128
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
129
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
130
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
131
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
132
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
133
|
+
|
134
|
+
Average Render Time: 0.302
|
135
|
+
Render Time Std Dev: 0.251
|
136
|
+
|
137
|
+
Slowest Total Render Times:
|
138
|
+
PeopleController#view took 0.695s
|
139
|
+
PeopleController#progress took 0.604s
|
140
|
+
ThingsController#view took 0.506s
|
141
|
+
PeopleController#view took 0.278s
|
142
|
+
ThingsController#view took 0.197s
|
143
|
+
ThingsController#view took 0.108s
|
144
|
+
RssController#uber took 0.012s
|
145
|
+
RssController#uber took 0.012s
|
146
|
+
TeamsController#progress took 0.000s
|
147
|
+
TeamsController#progress took 0.000s
|
113
148
|
|
114
149
|
= What's missing
|
115
150
|
|
116
151
|
* More reports
|
117
152
|
* Command line arguments including:
|
118
|
-
*
|
153
|
+
* Help
|
119
154
|
* What type of log file you've got (if somebody sends patches with tests)
|
155
|
+
* Read from STDIN
|
120
156
|
* Lots more
|
121
157
|
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ $VERBOSE = nil
|
|
9
9
|
|
10
10
|
spec = Gem::Specification.new do |s|
|
11
11
|
s.name = "production_log_analyzer"
|
12
|
-
s.version = "1.
|
12
|
+
s.version = "1.2.0"
|
13
13
|
s.summary = "Extracts statistics from Rails production logs"
|
14
14
|
s.author = "Eric Hodel"
|
15
15
|
s.email = "hodel@robotcoop.com"
|
data/bin/pl_analyze
CHANGED
@@ -5,46 +5,31 @@ require 'production_log/analyzer'
|
|
5
5
|
file_name = ARGV.shift
|
6
6
|
|
7
7
|
if file_name.nil? then
|
8
|
-
puts "Usage: #{$0} file_name"
|
8
|
+
puts "Usage: #{$0} file_name [-e email_recipient [-s subject]] [count]"
|
9
9
|
exit 1
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
email_recipient = nil
|
13
|
+
subject = nil
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
request_times = analyzer.slowest_request_times(count).map do |time, name|
|
19
|
-
"\t#{name} took #{time}s"
|
15
|
+
if ARGV.first == '-e' then
|
16
|
+
ARGV.shift # -e
|
17
|
+
email_recipient = ARGV.shift
|
20
18
|
end
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
puts "Slowest Request Times:"
|
26
|
-
puts request_times.join($/)
|
27
|
-
puts
|
28
|
-
|
29
|
-
db_times = analyzer.slowest_db_times(count).map do |time, name|
|
30
|
-
"\t#{name} took #{time}s"
|
20
|
+
if email_recipient and ARGV.first == '-s' then
|
21
|
+
ARGV.shift # -s
|
22
|
+
subject = ARGV.shift
|
31
23
|
end
|
32
24
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
25
|
+
count = ARGV.shift
|
26
|
+
count = count.nil? ? 10 : Integer(count)
|
27
|
+
|
28
|
+
if email_recipient.nil? then
|
29
|
+
analyzer = Analyzer.new file_name
|
30
|
+
analyzer.process
|
31
|
+
puts analyzer.report(count)
|
32
|
+
else
|
33
|
+
Analyzer.email file_name, email_recipient, subject, count
|
42
34
|
end
|
43
35
|
|
44
|
-
puts "Average Render Time: #{analyzer.average_render_time}"
|
45
|
-
puts "Render Time Std Dev: #{analyzer.render_time_std_dev}"
|
46
|
-
puts
|
47
|
-
puts "Slowest Total Render Times:"
|
48
|
-
puts render_times.join($/)
|
49
|
-
puts
|
50
|
-
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
$TESTING = false unless defined? $TESTING
|
2
2
|
|
3
3
|
require 'production_log/parser'
|
4
4
|
|
@@ -131,7 +131,36 @@ class Analyzer
|
|
131
131
|
|
132
132
|
attr_reader :render_times
|
133
133
|
|
134
|
-
|
134
|
+
##
|
135
|
+
# Generates and sends an email report with lots of fun stuff in it. This
|
136
|
+
# way, Mail.app will behave when given tabs (I hope).
|
137
|
+
|
138
|
+
def self.email(file_name, recipient, subject, count = 10)
|
139
|
+
analyzer = self.new file_name
|
140
|
+
analyzer.process
|
141
|
+
body = analyzer.report(count)
|
142
|
+
|
143
|
+
email = self.envelope(recipient, subject)
|
144
|
+
email << nil
|
145
|
+
email << "<pre>#{body}</pre>"
|
146
|
+
email = email.join($/) << $/
|
147
|
+
|
148
|
+
return email if $TESTING
|
149
|
+
|
150
|
+
IO.popen("/usr/sbin/sendmail -i -t", "w+") do |sm|
|
151
|
+
sm.print email
|
152
|
+
sm.flush
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.envelope(recipient, subject = nil) # :nodoc:
|
157
|
+
envelope = {}
|
158
|
+
envelope['To'] = recipient
|
159
|
+
envelope['Subject'] = subject || "pl_analyze"
|
160
|
+
envelope['Content-Type'] = "text/html"
|
161
|
+
|
162
|
+
return envelope.map { |(k,v)| "#{k}: #{v}" }
|
163
|
+
end
|
135
164
|
|
136
165
|
##
|
137
166
|
# Creates a new Analyzer that will read data from +logfile_name+.
|
@@ -154,9 +183,6 @@ class Analyzer
|
|
154
183
|
@request_times[entry_page] << entry.request_time
|
155
184
|
@db_times[entry_page] << entry.db_time
|
156
185
|
@render_times[entry_page] << entry.render_time
|
157
|
-
# entry.queries.each do |name, time, sql|
|
158
|
-
# @query_times[entry_page] << time
|
159
|
-
# end
|
160
186
|
end
|
161
187
|
end
|
162
188
|
end
|
@@ -165,93 +191,166 @@ class Analyzer
|
|
165
191
|
# The average total request time for all requests.
|
166
192
|
|
167
193
|
def average_request_time
|
168
|
-
|
169
|
-
times.delete 0
|
170
|
-
return times.average
|
194
|
+
return time_average(@request_times)
|
171
195
|
end
|
172
196
|
|
173
197
|
##
|
174
198
|
# The standard deviation of the total request time for all requests.
|
175
199
|
|
176
200
|
def request_time_std_dev
|
177
|
-
|
178
|
-
times.delete 0
|
179
|
-
return times.standard_deviation
|
201
|
+
return time_std_dev(@request_times)
|
180
202
|
end
|
181
203
|
|
182
204
|
##
|
183
205
|
# The +limit+ slowest total request times.
|
184
206
|
|
185
207
|
def slowest_request_times(limit = 10)
|
186
|
-
slowest_times
|
187
|
-
|
188
|
-
@request_times.each do |name, times|
|
189
|
-
times.each do |time|
|
190
|
-
slowest_times << [time, name]
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
return slowest_times.sort_by { |time, name| time }.reverse
|
208
|
+
return slowest_times(@request_times, limit)
|
195
209
|
end
|
196
210
|
|
197
211
|
##
|
198
212
|
# The average total database time for all requests.
|
199
213
|
|
200
214
|
def average_db_time
|
201
|
-
|
202
|
-
times.delete 0
|
203
|
-
return times.average
|
215
|
+
return time_average(@db_times)
|
204
216
|
end
|
205
217
|
|
206
218
|
##
|
207
219
|
# The standard deviation of the total database time for all requests.
|
208
220
|
|
209
221
|
def db_time_std_dev
|
210
|
-
|
211
|
-
times.delete 0
|
212
|
-
return times.standard_deviation
|
222
|
+
return time_std_dev(@db_times)
|
213
223
|
end
|
214
224
|
|
215
225
|
##
|
216
226
|
# The +limit+ slowest total database times.
|
217
227
|
|
218
228
|
def slowest_db_times(limit = 10)
|
219
|
-
slowest_times
|
220
|
-
|
221
|
-
@db_times.each do |name, times|
|
222
|
-
times.each do |time|
|
223
|
-
slowest_times << [time, name]
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
return slowest_times.sort_by { |time, name| time }.reverse
|
229
|
+
return slowest_times(@db_times, limit)
|
228
230
|
end
|
229
231
|
|
230
232
|
##
|
231
233
|
# The average total render time for all requests.
|
232
234
|
|
233
235
|
def average_render_time
|
234
|
-
|
235
|
-
times.delete 0
|
236
|
-
return times.average
|
236
|
+
return time_average(@render_times)
|
237
237
|
end
|
238
238
|
|
239
239
|
##
|
240
240
|
# The standard deviation of the total render time for all requests.
|
241
241
|
|
242
242
|
def render_time_std_dev
|
243
|
-
|
244
|
-
times.delete 0
|
245
|
-
return times.standard_deviation
|
243
|
+
return time_std_dev(@render_times)
|
246
244
|
end
|
247
245
|
|
248
246
|
##
|
249
247
|
# The +limit+ slowest total render times for all requests.
|
250
248
|
|
251
249
|
def slowest_render_times(limit = 10)
|
250
|
+
return slowest_times(@render_times, limit)
|
251
|
+
end
|
252
|
+
|
253
|
+
##
|
254
|
+
# A list of count/min/max/avg/std dev for request times.
|
255
|
+
|
256
|
+
def request_times_summary
|
257
|
+
return summarize("Request Times", @request_times)
|
258
|
+
end
|
259
|
+
|
260
|
+
##
|
261
|
+
# A list of count/min/max/avg/std dev for database times.
|
262
|
+
|
263
|
+
def db_times_summary
|
264
|
+
return summarize("DB Times", @db_times)
|
265
|
+
end
|
266
|
+
|
267
|
+
##
|
268
|
+
# A list of count/min/max/avg/std dev for request times.
|
269
|
+
|
270
|
+
def render_times_summary
|
271
|
+
return summarize("Render Times", @render_times)
|
272
|
+
end
|
273
|
+
|
274
|
+
##
|
275
|
+
# Builds a report containing +count+ slow items.
|
276
|
+
|
277
|
+
def report(count)
|
278
|
+
text = []
|
279
|
+
|
280
|
+
text << request_times_summary
|
281
|
+
text << nil
|
282
|
+
text << "Average Request Time: #{'%0.3f' % average_request_time}"
|
283
|
+
text << "Request Time Std Dev: #{'%0.3f' % request_time_std_dev}"
|
284
|
+
text << nil
|
285
|
+
text << "Slowest Request Times:"
|
286
|
+
slowest_request_times(count).each do |time, name|
|
287
|
+
text << "\t#{name} took #{'%0.3f' % time}s"
|
288
|
+
end
|
289
|
+
text << nil
|
290
|
+
text << "-" * 72
|
291
|
+
text << nil
|
292
|
+
|
293
|
+
text << db_times_summary
|
294
|
+
text << nil
|
295
|
+
text << "Average DB Time: #{'%0.3f' % average_db_time}"
|
296
|
+
text << "DB Time Std Dev: #{'%0.3f' % db_time_std_dev}"
|
297
|
+
text << nil
|
298
|
+
text << "Slowest Total DB Times:"
|
299
|
+
slowest_db_times(count).each do |time, name|
|
300
|
+
text << "\t#{name} took #{'%0.3f' % time}s"
|
301
|
+
end
|
302
|
+
text << nil
|
303
|
+
text << "-" * 72
|
304
|
+
text << nil
|
305
|
+
|
306
|
+
|
307
|
+
text << render_times_summary
|
308
|
+
text << nil
|
309
|
+
text << "Average Render Time: #{'%0.3f' % average_render_time}"
|
310
|
+
text << "Render Time Std Dev: #{'%0.3f' % render_time_std_dev}"
|
311
|
+
text << nil
|
312
|
+
text << "Slowest Total Render Times:"
|
313
|
+
slowest_render_times(count).each do |time, name|
|
314
|
+
text << "\t#{name} took #{'%0.3f' % time}s"
|
315
|
+
end
|
316
|
+
text << nil
|
317
|
+
|
318
|
+
return text.join($/)
|
319
|
+
end
|
320
|
+
|
321
|
+
private unless $TESTING
|
322
|
+
|
323
|
+
def summarize(title, records) # :nodoc:
|
324
|
+
record = nil
|
325
|
+
list = []
|
326
|
+
|
327
|
+
records.sort_by { |k,v| v.size}.reverse_each do |req, times|
|
328
|
+
record = [times.average, times.standard_deviation,
|
329
|
+
times.min, times.max]
|
330
|
+
record.map! { |v| "%0.3f" % v }
|
331
|
+
record.unshift ["#{pad_request_name req}", times.size]
|
332
|
+
list << record.join("\t")
|
333
|
+
end
|
334
|
+
|
335
|
+
list.unshift nil
|
336
|
+
|
337
|
+
times = records.values.flatten
|
338
|
+
record = [times.average, times.standard_deviation, times.min, times.max]
|
339
|
+
record.map! { |v| "%0.3f" % v }
|
340
|
+
record.unshift [pad_request_name('ALL REQUESTS'), times.size]
|
341
|
+
list.unshift record.join("\t")
|
342
|
+
|
343
|
+
record = [pad_request_name("#{title} Summary"), 'Count', 'Avg',
|
344
|
+
'Std Dev', 'Min', 'Max']
|
345
|
+
list.unshift record.join("\t")
|
346
|
+
|
347
|
+
return list.join("\n")
|
348
|
+
end
|
349
|
+
|
350
|
+
def slowest_times(records, limit) # :nodoc:
|
252
351
|
slowest_times = SlowestTimes.new limit
|
253
352
|
|
254
|
-
|
353
|
+
records.each do |name, times|
|
255
354
|
times.each do |time|
|
256
355
|
slowest_times << [time, name]
|
257
356
|
end
|
@@ -260,6 +359,27 @@ class Analyzer
|
|
260
359
|
return slowest_times.sort_by { |time, name| time }.reverse
|
261
360
|
end
|
262
361
|
|
362
|
+
def time_average(records) # :nodoc:
|
363
|
+
times = records.values.flatten
|
364
|
+
times.delete 0
|
365
|
+
return times.average
|
366
|
+
end
|
367
|
+
|
368
|
+
def time_std_dev(records) # :nodoc:
|
369
|
+
times = records.values.flatten
|
370
|
+
times.delete 0
|
371
|
+
return times.standard_deviation
|
372
|
+
end
|
373
|
+
|
374
|
+
def longest_request_name # :nodoc:
|
375
|
+
@longest_req ||= @request_times.keys.map { |name| name.length + 1 }.max
|
376
|
+
end
|
377
|
+
|
378
|
+
def pad_request_name(name) # :nodoc:
|
379
|
+
name = name.dup << ':'
|
380
|
+
name += (' ' * (longest_request_name - name.length))
|
381
|
+
end
|
382
|
+
|
263
383
|
end
|
264
384
|
|
265
385
|
# vim: ts=4 sts=4 sw=4
|
data/test/test_analyzer.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
#!/usr/local/bin/ruby -w
|
2
2
|
|
3
|
+
$TESTING = true
|
4
|
+
|
3
5
|
require 'test/unit'
|
4
6
|
|
5
7
|
require 'production_log/analyzer'
|
@@ -85,6 +87,120 @@ class TestAnalyzer < Test::Unit::TestCase
|
|
85
87
|
@analyzer.process
|
86
88
|
end
|
87
89
|
|
90
|
+
def test_self_email
|
91
|
+
email = Analyzer.email('test/test.syslog.log', 'devnull@robotcoop.com',
|
92
|
+
nil, 1)
|
93
|
+
expected = <<-EOF
|
94
|
+
Subject: pl_analyze
|
95
|
+
To: devnull@robotcoop.com
|
96
|
+
Content-Type: text/html
|
97
|
+
|
98
|
+
<pre>Request Times Summary: Count Avg Std Dev Min Max
|
99
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
100
|
+
|
101
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
102
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
103
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
104
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
105
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
106
|
+
|
107
|
+
Average Request Time: 0.634
|
108
|
+
Request Time Std Dev: 0.498
|
109
|
+
|
110
|
+
Slowest Request Times:
|
111
|
+
TeamsController#progress took 1.470s
|
112
|
+
|
113
|
+
------------------------------------------------------------------------
|
114
|
+
|
115
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
116
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
117
|
+
|
118
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
119
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
120
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
121
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
122
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
123
|
+
|
124
|
+
Average DB Time: 0.402
|
125
|
+
DB Time Std Dev: 0.394
|
126
|
+
|
127
|
+
Slowest Total DB Times:
|
128
|
+
TeamsController#progress took 1.144s
|
129
|
+
|
130
|
+
------------------------------------------------------------------------
|
131
|
+
|
132
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
133
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
134
|
+
|
135
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
136
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
137
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
138
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
139
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
140
|
+
|
141
|
+
Average Render Time: 0.302
|
142
|
+
Render Time Std Dev: 0.251
|
143
|
+
|
144
|
+
Slowest Total Render Times:
|
145
|
+
PeopleController#view took 0.695s
|
146
|
+
</pre>
|
147
|
+
EOF
|
148
|
+
|
149
|
+
assert_equal expected, email
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_self_envelope
|
153
|
+
expected = [
|
154
|
+
"Subject: pl_analyze",
|
155
|
+
"To: devnull@example.com",
|
156
|
+
"Content-Type: text/html"
|
157
|
+
]
|
158
|
+
|
159
|
+
assert_equal expected, Analyzer.envelope('devnull@example.com')
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_self_envelope_subject
|
163
|
+
expected = [
|
164
|
+
"Subject: happy fancy boom",
|
165
|
+
"To: devnull@example.com",
|
166
|
+
"Content-Type: text/html"
|
167
|
+
]
|
168
|
+
|
169
|
+
assert_equal(expected,
|
170
|
+
Analyzer.envelope('devnull@example.com', 'happy fancy boom'))
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_average_db_time
|
174
|
+
assert_in_delta 0.4023761, @analyzer.average_db_time, 0.0000001
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_average_render_time
|
178
|
+
assert_in_delta 0.3015584, @analyzer.average_render_time, 0.0000001
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_average_request_time
|
182
|
+
assert_in_delta 0.6338176, @analyzer.average_request_time, 0.0000001
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_db_time_std_dev
|
186
|
+
assert_in_delta 0.3941380, @analyzer.db_time_std_dev, 0.0000001
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_db_times_summary
|
190
|
+
expected = <<EOF.strip
|
191
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
192
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
193
|
+
|
194
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
195
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
196
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
197
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
198
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
199
|
+
EOF
|
200
|
+
|
201
|
+
assert_equal expected, @analyzer.db_times_summary
|
202
|
+
end
|
203
|
+
|
88
204
|
def test_logfile_name
|
89
205
|
assert_equal 'test/test.syslog.log', @analyzer.logfile_name
|
90
206
|
end
|
@@ -122,25 +238,126 @@ class TestAnalyzer < Test::Unit::TestCase
|
|
122
238
|
# assert_equal expected_query_times, @analyzer.query_times
|
123
239
|
end
|
124
240
|
|
125
|
-
def
|
126
|
-
|
127
|
-
assert_equal 3, times.length
|
128
|
-
expected = [
|
129
|
-
[1.469788, "TeamsController#progress"],
|
130
|
-
[1.259728, "ThingsController#view"],
|
131
|
-
[1.102098, "PeopleController#view"]
|
132
|
-
]
|
133
|
-
assert_equal expected, times
|
241
|
+
def test_render_time_std_dev
|
242
|
+
assert_in_delta 0.2513925, @analyzer.render_time_std_dev, 0.0000001
|
134
243
|
end
|
135
244
|
|
136
|
-
def
|
137
|
-
|
245
|
+
def test_render_times_summary
|
246
|
+
expected = <<EOF.strip
|
247
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
248
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
249
|
+
|
250
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
251
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
252
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
253
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
254
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
255
|
+
EOF
|
256
|
+
|
257
|
+
assert_equal expected, @analyzer.render_times_summary
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_report
|
261
|
+
expected = <<-EOF
|
262
|
+
Request Times Summary: Count Avg Std Dev Min Max
|
263
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
264
|
+
|
265
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
266
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
267
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
268
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
269
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
270
|
+
|
271
|
+
Average Request Time: 0.634
|
272
|
+
Request Time Std Dev: 0.498
|
273
|
+
|
274
|
+
Slowest Request Times:
|
275
|
+
TeamsController#progress took 1.470s
|
276
|
+
ThingsController#view took 1.260s
|
277
|
+
PeopleController#view took 1.102s
|
278
|
+
PeopleController#progress took 0.977s
|
279
|
+
ThingsController#view took 0.492s
|
280
|
+
ThingsController#view took 0.396s
|
281
|
+
PeopleController#view took 0.360s
|
282
|
+
TeamsController#progress took 0.212s
|
283
|
+
RssController#uber took 0.035s
|
284
|
+
RssController#uber took 0.035s
|
285
|
+
|
286
|
+
------------------------------------------------------------------------
|
287
|
+
|
288
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
289
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
290
|
+
|
291
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
292
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
293
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
294
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
295
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
296
|
+
|
297
|
+
Average DB Time: 0.402
|
298
|
+
DB Time Std Dev: 0.394
|
299
|
+
|
300
|
+
Slowest Total DB Times:
|
301
|
+
TeamsController#progress took 1.144s
|
302
|
+
ThingsController#view took 0.914s
|
303
|
+
PeopleController#progress took 0.830s
|
304
|
+
PeopleController#view took 0.486s
|
305
|
+
PeopleController#view took 0.189s
|
306
|
+
ThingsController#view took 0.173s
|
307
|
+
TeamsController#progress took 0.149s
|
308
|
+
ThingsController#view took 0.122s
|
309
|
+
RssController#uber took 0.008s
|
310
|
+
RssController#uber took 0.008s
|
311
|
+
|
312
|
+
------------------------------------------------------------------------
|
313
|
+
|
314
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
315
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
316
|
+
|
317
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
318
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
319
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
320
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
321
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
322
|
+
|
323
|
+
Average Render Time: 0.302
|
324
|
+
Render Time Std Dev: 0.251
|
325
|
+
|
326
|
+
Slowest Total Render Times:
|
327
|
+
PeopleController#view took 0.695s
|
328
|
+
PeopleController#progress took 0.604s
|
329
|
+
ThingsController#view took 0.506s
|
330
|
+
PeopleController#view took 0.278s
|
331
|
+
ThingsController#view took 0.197s
|
332
|
+
ThingsController#view took 0.108s
|
333
|
+
RssController#uber took 0.012s
|
334
|
+
RssController#uber took 0.012s
|
335
|
+
TeamsController#progress took 0.000s
|
336
|
+
TeamsController#progress took 0.000s
|
337
|
+
EOF
|
338
|
+
|
339
|
+
assert_equal expected, @analyzer.report(10)
|
138
340
|
end
|
139
341
|
|
140
342
|
def test_request_time_std_dev
|
141
343
|
assert_in_delta 0.4975667, @analyzer.request_time_std_dev, 0.0000001
|
142
344
|
end
|
143
345
|
|
346
|
+
def test_request_times_summary
|
347
|
+
expected = <<EOF.strip
|
348
|
+
Request Times Summary: Count Avg Std Dev Min Max
|
349
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
350
|
+
|
351
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
352
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
353
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
354
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
355
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
356
|
+
EOF
|
357
|
+
|
358
|
+
assert_equal expected, @analyzer.request_times_summary
|
359
|
+
end
|
360
|
+
|
144
361
|
def test_slowest_db_times
|
145
362
|
times = @analyzer.slowest_db_times 3
|
146
363
|
assert_equal 3, times.length
|
@@ -152,12 +369,15 @@ class TestAnalyzer < Test::Unit::TestCase
|
|
152
369
|
assert_equal expected, times
|
153
370
|
end
|
154
371
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
372
|
+
def test_slowest_request_times
|
373
|
+
times = @analyzer.slowest_request_times 3
|
374
|
+
assert_equal 3, times.length
|
375
|
+
expected = [
|
376
|
+
[1.469788, "TeamsController#progress"],
|
377
|
+
[1.259728, "ThingsController#view"],
|
378
|
+
[1.102098, "PeopleController#view"]
|
379
|
+
]
|
380
|
+
assert_equal expected, times
|
161
381
|
end
|
162
382
|
|
163
383
|
def test_slowest_render_times
|
@@ -171,13 +391,5 @@ class TestAnalyzer < Test::Unit::TestCase
|
|
171
391
|
assert_equal expected, times
|
172
392
|
end
|
173
393
|
|
174
|
-
def test_average_render_time
|
175
|
-
assert_in_delta 0.3015584, @analyzer.average_render_time, 0.0000001
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_render_time_std_dev
|
179
|
-
assert_in_delta 0.2513925, @analyzer.render_time_std_dev, 0.0000001
|
180
|
-
end
|
181
|
-
|
182
394
|
end
|
183
395
|
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.10
|
3
3
|
specification_version: 1
|
4
4
|
name: production_log_analyzer
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2005-
|
6
|
+
version: 1.2.0
|
7
|
+
date: 2005-05-10
|
8
8
|
summary: Extracts statistics from Rails production logs
|
9
9
|
require_paths:
|
10
10
|
- lib
|