production_log_analyzer 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +75 -75
- data/Rakefile +3 -3
- data/lib/production_log/analyzer.rb +27 -26
- data/lib/production_log/syslog_logger.rb +42 -13
- data/test/test_analyzer.rb +28 -18
- metadata +2 -2
data/README
CHANGED
@@ -70,81 +70,81 @@ In the future, pl_analyze will be able to read from STDIN.
|
|
70
70
|
|
71
71
|
= Sample output
|
72
72
|
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
148
148
|
|
149
149
|
= What's missing
|
150
150
|
|
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.2.
|
12
|
+
s.version = "1.2.1"
|
13
13
|
s.summary = "Extracts statistics from Rails production logs"
|
14
14
|
s.author = "Eric Hodel"
|
15
15
|
s.email = "hodel@robotcoop.com"
|
@@ -40,8 +40,8 @@ end
|
|
40
40
|
|
41
41
|
desc "Build Gem"
|
42
42
|
Rake::GemPackageTask.new spec do |pkg|
|
43
|
-
pkg.need_zip =
|
44
|
-
pkg.need_tar =
|
43
|
+
pkg.need_zip = true
|
44
|
+
pkg.need_tar = true
|
45
45
|
end
|
46
46
|
|
47
47
|
desc "Sends RDoc to RubyForge"
|
@@ -133,12 +133,12 @@ class Analyzer
|
|
133
133
|
|
134
134
|
##
|
135
135
|
# Generates and sends an email report with lots of fun stuff in it. This
|
136
|
-
# way, Mail.app will behave when given tabs
|
136
|
+
# way, Mail.app will behave when given tabs.
|
137
137
|
|
138
138
|
def self.email(file_name, recipient, subject, count = 10)
|
139
139
|
analyzer = self.new file_name
|
140
140
|
analyzer.process
|
141
|
-
body = analyzer.report
|
141
|
+
body = analyzer.report count
|
142
142
|
|
143
143
|
email = self.envelope(recipient, subject)
|
144
144
|
email << nil
|
@@ -279,9 +279,6 @@ class Analyzer
|
|
279
279
|
|
280
280
|
text << request_times_summary
|
281
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
282
|
text << "Slowest Request Times:"
|
286
283
|
slowest_request_times(count).each do |time, name|
|
287
284
|
text << "\t#{name} took #{'%0.3f' % time}s"
|
@@ -292,9 +289,6 @@ class Analyzer
|
|
292
289
|
|
293
290
|
text << db_times_summary
|
294
291
|
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
292
|
text << "Slowest Total DB Times:"
|
299
293
|
slowest_db_times(count).each do |time, name|
|
300
294
|
text << "\t#{name} took #{'%0.3f' % time}s"
|
@@ -303,12 +297,8 @@ class Analyzer
|
|
303
297
|
text << "-" * 72
|
304
298
|
text << nil
|
305
299
|
|
306
|
-
|
307
300
|
text << render_times_summary
|
308
301
|
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
302
|
text << "Slowest Total Render Times:"
|
313
303
|
slowest_render_times(count).each do |time, name|
|
314
304
|
text << "\t#{name} took #{'%0.3f' % time}s"
|
@@ -324,6 +314,21 @@ class Analyzer
|
|
324
314
|
record = nil
|
325
315
|
list = []
|
326
316
|
|
317
|
+
# header
|
318
|
+
record = [pad_request_name("#{title} Summary"), 'Count', 'Avg',
|
319
|
+
'Std Dev', 'Min', 'Max']
|
320
|
+
list << record.join("\t")
|
321
|
+
|
322
|
+
# all requests
|
323
|
+
times = records.values.flatten
|
324
|
+
record = [times.average, times.standard_deviation, times.min, times.max]
|
325
|
+
record.map! { |v| "%0.3f" % v }
|
326
|
+
record.unshift [pad_request_name('ALL REQUESTS'), times.size]
|
327
|
+
list << record.join("\t")
|
328
|
+
|
329
|
+
# spacer
|
330
|
+
list << nil
|
331
|
+
|
327
332
|
records.sort_by { |k,v| v.size}.reverse_each do |req, times|
|
328
333
|
record = [times.average, times.standard_deviation,
|
329
334
|
times.min, times.max]
|
@@ -332,18 +337,6 @@ class Analyzer
|
|
332
337
|
list << record.join("\t")
|
333
338
|
end
|
334
339
|
|
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
340
|
return list.join("\n")
|
348
341
|
end
|
349
342
|
|
@@ -372,11 +365,19 @@ class Analyzer
|
|
372
365
|
end
|
373
366
|
|
374
367
|
def longest_request_name # :nodoc:
|
375
|
-
@longest_req
|
368
|
+
return @longest_req if defined? @longest_req
|
369
|
+
|
370
|
+
names = @request_times.keys.map do |name|
|
371
|
+
(name||'Unknown').length + 1 # + : - HACK where does nil come from?
|
372
|
+
end
|
373
|
+
|
374
|
+
@longest_req = names.max
|
375
|
+
|
376
|
+
return @longest_req
|
376
377
|
end
|
377
378
|
|
378
379
|
def pad_request_name(name) # :nodoc:
|
379
|
-
name = name
|
380
|
+
name = (name||'Unknown') + ':' # HACK where does nil come from?
|
380
381
|
name += (' ' * (longest_request_name - name.length))
|
381
382
|
end
|
382
383
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'syslog'
|
2
|
+
require 'logger'
|
2
3
|
|
3
4
|
##
|
4
5
|
# This Logger logs messages to syslogd. Add it to your production environment
|
@@ -56,7 +57,7 @@ require 'syslog'
|
|
56
57
|
class SyslogLogger
|
57
58
|
|
58
59
|
##
|
59
|
-
#
|
60
|
+
# Log level for Logger compatibility.
|
60
61
|
|
61
62
|
attr_accessor :level
|
62
63
|
|
@@ -66,7 +67,7 @@ class SyslogLogger
|
|
66
67
|
SYSLOG = Syslog.open "rails"
|
67
68
|
|
68
69
|
##
|
69
|
-
#
|
70
|
+
# Maps Logger warning types to syslog(3) warning types.
|
70
71
|
|
71
72
|
LOGGER_MAP = {
|
72
73
|
:fatal => :err,
|
@@ -77,17 +78,47 @@ class SyslogLogger
|
|
77
78
|
}
|
78
79
|
|
79
80
|
##
|
80
|
-
#
|
81
|
+
# Maps Logger log levels to their values so we can silence.
|
81
82
|
|
82
|
-
|
83
|
-
|
83
|
+
LOGGER_LEVEL_MAP = {}
|
84
|
+
|
85
|
+
LOGGER_MAP.each_key do |key|
|
86
|
+
LOGGER_LEVEL_MAP[key] = Logger.const_get key.to_s.upcase
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Builds a logging method for level +meth+.
|
91
|
+
|
92
|
+
def self.log_method(meth)
|
93
|
+
eval <<-EOF
|
94
|
+
def #{meth}(message)
|
95
|
+
SYSLOG.#{LOGGER_MAP[meth]} clean(message) if #{LOGGER_LEVEL_MAP[meth]} >= @level
|
96
|
+
end
|
97
|
+
EOF
|
98
|
+
end
|
99
|
+
|
100
|
+
LOGGER_MAP.each_key do |level|
|
101
|
+
log_method level
|
84
102
|
end
|
85
103
|
|
86
104
|
##
|
87
|
-
#
|
105
|
+
# Fill in variables for Logger compatibility.
|
106
|
+
|
107
|
+
def initialize(*args)
|
108
|
+
@level = Logger::DEBUG
|
109
|
+
end
|
88
110
|
|
89
|
-
|
90
|
-
|
111
|
+
##
|
112
|
+
# Allows messages of a particular log level to be ignored temporarily.
|
113
|
+
#
|
114
|
+
# Can you say "Broken Windows"?
|
115
|
+
|
116
|
+
def silence(temporary_level = Logger::ERROR)
|
117
|
+
old_logger_level = @level
|
118
|
+
@level = temporary_level
|
119
|
+
yield
|
120
|
+
ensure
|
121
|
+
@level = old_logger_level
|
91
122
|
end
|
92
123
|
|
93
124
|
private
|
@@ -110,11 +141,9 @@ if __FILE__ == $0 then
|
|
110
141
|
|
111
142
|
message = "message from syslog_logger.rb logged using"
|
112
143
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
logger.error "error #{message} #{SyslogLogger::LOGGER_MAP[:error]}"
|
117
|
-
logger.debug "debug #{message} #{SyslogLogger::LOGGER_MAP[:debug]}"
|
144
|
+
SyslogLogger::LOGGER_MAP.each do |logger_level, syslog_level|
|
145
|
+
logger.send logger_level, "#{logger_level} #{message} #{syslog_level}"
|
146
|
+
end
|
118
147
|
end
|
119
148
|
|
120
149
|
# vim: ts=4 sts=4 sw=4
|
data/test/test_analyzer.rb
CHANGED
@@ -104,9 +104,6 @@ RssController#uber: 2 0.035 0.000 0.035 0.035
|
|
104
104
|
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
105
105
|
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
106
106
|
|
107
|
-
Average Request Time: 0.634
|
108
|
-
Request Time Std Dev: 0.498
|
109
|
-
|
110
107
|
Slowest Request Times:
|
111
108
|
TeamsController#progress took 1.470s
|
112
109
|
|
@@ -121,9 +118,6 @@ RssController#uber: 2 0.008 0.000 0.008 0.008
|
|
121
118
|
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
122
119
|
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
123
120
|
|
124
|
-
Average DB Time: 0.402
|
125
|
-
DB Time Std Dev: 0.394
|
126
|
-
|
127
121
|
Slowest Total DB Times:
|
128
122
|
TeamsController#progress took 1.144s
|
129
123
|
|
@@ -138,9 +132,6 @@ RssController#uber: 2 0.012 0.000 0.012 0.012
|
|
138
132
|
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
139
133
|
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
140
134
|
|
141
|
-
Average Render Time: 0.302
|
142
|
-
Render Time Std Dev: 0.251
|
143
|
-
|
144
135
|
Slowest Total Render Times:
|
145
136
|
PeopleController#view took 0.695s
|
146
137
|
</pre>
|
@@ -205,6 +196,34 @@ EOF
|
|
205
196
|
assert_equal 'test/test.syslog.log', @analyzer.logfile_name
|
206
197
|
end
|
207
198
|
|
199
|
+
def test_longest_request_name
|
200
|
+
assert_equal false, @analyzer.instance_variables.include?('@longest_req')
|
201
|
+
|
202
|
+
request_times = {
|
203
|
+
"ThingsController#view" => [0],
|
204
|
+
"TeamsController#progress" => [1],
|
205
|
+
"RssController#uber" => [0],
|
206
|
+
"PeopleController#progress" => [0],
|
207
|
+
nil => [0],
|
208
|
+
}
|
209
|
+
|
210
|
+
@analyzer.instance_variable_set('@request_times', request_times)
|
211
|
+
|
212
|
+
assert_equal 26, @analyzer.longest_request_name
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_pad_request_name
|
216
|
+
assert_equal 26, @analyzer.longest_request_name
|
217
|
+
assert_equal("PeopleController#view: ",
|
218
|
+
@analyzer.pad_request_name("PeopleController#view"))
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_pad_request_name_nil
|
222
|
+
assert_equal 26, @analyzer.longest_request_name
|
223
|
+
assert_equal("Unknown: ",
|
224
|
+
@analyzer.pad_request_name(nil))
|
225
|
+
end
|
226
|
+
|
208
227
|
def test_process
|
209
228
|
expected_request_times = {
|
210
229
|
"PeopleController#view" => [1.102098, 0.36021],
|
@@ -268,9 +287,6 @@ RssController#uber: 2 0.035 0.000 0.035 0.035
|
|
268
287
|
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
269
288
|
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
270
289
|
|
271
|
-
Average Request Time: 0.634
|
272
|
-
Request Time Std Dev: 0.498
|
273
|
-
|
274
290
|
Slowest Request Times:
|
275
291
|
TeamsController#progress took 1.470s
|
276
292
|
ThingsController#view took 1.260s
|
@@ -294,9 +310,6 @@ RssController#uber: 2 0.008 0.000 0.008 0.008
|
|
294
310
|
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
295
311
|
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
296
312
|
|
297
|
-
Average DB Time: 0.402
|
298
|
-
DB Time Std Dev: 0.394
|
299
|
-
|
300
313
|
Slowest Total DB Times:
|
301
314
|
TeamsController#progress took 1.144s
|
302
315
|
ThingsController#view took 0.914s
|
@@ -320,9 +333,6 @@ RssController#uber: 2 0.012 0.000 0.012 0.012
|
|
320
333
|
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
321
334
|
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
322
335
|
|
323
|
-
Average Render Time: 0.302
|
324
|
-
Render Time Std Dev: 0.251
|
325
|
-
|
326
336
|
Slowest Total Render Times:
|
327
337
|
PeopleController#view took 0.695s
|
328
338
|
PeopleController#progress took 0.604s
|
metadata
CHANGED
@@ -3,8 +3,8 @@ 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.2.
|
7
|
-
date: 2005-05-
|
6
|
+
version: 1.2.1
|
7
|
+
date: 2005-05-16
|
8
8
|
summary: Extracts statistics from Rails production logs
|
9
9
|
require_paths:
|
10
10
|
- lib
|