erkki-production_log_analyzer 2009022401
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/History.txt +34 -0
- data/LICENSE.txt +27 -0
- data/Manifest.txt +18 -0
- data/README.txt +147 -0
- data/Rakefile +17 -0
- data/bin/action_errors +46 -0
- data/bin/action_grep +19 -0
- data/bin/pl_analyze +36 -0
- data/lib/production_log/action_grep.rb +42 -0
- data/lib/production_log/analyzer.rb +406 -0
- data/lib/production_log/parser.rb +178 -0
- data/test/test.syslog.0.14.x.log +5 -0
- data/test/test.syslog.1.2.shortname.log +5 -0
- data/test/test.syslog.empty.log +2 -0
- data/test/test.syslog.log +258 -0
- data/test/test_action_grep.rb +66 -0
- data/test/test_analyzer.rb +418 -0
- data/test/test_parser.rb +297 -0
- metadata +97 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
require 'production_log/action_grep'
|
6
|
+
|
7
|
+
class TestActionGrep < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@syslog_file_name = File.expand_path(File.join(File.dirname(__FILE__),
|
11
|
+
'test.syslog.log'))
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_module_grep
|
15
|
+
old_stdout = $stdout.dup
|
16
|
+
stdout = StringIO.new
|
17
|
+
$stdout = stdout
|
18
|
+
|
19
|
+
ActionGrep.grep 'RssController', @syslog_file_name
|
20
|
+
|
21
|
+
stdout.rewind
|
22
|
+
|
23
|
+
lines = stdout.readlines
|
24
|
+
|
25
|
+
assert_equal 19, lines.length
|
26
|
+
|
27
|
+
ensure
|
28
|
+
$stdout = old_stdout
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_module_grep_arguments
|
32
|
+
file = Tempfile.new File.basename(__FILE__)
|
33
|
+
|
34
|
+
assert_raises ArgumentError do
|
35
|
+
ActionGrep.grep 'Foo_Controller', '/tmp/no_such_file/no_really/'
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_raises ArgumentError do
|
39
|
+
ActionGrep.grep 'FooController#5', '/tmp/no_such_file/no_really/'
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_raises ArgumentError do
|
43
|
+
ActionGrep.grep '5', '/tmp/no_such_file/no_really/'
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_raises ArgumentError do
|
47
|
+
ActionGrep.grep 'FooController', '/tmp/no_such_file/no_really'
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_nothing_raised do
|
51
|
+
ActionGrep.grep 'FooController', file.path
|
52
|
+
ActionGrep.grep 'FooController5', file.path
|
53
|
+
ActionGrep.grep 'FooController#action', file.path
|
54
|
+
ActionGrep.grep 'FooController#action_thingy', file.path
|
55
|
+
ActionGrep.grep 'FooController#action_thingy5', file.path
|
56
|
+
ActionGrep.grep 'FooController5#action', file.path
|
57
|
+
ActionGrep.grep 'FooController5#action_thingy', file.path
|
58
|
+
ActionGrep.grep 'FooController5#action_thingy5', file.path
|
59
|
+
end
|
60
|
+
|
61
|
+
ensure
|
62
|
+
file.close
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,418 @@
|
|
1
|
+
$TESTING = true
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
require 'production_log/analyzer'
|
6
|
+
|
7
|
+
class TestEnumerable < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def test_sum
|
10
|
+
assert_equal 45, (1..9).sum
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_average
|
14
|
+
# Ranges don't have a length
|
15
|
+
assert_in_delta 5.0, (1..9).to_a.average, 0.01
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_sample_variance
|
19
|
+
assert_in_delta 6.6666, (1..9).to_a.sample_variance, 0.0001
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_standard_deviation
|
23
|
+
assert_in_delta 2.5819, (1..9).to_a.standard_deviation, 0.0001
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class TestSizedList < Test::Unit::TestCase
|
29
|
+
|
30
|
+
def setup
|
31
|
+
@list = SizedList.new 10 do |arr,|
|
32
|
+
arr.delete_at 0
|
33
|
+
true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_append
|
38
|
+
assert_equal [], @list.entries
|
39
|
+
|
40
|
+
(1..10).each { |i| @list << i }
|
41
|
+
assert_equal 10, @list.length
|
42
|
+
assert_equal((1..10).to_a, @list.entries)
|
43
|
+
|
44
|
+
@list << 11
|
45
|
+
assert_equal 10, @list.length
|
46
|
+
assert_equal((2..11).to_a, @list.entries)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class TestSlowestTimes < Test::Unit::TestCase
|
52
|
+
|
53
|
+
def setup
|
54
|
+
@list = SlowestTimes.new 10
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_that_it_works
|
58
|
+
expected = []
|
59
|
+
|
60
|
+
10.downto(1) do |i|
|
61
|
+
@list << [i, nil]
|
62
|
+
expected << [i, nil]
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal expected, @list.entries
|
66
|
+
|
67
|
+
@list << [11, nil]
|
68
|
+
expected.pop
|
69
|
+
expected.push [11, nil]
|
70
|
+
|
71
|
+
assert_equal 10, @list.length
|
72
|
+
assert_equal expected, @list.entries
|
73
|
+
|
74
|
+
@list << [0, nil]
|
75
|
+
|
76
|
+
assert_equal expected, @list.entries
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
class TestAnalyzer < Test::Unit::TestCase
|
82
|
+
|
83
|
+
def setup
|
84
|
+
@analyzer = Analyzer.new "#{File.dirname(__FILE__)}/test.syslog.log"
|
85
|
+
@analyzer.process
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_self_email
|
89
|
+
email = Analyzer.email("#{File.dirname(__FILE__)}/test.syslog.log", 'devnull@robotcoop.com',
|
90
|
+
nil, 1)
|
91
|
+
expected = <<-EOF
|
92
|
+
Subject: pl_analyze
|
93
|
+
To: devnull@robotcoop.com
|
94
|
+
Content-Type: text/html
|
95
|
+
|
96
|
+
<pre>Request Times Summary: Count Avg Std Dev Min Max
|
97
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
98
|
+
|
99
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
100
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
101
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
102
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
103
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
104
|
+
|
105
|
+
Slowest Request Times:
|
106
|
+
\tTeamsController#progress took 1.470s
|
107
|
+
|
108
|
+
------------------------------------------------------------------------
|
109
|
+
|
110
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
111
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
112
|
+
|
113
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
114
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
115
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
116
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
117
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
118
|
+
|
119
|
+
Slowest Total DB Times:
|
120
|
+
\tTeamsController#progress took 1.144s
|
121
|
+
|
122
|
+
------------------------------------------------------------------------
|
123
|
+
|
124
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
125
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
126
|
+
|
127
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
128
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
129
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
130
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
131
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
132
|
+
|
133
|
+
Slowest Total Render Times:
|
134
|
+
\tPeopleController#view took 0.695s
|
135
|
+
</pre>
|
136
|
+
EOF
|
137
|
+
|
138
|
+
assert_equal expected, email
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_self_envelope
|
142
|
+
expected = [
|
143
|
+
"Subject: pl_analyze",
|
144
|
+
"To: devnull@example.com",
|
145
|
+
"Content-Type: text/html"
|
146
|
+
]
|
147
|
+
|
148
|
+
assert_equal expected, Analyzer.envelope('devnull@example.com')
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_self_envelope_subject
|
152
|
+
expected = [
|
153
|
+
"Subject: happy fancy boom",
|
154
|
+
"To: devnull@example.com",
|
155
|
+
"Content-Type: text/html"
|
156
|
+
]
|
157
|
+
|
158
|
+
assert_equal(expected,
|
159
|
+
Analyzer.envelope('devnull@example.com', 'happy fancy boom'))
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_average_db_time
|
163
|
+
assert_in_delta 0.4023761, @analyzer.average_db_time, 0.0000001
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_average_render_time
|
167
|
+
assert_in_delta 0.3015584, @analyzer.average_render_time, 0.0000001
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_average_request_time
|
171
|
+
assert_in_delta 0.6338176, @analyzer.average_request_time, 0.0000001
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_db_time_std_dev
|
175
|
+
assert_in_delta 0.3941380, @analyzer.db_time_std_dev, 0.0000001
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_db_times_summary
|
179
|
+
expected = <<EOF.strip
|
180
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
181
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
182
|
+
|
183
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
184
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
185
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
186
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
187
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
188
|
+
EOF
|
189
|
+
|
190
|
+
assert_equal expected, @analyzer.db_times_summary
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_empty_syslog
|
194
|
+
analyzer = Analyzer.new "#{File.dirname(__FILE__)}/test.syslog.empty.log"
|
195
|
+
assert_nothing_raised do
|
196
|
+
analyzer.process
|
197
|
+
analyzer.report(1)
|
198
|
+
end
|
199
|
+
assert_equal "No requests to analyze", analyzer.report(1)
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_logfile_name
|
203
|
+
assert_equal "#{File.dirname(__FILE__)}/test.syslog.log", @analyzer.logfile_name
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_longest_request_name
|
207
|
+
assert_equal false, @analyzer.instance_variables.include?('@longest_req')
|
208
|
+
|
209
|
+
request_times = {
|
210
|
+
"ThingsController#view" => [0],
|
211
|
+
"TeamsController#progress" => [1],
|
212
|
+
"RssController#uber" => [0],
|
213
|
+
"PeopleController#progress" => [0],
|
214
|
+
nil => [0],
|
215
|
+
}
|
216
|
+
|
217
|
+
@analyzer.instance_variable_set('@request_times', request_times)
|
218
|
+
|
219
|
+
assert_equal 26, @analyzer.longest_request_name
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_pad_request_name
|
223
|
+
assert_equal 26, @analyzer.longest_request_name
|
224
|
+
assert_equal("PeopleController#view: ",
|
225
|
+
@analyzer.pad_request_name("PeopleController#view"))
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_pad_request_name_nil
|
229
|
+
assert_equal 26, @analyzer.longest_request_name
|
230
|
+
assert_equal("Unknown: ",
|
231
|
+
@analyzer.pad_request_name(nil))
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_pad_request_name_short
|
235
|
+
analyzer = Analyzer.new "#{File.dirname(__FILE__)}/test.syslog.1.2.shortname.log"
|
236
|
+
analyzer.process
|
237
|
+
longer_request_name_value = " " * (analyzer.longest_request_name + 1)
|
238
|
+
assert_nothing_raised do
|
239
|
+
analyzer.pad_request_name(longer_request_name_value)
|
240
|
+
end
|
241
|
+
assert_equal longer_request_name_value + ":", analyzer.pad_request_name(longer_request_name_value)
|
242
|
+
end
|
243
|
+
|
244
|
+
def test_process
|
245
|
+
expected_request_times = {
|
246
|
+
"PeopleController#view" => [1.102098, 0.36021],
|
247
|
+
"ThingsController#view" => [0.396183, 0.49176, 1.259728],
|
248
|
+
"TeamsController#progress" => [1.469788, 0.211973],
|
249
|
+
"RssController#uber" => [0.034519, 0.034519],
|
250
|
+
"PeopleController#progress" => [0.977398, 0]
|
251
|
+
}
|
252
|
+
assert_equal expected_request_times, @analyzer.request_times
|
253
|
+
|
254
|
+
expected_db_times = {
|
255
|
+
"PeopleController#view" => [0.486258, 0.189119],
|
256
|
+
"ThingsController#view" => [0.122158, 0.172767, 0.914192],
|
257
|
+
"TeamsController#progress" => [1.143577, 0.149357],
|
258
|
+
"RssController#uber" => [0.007962, 0.007962],
|
259
|
+
"PeopleController#progress" => [0.830409, 0]
|
260
|
+
}
|
261
|
+
assert_equal expected_db_times, @analyzer.db_times
|
262
|
+
|
263
|
+
expected_render_times = {
|
264
|
+
"PeopleController#view" => [0.695476, 0.277921],
|
265
|
+
"ThingsController#view" => [0.107987, 0.197126, 0.505973],
|
266
|
+
"TeamsController#progress" => [0, 0],
|
267
|
+
"RssController#uber" => [0.01177, 0.01177],
|
268
|
+
"PeopleController#progress" => [0.604444, 0]
|
269
|
+
}
|
270
|
+
assert_equal expected_render_times, @analyzer.render_times
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_render_time_std_dev
|
274
|
+
assert_in_delta 0.2513925, @analyzer.render_time_std_dev, 0.0000001
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_render_times_summary
|
278
|
+
expected = <<EOF.strip
|
279
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
280
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
281
|
+
|
282
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
283
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
284
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
285
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
286
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
287
|
+
EOF
|
288
|
+
|
289
|
+
assert_equal expected, @analyzer.render_times_summary
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_report
|
293
|
+
expected = <<-EOF
|
294
|
+
Request Times Summary: Count Avg Std Dev Min Max
|
295
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
296
|
+
|
297
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
298
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
299
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
300
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
301
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
302
|
+
|
303
|
+
Slowest Request Times:
|
304
|
+
\tTeamsController#progress took 1.470s
|
305
|
+
\tThingsController#view took 1.260s
|
306
|
+
\tPeopleController#view took 1.102s
|
307
|
+
\tPeopleController#progress took 0.977s
|
308
|
+
\tThingsController#view took 0.492s
|
309
|
+
\tThingsController#view took 0.396s
|
310
|
+
\tPeopleController#view took 0.360s
|
311
|
+
\tTeamsController#progress took 0.212s
|
312
|
+
\tRssController#uber took 0.035s
|
313
|
+
\tRssController#uber took 0.035s
|
314
|
+
|
315
|
+
------------------------------------------------------------------------
|
316
|
+
|
317
|
+
DB Times Summary: Count Avg Std Dev Min Max
|
318
|
+
ALL REQUESTS: 11 0.366 0.393 0.000 1.144
|
319
|
+
|
320
|
+
ThingsController#view: 3 0.403 0.362 0.122 0.914
|
321
|
+
TeamsController#progress: 2 0.646 0.497 0.149 1.144
|
322
|
+
RssController#uber: 2 0.008 0.000 0.008 0.008
|
323
|
+
PeopleController#progress: 2 0.415 0.415 0.000 0.830
|
324
|
+
PeopleController#view: 2 0.338 0.149 0.189 0.486
|
325
|
+
|
326
|
+
Slowest Total DB Times:
|
327
|
+
\tTeamsController#progress took 1.144s
|
328
|
+
\tThingsController#view took 0.914s
|
329
|
+
\tPeopleController#progress took 0.830s
|
330
|
+
\tPeopleController#view took 0.486s
|
331
|
+
\tPeopleController#view took 0.189s
|
332
|
+
\tThingsController#view took 0.173s
|
333
|
+
\tTeamsController#progress took 0.149s
|
334
|
+
\tThingsController#view took 0.122s
|
335
|
+
\tRssController#uber took 0.008s
|
336
|
+
\tRssController#uber took 0.008s
|
337
|
+
|
338
|
+
------------------------------------------------------------------------
|
339
|
+
|
340
|
+
Render Times Summary: Count Avg Std Dev Min Max
|
341
|
+
ALL REQUESTS: 11 0.219 0.253 0.000 0.695
|
342
|
+
|
343
|
+
ThingsController#view: 3 0.270 0.171 0.108 0.506
|
344
|
+
TeamsController#progress: 2 0.000 0.000 0.000 0.000
|
345
|
+
RssController#uber: 2 0.012 0.000 0.012 0.012
|
346
|
+
PeopleController#progress: 2 0.302 0.302 0.000 0.604
|
347
|
+
PeopleController#view: 2 0.487 0.209 0.278 0.695
|
348
|
+
|
349
|
+
Slowest Total Render Times:
|
350
|
+
\tPeopleController#view took 0.695s
|
351
|
+
\tPeopleController#progress took 0.604s
|
352
|
+
\tThingsController#view took 0.506s
|
353
|
+
\tPeopleController#view took 0.278s
|
354
|
+
\tThingsController#view took 0.197s
|
355
|
+
\tThingsController#view took 0.108s
|
356
|
+
\tRssController#uber took 0.012s
|
357
|
+
\tRssController#uber took 0.012s
|
358
|
+
\tTeamsController#progress took 0.000s
|
359
|
+
\tTeamsController#progress took 0.000s
|
360
|
+
EOF
|
361
|
+
|
362
|
+
assert_equal expected, @analyzer.report(10)
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_request_time_std_dev
|
366
|
+
assert_in_delta 0.4975667, @analyzer.request_time_std_dev, 0.0000001
|
367
|
+
end
|
368
|
+
|
369
|
+
def test_request_times_summary
|
370
|
+
expected = <<EOF.strip
|
371
|
+
Request Times Summary: Count Avg Std Dev Min Max
|
372
|
+
ALL REQUESTS: 11 0.576 0.508 0.000 1.470
|
373
|
+
|
374
|
+
ThingsController#view: 3 0.716 0.387 0.396 1.260
|
375
|
+
TeamsController#progress: 2 0.841 0.629 0.212 1.470
|
376
|
+
RssController#uber: 2 0.035 0.000 0.035 0.035
|
377
|
+
PeopleController#progress: 2 0.489 0.489 0.000 0.977
|
378
|
+
PeopleController#view: 2 0.731 0.371 0.360 1.102
|
379
|
+
EOF
|
380
|
+
|
381
|
+
assert_equal expected, @analyzer.request_times_summary
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_slowest_db_times
|
385
|
+
times = @analyzer.slowest_db_times 3
|
386
|
+
assert_equal 3, times.length
|
387
|
+
expected = [
|
388
|
+
[1.143577, "TeamsController#progress"],
|
389
|
+
[0.914192, "ThingsController#view"],
|
390
|
+
[0.830409, "PeopleController#progress"]
|
391
|
+
]
|
392
|
+
assert_equal expected, times
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_slowest_request_times
|
396
|
+
times = @analyzer.slowest_request_times 3
|
397
|
+
assert_equal 3, times.length
|
398
|
+
expected = [
|
399
|
+
[1.469788, "TeamsController#progress"],
|
400
|
+
[1.259728, "ThingsController#view"],
|
401
|
+
[1.102098, "PeopleController#view"]
|
402
|
+
]
|
403
|
+
assert_equal expected, times
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_slowest_render_times
|
407
|
+
times = @analyzer.slowest_render_times 3
|
408
|
+
assert_equal 3, times.length
|
409
|
+
expected = [
|
410
|
+
[0.695476, "PeopleController#view"],
|
411
|
+
[0.604444, "PeopleController#progress"],
|
412
|
+
[0.505973, "ThingsController#view"]
|
413
|
+
]
|
414
|
+
assert_equal expected, times
|
415
|
+
end
|
416
|
+
|
417
|
+
end
|
418
|
+
|