nbogie-production_log_analyzer 1.5.1.1 → 1.5.1.2

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/.gemtest ADDED
File without changes
data/History.txt CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.5.1.2
2
+
3
+ * Add tool to diff reports, to see what actions got faster or slower, etc.
4
+
1
5
  === 1.5.1.1
2
6
 
3
7
  * Groups by http verb (GET/PUT/POST/DELETE/HEAD)
data/README.txt CHANGED
@@ -138,6 +138,33 @@ In the future, pl_analyze will be able to read from STDIN.
138
138
  TeamsController#progress took 0.000s
139
139
  TeamsController#progress took 0.000s
140
140
 
141
+ There's an experimental report-differ which you can invoke as follows:
142
+
143
+ ruby -Ilib report_differ.rb report_b.txt report_a.txt > report_diff.txt
144
+
145
+ Sample diff output
146
+
147
+ Request_Times_Summary: Count Avg Max
148
+ ALL_REQUESTS +1.4(16515->22909) -2.2(0.405->0.18) -1.6(59.678->37.721)
149
+
150
+ SleepwalkersController#update.PUT.xml +1.4(6249->8793) -1.1(0.079->0.07) -2.7(8.328->3.103)
151
+ SleepwalkersController#update.PUT.csv +1.4(6245->8807) -1.0(0.099->0.097) +1.2(2.536->3.02)
152
+ SleepwalkersController#show.GET +1.4(509->710) -1.2(0.072->0.061) -2.3(3.505->1.504)
153
+ SleepwalkersController#show.GET.json +1.4(496->702) -1.2(0.076->0.064) -7.3(4.874->0.663)
154
+ AccomplicesController#history.GET.csv +1.4(470->680) -3.3(5.35->1.618) -1.5(20.681->13.692)
155
+ WindsController#feeds.GET +1.4(237->320) -1.1(0.201->0.183) +1.5(1.304->1.989)
156
+ ScamsController#show.GET +1.3(236->317) -3.0(11.793->3.869) -1.6(59.678->37.721)
157
+ SleepwalkersController#update.PUT -1.1(9->8) -1.1(0.051->0.047) -1.2(0.09->0.076)
158
+ AccomplicesController#show.GET.xml 1.0(2->2) -1.0(0.102->0.1) -1.0(0.184->0.179)
159
+ ScamsController#map.GET +6.0(2->12) -3.5(1.075->0.305) +1.1(2.008->2.112)
160
+ WindsController#feeds.GET.atom 1.0(1->1) -1.1(0.061->0.058) -1.1(0.061->0.058)
161
+ ScamsController#tag.GET.rss 1.0(1->1) -1.0(0.134->0.129) -1.0(0.134->0.129)
162
+
163
+ Unmatched_Actions:
164
+
165
+ ScamsController#index.GET.json only in report_a.txt
166
+ Api::V1::MisinterpretationsController#destroy.DELETE. only in report_a.txt
167
+
141
168
  == What's missing
142
169
 
143
170
  * More reports
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ Hoe.plugin :email, :perforce # not on minitest yet
8
8
  Hoe.spec 'nbogie-production_log_analyzer' do
9
9
  developer 'Eric Hodel', 'drbrain@segment7.net'
10
10
  self.name = 'nbogie-production_log_analyzer'
11
- self.version = '1.5.1.1'
11
+ self.version = '1.5.1.2'
12
12
 
13
13
  extra_deps << ['rails_analyzer_tools', '>= 1.4.0']
14
14
  end
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+
5
+ require 'report/report_parser'
6
+ require 'report/report_differ'
7
+
8
+ class TestReportDiffer < Test::Unit::TestCase
9
+
10
+ def file_data(filename)
11
+ 'test/example_data/' + filename
12
+ end
13
+
14
+ def setup
15
+ @differ = ReportDiffer.new
16
+ report_filenames = ['report_a', 'report_b'].map do |keyname|
17
+ "test/example_data/#{keyname}.txt"
18
+ end
19
+ create_reports()
20
+ #ReportDiffer.compare_files(report_filenames[0], report_filenames[1])
21
+ end
22
+
23
+
24
+ def test_initialization
25
+ differ = ReportDiffer.new
26
+ end
27
+
28
+ def test_compute_difference_in_values()
29
+ data = [
30
+ #when increasing
31
+ [100, 1000, 10],
32
+ [100, 200, 2],
33
+ [100, 130, 1.3],
34
+ #when same
35
+ [100, 100, 1],
36
+ [0,0, 1],
37
+ #when lessening
38
+ [100, 90, -1.11],
39
+ [100, 50, -2],
40
+ [100, 10, -10],
41
+ #when one number is zero - not sure what we should return here.
42
+ [0.00, 1, 999999],
43
+ [1, 0.00, -999999],
44
+ ]
45
+ data.each do |group|
46
+ va, vb, expected = group
47
+ actual = @differ.compute_difference_in_values(va, vb)
48
+ assert_equal(expected, actual, "for #{va}->#{vb}")
49
+ end
50
+ end
51
+
52
+
53
+ def test_compare
54
+ threshold = 1.2
55
+ actual=@differ.compare(@report_a, @report_b, threshold)
56
+ assert_not_nil actual
57
+ expected = {
58
+ :summary_diff=>
59
+ {
60
+ :diff_count=>{:change => -1.11, :from => 100, :to => 90},
61
+ :diff_avg_time=>{:change => 1.5, :from => 10, :to => 15},
62
+ :diff_min_time=>{:change => 1, :from => 0.1, :to => 0.1},
63
+ :diff_max_time=>{:change => 2.0, :from => 20.0, :to => 40.0},
64
+ :diff_std_dev=>{:change => 3.0, :from => 2.0, :to => 6.0}},
65
+ :request_diffs=>
66
+ {"MyCon#MyAc.get.xml"=>
67
+ {
68
+ :diff_count=>{:change => 1.1, :from => 100, :to => 110},
69
+ :diff_avg_time=>{:change => 1.2, :from => 100, :to => 120},
70
+ :diff_std_dev=>{:change => 1.3, :from => 100, :to => 130},
71
+ :diff_min_time=>{:change => 1.4, :from => 100, :to => 140},
72
+ :diff_max_time=>{:change => 1.5, :from => 100, :to => 150} }},
73
+ :unmatched_actions => [],
74
+ :threshold => threshold
75
+ }
76
+
77
+
78
+ assert_equal(expected, actual)
79
+
80
+ ra1 = Request.create('MyCon','MyAc2',600,1,1,1,1)
81
+ rb1 = Request.create('MyCon','MyAc2',610,1,1,1,1)
82
+ ra2 = Request.create('MyCon','MyAc3',50,1,1,1,1)
83
+ rb2 = Request.create('MyCon','MyAc3',50,1,1,1,1)
84
+ @report_a.requests << ra1 << ra2
85
+ @report_b.requests << rb1 << rb2
86
+ assert_equal 3, @report_a.requests.size
87
+
88
+ actual=@differ.compare(@report_a, @report_b, threshold)
89
+ end
90
+ def test_prepare_report()
91
+ diff_data = @differ.compare(@report_a, @report_b)
92
+ report_text = @differ.prepare_report(diff_data)
93
+ #TODO: check report text as as we expect
94
+ ##puts report_text
95
+ end
96
+
97
+ def test_matched_requests_values_ab
98
+ matches = @differ.find_matched_actions(@report_a, @report_b)
99
+ assert_equal 1, matches.size
100
+ assert_equal [100, 110], matches.first.values_ab(:count)
101
+ assert_equal [100, 120], matches.first.values_ab(:avg_time)
102
+ assert_equal [100, 130], matches.first.values_ab(:std_dev)
103
+ assert_equal [100, 140], matches.first.values_ab(:min_time)
104
+ assert_equal [100, 150], matches.first.values_ab(:max_time)
105
+ end
106
+
107
+ def test_find_matched_actions
108
+ matches = @differ.find_matched_actions(@report_a, @report_b)
109
+ assert_equal 1, matches.size
110
+ the_match=matches.first
111
+ assert_equal [@report_a.requests.first, @report_b.requests.first], [the_match.request1, the_match.request2]
112
+
113
+ #with one of the reports having NO requests
114
+ @report_a.requests.clear
115
+ assert_equal 0, @differ.find_matched_actions(@report_a, @report_b).size
116
+ end
117
+
118
+ def test_find_unmatched_actions
119
+ #initially, should return empty list - all match
120
+ assert_equal [], @differ.find_unmatched_actions(@report_a, @report_b)
121
+ #add a request to only one report - should find it
122
+ odd_req = Request.create('MyCon','UniqueAction',110,120,130,140,150)
123
+ @report_a.requests << odd_req
124
+ unmatcheds = @differ.find_unmatched_actions(@report_a, @report_b)
125
+ assert_equal 1, unmatcheds.size
126
+ assert_equal 'UniqueAction', unmatcheds.first.request.action
127
+ assert_equal @report_a, unmatcheds.first.report
128
+
129
+ #add another request (only to rep b)
130
+ odd_req2 = Request.create('UniqueCon','MyAc',110,120,130,140,150)
131
+ @report_b.requests << odd_req2
132
+ unmatcheds = @differ.find_unmatched_actions(@report_a, @report_b)
133
+ assert_equal 2, unmatcheds.size
134
+ assert_equal 'UniqueAction', unmatcheds.first.request.action
135
+ assert_equal @report_a, unmatcheds.first.report
136
+ assert_equal 'UniqueCon', unmatcheds.last.request.controller
137
+ assert_equal @report_b, unmatcheds.last.report
138
+ end
139
+
140
+ def test_compare_summaries
141
+ actual=@differ.compare_summaries(@report_a, @report_b)
142
+ assert_equal(
143
+ {
144
+ :diff_count=>{:change => -1.11, :from => 100, :to => 90},
145
+ :diff_avg_time=>{:change => 1.5, :from => 10, :to => 15},
146
+ :diff_std_dev=>{:change => 3.0, :from => 2.0, :to => 6.0},
147
+ :diff_min_time=>{:change => 1, :from => 0.1, :to => 0.1},
148
+ :diff_max_time=>{:change => 2.0, :from => 20.0, :to => 40.0},
149
+ }, actual)
150
+ end
151
+
152
+ #populate @report_a, @report_b
153
+ def create_reports
154
+ ra = Report.new
155
+ ra.summary.count=100
156
+ ra.summary.avg_time=10.0
157
+ ra.summary.std_dev=2.0
158
+ ra.summary.min_time=0.1
159
+ ra.summary.max_time=20.0
160
+
161
+ ca1 = Request.create('MyCon','MyAc',100,100,100,100,100, {:verb=>'get',:format =>'xml'})
162
+ cb1 = Request.create('MyCon','MyAc',110,120,130,140,150, {:verb=>'get',:format =>'xml'})
163
+ ra.requests << ca1
164
+
165
+ rb = Report.new
166
+ rb.summary.count=90
167
+ rb.summary.avg_time=15.0
168
+ rb.summary.std_dev=6
169
+ rb.summary.min_time=0.1
170
+ rb.summary.max_time=40.0
171
+ rb.requests << cb1
172
+ @report_a = ra
173
+ @report_b = rb
174
+ end
175
+
176
+
177
+ end
178
+
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+
5
+ require 'report/report_parser'
6
+
7
+ class TestReportParser < Test::Unit::TestCase
8
+
9
+ def file_data(filename)
10
+ 'test/example_data/' + filename
11
+ end
12
+
13
+ def setup
14
+ @parser = ReportParser.new
15
+ end
16
+
17
+ def test_initialization
18
+ parser = ReportParser.new
19
+ end
20
+
21
+ def test_can_parse_report
22
+ content = File.read(file_data('example.txt'))
23
+
24
+ result = @parser.parse("my report name", content)
25
+ assert_not_nil(result)
26
+ assert_equal("my report name", result.name)
27
+ assert_equal(8, result.requests.size)
28
+ expected_controllers= %w(
29
+ FooController
30
+ FooController
31
+ FooController
32
+ FooController
33
+ BarController
34
+ HealthController
35
+ QuxController
36
+ UsersController)
37
+ assert_equal(expected_controllers, result.requests.map{|rq| rq.controller})
38
+ end
39
+
40
+ def test_can_extract_from_all_requests
41
+ content = File.read(file_data('example.txt'))
42
+ result = @parser.parse("whatever", content)
43
+ assert_equal(11830,result.summary.count)
44
+ assert_equal(0.185,result.summary.avg_time)
45
+ assert_equal(0.212,result.summary.std_dev)
46
+ assert_equal(0.001,result.summary.min_time)
47
+ assert_equal(3.553,result.summary.max_time)
48
+ end
49
+
50
+ def test_can_parse_a_request
51
+ line = "ApiFooController#update.PUT.xml: 3557 0.144 0.137 0.059 3.212"
52
+ request = @parser.parse_request(line)
53
+ assert_equal("ApiFooController",request.controller)
54
+ assert_equal("update",request.action)
55
+ assert_equal("PUT",request.verb)
56
+ assert_equal("xml",request.format)
57
+ assert_equal(3557,request.count)
58
+ assert_equal(0.144,request.avg_time)
59
+ assert_equal(0.137,request.std_dev)
60
+ assert_equal(0.059,request.min_time)
61
+ assert_equal(3.212,request.max_time)
62
+ end
63
+
64
+ def test_should_normalize_request_format_to_lowercase
65
+ line = "ApiFooController#update.PUT.XmL: 3557 0.144 0.137 0.059 3.212"
66
+ request = @parser.parse_request(line)
67
+ assert_equal("xml",request.format)
68
+ end
69
+
70
+ def test_should_normalize_request_verb_to_uppercase
71
+ line = "ApiFooController#update.puT.xml: 3557 0.144 0.137 0.059 3.212"
72
+ request = @parser.parse_request(line)
73
+ assert_equal("PUT",request.verb)
74
+ end
75
+
76
+ def test_should_parse_request_having_no_format
77
+ line = "ApiFooController#update.GET: 3557 0.144 0.137 0.059 3.212"
78
+ request = @parser.parse_request(line)
79
+ assert_equal("GET",request.verb)
80
+ assert_nil(request.format)
81
+ assert_equal(0.144,request.avg_time)
82
+ end
83
+
84
+ def test_can_parse_a_request_having_module_named_controller_name
85
+ line = "Api::V1::FooController#show.GET: 11707 0.107 0.263 0.015 19.075"
86
+ request = @parser.parse_request(line)
87
+ assert_equal("Api::V1::FooController",request.controller)
88
+ end
89
+
90
+ def test_should_parse_a_few_lines
91
+ should_parse "QuxController#index.GET.rss: 5 0.241 0.078 0.121 0.367"
92
+ end
93
+
94
+ def should_parse(line)
95
+ @parser.parse_request(line)
96
+ end
97
+
98
+ end
99
+
100
+ class TestRequest < Test::Unit::TestCase
101
+ def test_remembers_its_values
102
+ r = Request.new
103
+ r.controller = "somecontroller"
104
+ r.action = "someaction"
105
+ r.verb = "GET"
106
+ r.format = "xml"
107
+ r.count = 100
108
+ r.avg_time = 1.123
109
+ r.std_dev = 0.22
110
+ r.min_time = 3.33
111
+ r.max_time = 10.10
112
+ assert_equal("somecontroller",r.controller)
113
+ assert_equal("someaction",r.action)
114
+ assert_equal("GET",r.verb)
115
+ assert_equal("xml",r.format)
116
+ assert_equal(3.33,r.min_time)
117
+ assert_equal(10.10,r.max_time)
118
+ assert_equal(1.123,r.avg_time)
119
+ assert_equal(0.22,r.std_dev)
120
+ end
121
+
122
+ def test_create
123
+ req = Request.create('Con','Ac',1,2,3,4,5, {:verb=>'get',:format =>'xml'})
124
+ assert_equal('Con', req.controller)
125
+ assert_equal('Ac', req.action)
126
+ assert_equal(1, req.count)
127
+ assert_equal(2, req.avg_time)
128
+ assert_equal(3, req.std_dev)
129
+ assert_equal(4, req.min_time)
130
+ assert_equal(5, req.max_time)
131
+ end
132
+
133
+ def test_should_not_fixup_already_fixed_up_name
134
+ r = Request.new
135
+ r.controller = "Api::V1::GraultController"
136
+ r.fixup_controller_name!
137
+ assert_equal("Api::V1::GraultController",r.controller)
138
+ end
139
+ end
140
+
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nbogie-production_log_analyzer
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 119
5
+ prerelease:
5
6
  segments:
6
7
  - 1
7
8
  - 5
8
9
  - 1
9
- - 1
10
- version: 1.5.1.1
10
+ - 2
11
+ version: 1.5.1.2
11
12
  platform: ruby
12
13
  authors:
13
14
  - Eric Hodel
@@ -15,16 +16,17 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2010-06-10 00:00:00 +01:00
19
- default_executable:
19
+ date: 2011-07-07 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: rails_analyzer_tools
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 7
28
30
  segments:
29
31
  - 1
30
32
  - 4
@@ -33,33 +35,21 @@ dependencies:
33
35
  type: :runtime
34
36
  version_requirements: *id001
35
37
  - !ruby/object:Gem::Dependency
36
- name: rubyforge
38
+ name: hoe
37
39
  prerelease: false
38
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
39
42
  requirements:
40
43
  - - ">="
41
44
  - !ruby/object:Gem::Version
45
+ hash: 35
42
46
  segments:
43
47
  - 2
44
- - 0
48
+ - 9
45
49
  - 4
46
- version: 2.0.4
50
+ version: 2.9.4
47
51
  type: :development
48
52
  version_requirements: *id002
49
- - !ruby/object:Gem::Dependency
50
- name: hoe
51
- prerelease: false
52
- requirement: &id003 !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- segments:
57
- - 2
58
- - 6
59
- - 0
60
- version: 2.6.0
61
- type: :development
62
- version_requirements: *id003
63
53
  description: |-
64
54
  production_log_analyzer lets you find out which actions on a Rails
65
55
  site are slowing you down.
@@ -99,7 +89,9 @@ files:
99
89
  - test/test_action_grep.rb
100
90
  - test/test_analyzer.rb
101
91
  - test/test_parser.rb
102
- has_rdoc: true
92
+ - test/test_report_differ.rb
93
+ - test/test_report_parser.rb
94
+ - .gemtest
103
95
  homepage: http://seattlerb.rubyforge.org/production_log_analyzer
104
96
  licenses: []
105
97
 
@@ -110,27 +102,33 @@ rdoc_options:
110
102
  require_paths:
111
103
  - lib
112
104
  required_ruby_version: !ruby/object:Gem::Requirement
105
+ none: false
113
106
  requirements:
114
107
  - - ">="
115
108
  - !ruby/object:Gem::Version
109
+ hash: 3
116
110
  segments:
117
111
  - 0
118
112
  version: "0"
119
113
  required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
120
115
  requirements:
121
116
  - - ">="
122
117
  - !ruby/object:Gem::Version
118
+ hash: 3
123
119
  segments:
124
120
  - 0
125
121
  version: "0"
126
122
  requirements: []
127
123
 
128
124
  rubyforge_project: nbogie-production_log_analyzer
129
- rubygems_version: 1.3.6
125
+ rubygems_version: 1.8.5
130
126
  signing_key:
131
127
  specification_version: 3
132
128
  summary: production_log_analyzer lets you find out which actions on a Rails site are slowing you down
133
129
  test_files:
134
130
  - test/test_parser.rb
135
131
  - test/test_analyzer.rb
132
+ - test/test_report_differ.rb
136
133
  - test/test_action_grep.rb
134
+ - test/test_report_parser.rb