miniprofiler 0.1.7.1

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.
Files changed (42) hide show
  1. data/.gitignore +4 -0
  2. data/CHANGELOG +32 -0
  3. data/Gemfile +15 -0
  4. data/Gemfile.lock +64 -0
  5. data/README.md +110 -0
  6. data/Rakefile +40 -0
  7. data/autotest/discover.rb +2 -0
  8. data/lib/mini_profiler/body_add_proxy.rb +45 -0
  9. data/lib/mini_profiler/client_timer_struct.rb +76 -0
  10. data/lib/mini_profiler/config.rb +52 -0
  11. data/lib/mini_profiler/context.rb +10 -0
  12. data/lib/mini_profiler/page_timer_struct.rb +53 -0
  13. data/lib/mini_profiler/profiler.rb +405 -0
  14. data/lib/mini_profiler/profiling_methods.rb +73 -0
  15. data/lib/mini_profiler/request_timer_struct.rb +96 -0
  16. data/lib/mini_profiler/sql_timer_struct.rb +48 -0
  17. data/lib/mini_profiler/storage/abstract_store.rb +27 -0
  18. data/lib/mini_profiler/storage/file_store.rb +108 -0
  19. data/lib/mini_profiler/storage/memory_store.rb +68 -0
  20. data/lib/mini_profiler/storage/redis_store.rb +44 -0
  21. data/lib/mini_profiler/timer_struct.rb +31 -0
  22. data/lib/mini_profiler_rails/railtie.rb +84 -0
  23. data/lib/patches/sql_patches.rb +185 -0
  24. data/lib/rack-mini-profiler.rb +6 -0
  25. data/rack-mini-profiler.gemspec +23 -0
  26. data/spec/components/body_add_proxy_spec.rb +90 -0
  27. data/spec/components/client_timer_struct_spec.rb +165 -0
  28. data/spec/components/file_store_spec.rb +47 -0
  29. data/spec/components/memory_store_spec.rb +40 -0
  30. data/spec/components/page_timer_struct_spec.rb +33 -0
  31. data/spec/components/profiler_spec.rb +126 -0
  32. data/spec/components/redis_store_spec.rb +44 -0
  33. data/spec/components/request_timer_struct_spec.rb +148 -0
  34. data/spec/components/sql_timer_struct_spec.rb +63 -0
  35. data/spec/components/timer_struct_spec.rb +47 -0
  36. data/spec/fixtures/simple_client_request.yml +17 -0
  37. data/spec/fixtures/weird_client_request.yml +13 -0
  38. data/spec/integration/mini_profiler_spec.rb +142 -0
  39. data/spec/spec_helper.rb +31 -0
  40. data/spec/support/expand_each_to_matcher.rb +8 -0
  41. data/test_old/config.ru +41 -0
  42. metadata +155 -0
@@ -0,0 +1,165 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+ require 'yaml'
4
+
5
+ describe Rack::MiniProfiler::ClientTimerStruct do
6
+
7
+ def new_page
8
+ Rack::MiniProfiler::PageTimerStruct.new({})
9
+ end
10
+
11
+ def fixture(name)
12
+ YAML.load(File.open(File.dirname(__FILE__) + "/../fixtures/#{name}.yml"))
13
+ end
14
+
15
+ before do
16
+ @client = Rack::MiniProfiler::ClientTimerStruct.new
17
+ end
18
+
19
+ it 'defaults to no attributes' do
20
+ ::JSON.parse(@client.to_json).should be_empty
21
+ end
22
+
23
+ describe 'init_from_form_data' do
24
+
25
+ describe 'without a form' do
26
+ before do
27
+ @client.init_from_form_data({}, new_page)
28
+ end
29
+
30
+ it 'has no Timings' do
31
+ @client['Timings'].should be_nil
32
+ end
33
+
34
+ it 'has no RedirectCount' do
35
+ @client['RedirectCount'].should be_nil
36
+ end
37
+ end
38
+
39
+ describe 'with a simple request' do
40
+ before do
41
+ @client.init_from_form_data(fixture(:simple_client_request), new_page)
42
+ end
43
+
44
+ it 'has the correct RedirectCount' do
45
+ @client['RedirectCount'].should == 1
46
+ end
47
+
48
+ it 'has Timings' do
49
+ @client['Timings'].should_not be_empty
50
+ end
51
+
52
+ describe "bob.js" do
53
+ before do
54
+ @bob = @client['Timings'].find {|t| t["Name"] == "bob.js"}
55
+ end
56
+
57
+ it 'has it in the timings' do
58
+ @bob.should_not be_nil
59
+ end
60
+
61
+ it 'has the correct duration' do
62
+ @bob["Duration"].should == 6
63
+ end
64
+
65
+ end
66
+
67
+ describe "Navigation" do
68
+ before do
69
+ @nav = @client['Timings'].find {|t| t["Name"] == "Navigation"}
70
+ end
71
+
72
+ it 'has a Timing for the Navigation' do
73
+ @nav.should_not be_nil
74
+ end
75
+
76
+ it 'has the correct start' do
77
+ @nav['Start'].should == 0
78
+ end
79
+
80
+ it 'has the correct duration' do
81
+ @nav['Duration'].should == 16
82
+ end
83
+ end
84
+
85
+ describe "Simple" do
86
+ before do
87
+ @simple = @client['Timings'].find {|t| t["Name"] == "Simple"}
88
+ end
89
+
90
+ it 'has a Timing for the Simple' do
91
+ @simple.should_not be_nil
92
+ end
93
+
94
+ it 'has the correct start' do
95
+ @simple['Start'].should == 1
96
+ end
97
+
98
+ it 'has the correct duration' do
99
+ @simple['Duration'].should == 10
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ describe 'with some odd values' do
106
+ before do
107
+ @client.init_from_form_data(fixture(:weird_client_request), new_page)
108
+ end
109
+
110
+ it 'has the correct RedirectCount' do
111
+ @client['RedirectCount'].should == 99
112
+ end
113
+
114
+ it 'has Timings' do
115
+ @client['Timings'].should_not be_empty
116
+ end
117
+
118
+ it 'has no timing when the start is before Navigation' do
119
+ @client['Timings'].find {|t| t["Name"] == "Previous"}.should be_nil
120
+ end
121
+
122
+ describe "weird" do
123
+ before do
124
+ @weird = @client['Timings'].find {|t| t["Name"] == "Weird"}
125
+ end
126
+
127
+ it 'has a Timing for the Weird' do
128
+ @weird.should_not be_nil
129
+ end
130
+
131
+ it 'has the correct start' do
132
+ @weird['Start'].should == 11
133
+ end
134
+
135
+ it 'has a 0 duration because start time is greater than end time' do
136
+ @weird['Duration'].should == 0
137
+ end
138
+ end
139
+
140
+ describe "differentFormat" do
141
+ before do
142
+ @diff = @client['Timings'].find {|t| t["Name"] == "differentFormat"}
143
+ end
144
+
145
+ it 'has a Timing for the differentFormat' do
146
+ @diff.should_not be_nil
147
+ end
148
+
149
+ it 'has the correct start' do
150
+ @diff['Start'].should == 1
151
+ end
152
+
153
+ it 'has a -1 duration because the format was different' do
154
+ @diff['Duration'].should == -1
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+
161
+
162
+ end
163
+
164
+
165
+ end
@@ -0,0 +1,47 @@
1
+
2
+ require 'spec_helper'
3
+ require 'rack-mini-profiler'
4
+ require 'mini_profiler/page_timer_struct'
5
+ require 'mini_profiler/storage/abstract_store'
6
+ require 'mini_profiler/storage/file_store'
7
+
8
+ describe Rack::MiniProfiler::FileStore do
9
+
10
+ context 'page struct' do
11
+
12
+ before do
13
+ tmp = File.expand_path(__FILE__ + "/../../../tmp")
14
+ Dir::mkdir(tmp) unless File.exists?(tmp)
15
+ @store = Rack::MiniProfiler::FileStore.new(:path => tmp)
16
+ end
17
+
18
+ describe 'storage' do
19
+
20
+ it 'can store a PageStruct and retrieve it' do
21
+ page_struct = Rack::MiniProfiler::PageTimerStruct.new({})
22
+ page_struct['Id'] = "XYZ"
23
+ page_struct['Random'] = "random"
24
+ @store.save(page_struct)
25
+ page_struct = @store.load("XYZ")
26
+ page_struct['Random'].should == "random"
27
+ page_struct['Id'].should == "XYZ"
28
+ end
29
+
30
+ it 'can list unviewed items for a user' do
31
+ @store.set_unviewed('a', 'XYZ')
32
+ @store.set_unviewed('a', 'ABC')
33
+ @store.get_unviewed_ids('a').sort.to_a.should == ['XYZ', 'ABC'].sort.to_a
34
+ end
35
+
36
+ it 'can set an item to viewed once it is unviewed' do
37
+ @store.set_unviewed('a', 'XYZ')
38
+ @store.set_unviewed('a', 'ABC')
39
+ @store.set_viewed('a', 'XYZ')
40
+ @store.get_unviewed_ids('a').should == ['ABC']
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'mini_profiler/storage/abstract_store'
3
+ require 'mini_profiler/storage/memory_store'
4
+
5
+ describe Rack::MiniProfiler::MemoryStore do
6
+
7
+ context 'page struct' do
8
+
9
+ before do
10
+ @store = Rack::MiniProfiler::MemoryStore.new nil
11
+ end
12
+
13
+ describe 'storage' do
14
+
15
+ it 'can store a PageStruct and retrieve it' do
16
+ page_struct = {'Id' => "XYZ", 'Random' => "random"}
17
+ @store.save(page_struct)
18
+ page_struct = @store.load("XYZ")
19
+ page_struct['Id'].should == "XYZ"
20
+ page_struct['Random'].should == "random"
21
+ end
22
+
23
+ it 'can list unviewed items for a user' do
24
+ @store.set_unviewed('a', 'XYZ')
25
+ @store.set_unviewed('a', 'ABC')
26
+ @store.get_unviewed_ids('a').should == ['XYZ', 'ABC']
27
+ end
28
+
29
+ it 'can set an item to viewed once it is unviewed' do
30
+ @store.set_unviewed('a', 'XYZ')
31
+ @store.set_unviewed('a', 'ABC')
32
+ @store.set_viewed('a', 'XYZ')
33
+ @store.get_unviewed_ids('a').should == ['ABC']
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+
4
+ describe Rack::MiniProfiler::PageTimerStruct do
5
+
6
+ before do
7
+ @page = Rack::MiniProfiler::PageTimerStruct.new({})
8
+ end
9
+
10
+ it 'has an Id' do
11
+ @page['Id'].should_not be_nil
12
+ end
13
+
14
+ it 'has a Root' do
15
+ @page['Root'].should_not be_nil
16
+ end
17
+
18
+ describe 'to_json' do
19
+ before do
20
+ @json = @page.to_json
21
+ @deserialized = ::JSON.parse(@json)
22
+ end
23
+
24
+ it 'has a Started element' do
25
+ @deserialized['Started'].should_not be_nil
26
+ end
27
+
28
+ it 'has a DurationMilliseconds element' do
29
+ @deserialized['DurationMilliseconds'].should_not be_nil
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+
4
+ describe Rack::MiniProfiler do
5
+
6
+ describe 'unique id' do
7
+
8
+ before do
9
+ @unique = Rack::MiniProfiler.generate_id
10
+ end
11
+
12
+ it 'is not nil' do
13
+ @unique.should_not be_nil
14
+ end
15
+
16
+ it 'is not empty' do
17
+ @unique.should_not be_empty
18
+ end
19
+
20
+ describe 'configuration' do
21
+
22
+ it 'allows us to set configuration settings' do
23
+ Rack::MiniProfiler.config.auto_inject = false
24
+ Rack::MiniProfiler.config.auto_inject.should == false
25
+ end
26
+
27
+ it 'can reset the settings' do
28
+ Rack::MiniProfiler.config.auto_inject = false
29
+ Rack::MiniProfiler.reset_config
30
+ Rack::MiniProfiler.config.auto_inject.should be_true
31
+ end
32
+
33
+ describe 'base_url_path' do
34
+ it 'adds a trailing slash onto the base_url_path' do
35
+ profiler = Rack::MiniProfiler.new(nil, :base_url_path => "/test-resource")
36
+ profiler.config.base_url_path.should == "/test-resource/"
37
+ end
38
+
39
+ it "doesn't add the trailing slash when it's already there" do
40
+ profiler = Rack::MiniProfiler.new(nil, :base_url_path => "/test-resource/")
41
+ profiler.config.base_url_path.should == "/test-resource/"
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ describe 'profile method' do
50
+ before do
51
+ Rack::MiniProfiler.create_current
52
+ class TestClass
53
+ def foo(bar,baz)
54
+ return [bar, baz, yield]
55
+ end
56
+ end
57
+ end
58
+
59
+ it 'should not destroy a method' do
60
+ Rack::MiniProfiler.profile_method TestClass, :foo
61
+ TestClass.new.foo("a","b"){"c"}.should == ["a","b","c"]
62
+ Rack::MiniProfiler.unprofile_method TestClass, :foo
63
+ end
64
+
65
+ end
66
+
67
+ describe 'step' do
68
+
69
+ describe 'basic usage' do
70
+ it 'yields the block given' do
71
+ Rack::MiniProfiler.create_current
72
+ Rack::MiniProfiler.step('test') { "mini profiler" }.should == "mini profiler"
73
+ end
74
+ end
75
+
76
+
77
+ describe 'typical usage' do
78
+ before(:all) do
79
+ Rack::MiniProfiler.create_current
80
+ Time.now = Time.new
81
+ Time.now += 1
82
+ Rack::MiniProfiler.step('outer') {
83
+ Time.now += 2
84
+ Rack::MiniProfiler.step('inner') {
85
+ Time.now += 3
86
+ }
87
+ Time.now += 4
88
+ }
89
+ @page_struct = Rack::MiniProfiler.current.page_struct
90
+ @root = @page_struct.root
91
+ @root.record_time
92
+
93
+ @outer = @page_struct.root.children[0]
94
+ @inner = @outer.children[0]
95
+ end
96
+
97
+ after(:all) do
98
+ Time.back_to_normal
99
+ end
100
+
101
+ it 'measures total duration correctly' do
102
+ @page_struct.duration_ms.to_i.should == 10 * 1000
103
+ end
104
+
105
+ it 'measures outer start time correctly' do
106
+ @outer.start_ms.to_i.should == 1 * 1000
107
+ end
108
+
109
+ it 'measures outer duration correctly' do
110
+ @outer.duration_ms.to_i.should == 9 * 1000
111
+ end
112
+
113
+ it 'measures inner start time correctly' do
114
+ @inner.start_ms.to_i.should == 3 * 1000
115
+ end
116
+
117
+ it 'measures inner duration correctly' do
118
+ @inner.duration_ms.to_i.should == 3 * 1000
119
+ end
120
+
121
+ end
122
+
123
+ end
124
+
125
+ end
126
+
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+ require 'mini_profiler/page_timer_struct'
4
+ require 'mini_profiler/storage/abstract_store'
5
+ require 'mini_profiler/storage/redis_store'
6
+
7
+ describe Rack::MiniProfiler::RedisStore do
8
+
9
+ context 'page struct' do
10
+
11
+ before do
12
+ @store = Rack::MiniProfiler::RedisStore.new(nil)
13
+ end
14
+
15
+ describe 'storage' do
16
+
17
+ it 'can store a PageStruct and retrieve it' do
18
+ page_struct = Rack::MiniProfiler::PageTimerStruct.new({})
19
+ page_struct['Id'] = "XYZ"
20
+ page_struct['Random'] = "random"
21
+ @store.save(page_struct)
22
+ page_struct = @store.load("XYZ")
23
+ page_struct['Random'].should == "random"
24
+ page_struct['Id'].should == "XYZ"
25
+ end
26
+
27
+ it 'can list unviewed items for a user' do
28
+ @store.set_unviewed('a', 'XYZ')
29
+ @store.set_unviewed('a', 'ABC')
30
+ @store.get_unviewed_ids('a').should == ['XYZ', 'ABC']
31
+ end
32
+
33
+ it 'can set an item to viewed once it is unviewed' do
34
+ @store.set_unviewed('a', 'XYZ')
35
+ @store.set_unviewed('a', 'ABC')
36
+ @store.set_viewed('a', 'XYZ')
37
+ @store.get_unviewed_ids('a').should == ['ABC']
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+
4
+ describe Rack::MiniProfiler::RequestTimerStruct do
5
+
6
+ def new_page
7
+ Rack::MiniProfiler::PageTimerStruct.new({})
8
+ end
9
+
10
+ before do
11
+ @name = 'cool request'
12
+ @request = Rack::MiniProfiler::RequestTimerStruct.createRoot(@name, new_page)
13
+ end
14
+
15
+ it 'sets IsRoot to true' do
16
+ @request['IsRoot'].should be_true
17
+ end
18
+
19
+ it 'has an Id' do
20
+ @request['Id'].should_not be_nil
21
+ end
22
+
23
+ it 'has a Root' do
24
+ @request['Name'].should == @name
25
+ end
26
+
27
+ it 'begins with a children duration of 0' do
28
+ @request.children_duration.should == 0
29
+ end
30
+
31
+ it 'has a false HasChildren attribute' do
32
+ @request['HasChildren'].should be_false
33
+ end
34
+
35
+ it 'has an empty Children attribute' do
36
+ @request['Children'].should be_empty
37
+ end
38
+
39
+ it 'has a depth of 0' do
40
+ @request['Depth'].should == 0
41
+ end
42
+
43
+ it 'has a false HasSqlTimings attribute' do
44
+ @request['HasSqlTimings'].should be_false
45
+ end
46
+
47
+ it 'has no sql timings at first' do
48
+ @request['SqlTimings'].should be_empty
49
+ end
50
+
51
+ it 'has a 0 for SqlTimingsDurationMilliseconds' do
52
+ @request['SqlTimingsDurationMilliseconds'].should == 0
53
+ end
54
+
55
+ describe 'add SQL' do
56
+
57
+ before do
58
+ @page = new_page
59
+ @request.add_sql("SELECT 1 FROM users", 77, @page)
60
+ end
61
+
62
+ it 'has a true HasSqlTimings attribute' do
63
+ @request['HasSqlTimings'].should be_true
64
+ end
65
+
66
+ it 'has the SqlTiming object' do
67
+ @request['SqlTimings'].should_not be_empty
68
+ end
69
+
70
+ it 'has a child with the ParentTimingId of the request' do
71
+ @request['SqlTimings'][0]['ParentTimingId'].should == @request['Id']
72
+ end
73
+
74
+ it 'increases SqlTimingsDurationMilliseconds' do
75
+ @request['SqlTimingsDurationMilliseconds'].should == 77
76
+ end
77
+
78
+ it "increases the page's " do
79
+ @page['DurationMillisecondsInSql'].should == 77
80
+ end
81
+
82
+ end
83
+
84
+ describe 'record time' do
85
+
86
+ describe 'add children' do
87
+
88
+ before do
89
+ @child = @request.add_child('child')
90
+ @child.record_time(1111)
91
+ end
92
+
93
+ it 'has a IsRoot value of false' do
94
+ @child['IsRoot'].should be_false
95
+ end
96
+
97
+ it 'has a true HasChildren attribute' do
98
+ @request['HasChildren'].should be_true
99
+ end
100
+
101
+ it 'has the child in the Children attribute' do
102
+ @request['Children'].should == [@child]
103
+ end
104
+
105
+ it 'assigns its Id to the child' do
106
+ @child['ParentTimingId'].should == @request['Id']
107
+ end
108
+
109
+ it 'assigns a depth of 1 to the child' do
110
+ @child['Depth'].should == 1
111
+ end
112
+
113
+ it 'increases the children duration' do
114
+ @request.children_duration.should == 1111
115
+ end
116
+
117
+ it 'marks short timings as trivial' do
118
+ @request.record_time(1)
119
+ @request['IsTrivial'].should be_true
120
+ end
121
+
122
+
123
+ describe 'record time on parent' do
124
+ before do
125
+ @request.record_time(1234)
126
+ end
127
+
128
+ it "is not a trivial query" do
129
+ @request['IsTrivial'].should be_false
130
+ end
131
+
132
+ it 'has stores the recorded time in DurationMilliseconds' do
133
+ @request['DurationMilliseconds'].should == 1234
134
+ end
135
+
136
+ it 'calculates DurationWithoutChildrenMilliseconds without the children timings' do
137
+ @request['DurationWithoutChildrenMilliseconds'].should == 123
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+
144
+
145
+ end
146
+
147
+
148
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'rack-mini-profiler'
3
+
4
+ describe Rack::MiniProfiler::SqlTimerStruct do
5
+
6
+ describe 'valid sql timer' do
7
+ before do
8
+ @sql = Rack::MiniProfiler::SqlTimerStruct.new("SELECT * FROM users", 200, Rack::MiniProfiler::PageTimerStruct.new({}), nil)
9
+ end
10
+
11
+ it 'has an ExecuteType' do
12
+ @sql['ExecuteType'].should_not be_nil
13
+ end
14
+
15
+ it 'has a FormattedCommandString' do
16
+ @sql['FormattedCommandString'].should_not be_nil
17
+ end
18
+
19
+ it 'has a StackTraceSnippet' do
20
+ @sql['StackTraceSnippet'].should_not be_nil
21
+ end
22
+
23
+ it 'has a StartMilliseconds' do
24
+ @sql['StartMilliseconds'].should_not be_nil
25
+ end
26
+
27
+ it 'has a DurationMilliseconds' do
28
+ @sql['DurationMilliseconds'].should_not be_nil
29
+ end
30
+
31
+ it 'has a IsDuplicate' do
32
+ @sql['IsDuplicate'].should_not be_nil
33
+ end
34
+ end
35
+
36
+
37
+
38
+ describe 'backtrace' do
39
+ it 'has a snippet' do
40
+ sql = Rack::MiniProfiler::SqlTimerStruct.new("SELECT * FROM users", 200, Rack::MiniProfiler::PageTimerStruct.new({}), nil)
41
+ sql['StackTraceSnippet'].should_not be nil
42
+ end
43
+
44
+ it 'includes rspec in the trace (default is no filter)' do
45
+ sql = Rack::MiniProfiler::SqlTimerStruct.new("SELECT * FROM users", 200, Rack::MiniProfiler::PageTimerStruct.new({}), nil)
46
+ sql['StackTraceSnippet'].should match /rspec/
47
+ end
48
+
49
+ it "doesn't include rspec if we filter for only app" do
50
+ Rack::MiniProfiler.config.backtrace_filter = /\/app/
51
+ sql = Rack::MiniProfiler::SqlTimerStruct.new("SELECT * FROM users", 200, Rack::MiniProfiler::PageTimerStruct.new({}), nil)
52
+ sql['StackTraceSnippet'].should_not match /rspec/
53
+ end
54
+
55
+ it "includes rspec if we filter for it" do
56
+ Rack::MiniProfiler.config.backtrace_filter = /\/(app|rspec)/
57
+ sql = Rack::MiniProfiler::SqlTimerStruct.new("SELECT * FROM users", 200, Rack::MiniProfiler::PageTimerStruct.new({}), nil)
58
+ sql['StackTraceSnippet'].should match /rspec/
59
+ end
60
+
61
+ end
62
+
63
+ end