rack-bug 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +21 -0
- data/README.md +115 -0
- data/Rakefile +6 -19
- data/Thorfile +109 -0
- data/lib/rack/bug.rb +4 -2
- data/lib/rack/bug/filtered_backtrace.rb +38 -0
- data/lib/rack/bug/options.rb +4 -4
- data/lib/rack/bug/panel.rb +12 -12
- data/lib/rack/bug/panel_app.rb +8 -8
- data/lib/rack/bug/panels/active_record_panel.rb +11 -11
- data/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb +3 -3
- data/lib/rack/bug/panels/cache_panel.rb +1 -1
- data/lib/rack/bug/panels/cache_panel/memcache_extension.rb +4 -4
- data/lib/rack/bug/panels/cache_panel/panel_app.rb +11 -11
- data/lib/rack/bug/panels/cache_panel/stats.rb +20 -20
- data/lib/rack/bug/panels/log_panel.rb +27 -10
- data/lib/rack/bug/panels/log_panel/rails_extension.rb +2 -2
- data/lib/rack/bug/panels/memory_panel.rb +8 -8
- data/lib/rack/bug/panels/rails_info_panel.rb +5 -5
- data/lib/rack/bug/panels/redis_panel.rb +3 -3
- data/lib/rack/bug/panels/redis_panel/redis_extension.rb +3 -3
- data/lib/rack/bug/panels/redis_panel/stats.rb +17 -13
- data/lib/rack/bug/panels/request_variables_panel.rb +7 -7
- data/lib/rack/bug/panels/sphinx_panel.rb +44 -0
- data/lib/rack/bug/panels/sphinx_panel/sphinx_extension.rb +13 -0
- data/lib/rack/bug/panels/sphinx_panel/stats.rb +96 -0
- data/lib/rack/bug/panels/sql_panel.rb +1 -1
- data/lib/rack/bug/panels/sql_panel/panel_app.rb +7 -7
- data/lib/rack/bug/panels/sql_panel/query.rb +13 -23
- data/lib/rack/bug/panels/sql_panel/sql_extension.rb +2 -2
- data/lib/rack/bug/panels/templates_panel.rb +1 -1
- data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +1 -1
- data/lib/rack/bug/panels/templates_panel/rendering.rb +14 -14
- data/lib/rack/bug/panels/templates_panel/trace.rb +8 -8
- data/lib/rack/bug/panels/timer_panel.rb +10 -10
- data/lib/rack/bug/params_signature.rb +18 -18
- data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +7 -5
- data/lib/rack/bug/render.rb +16 -16
- data/lib/rack/bug/toolbar.rb +39 -33
- data/lib/rack/bug/views/panels/log.html.erb +4 -6
- data/lib/rack/bug/views/panels/redis.html.erb +14 -0
- data/lib/rack/bug/views/panels/sphinx.html.erb +32 -0
- data/rack-bug.gemspec +102 -97
- data/spec/fixtures/config.ru +3 -1
- data/spec/fixtures/sample_app.rb +7 -6
- data/spec/rack/bug/panels/active_record_panel_spec.rb +6 -6
- data/spec/rack/bug/panels/cache_panel_spec.rb +46 -46
- data/spec/rack/bug/panels/log_panel_spec.rb +8 -7
- data/spec/rack/bug/panels/memory_panel_spec.rb +6 -6
- data/spec/rack/bug/panels/rails_info_panel_spec.rb +5 -5
- data/spec/rack/bug/panels/redis_panel_spec.rb +31 -19
- data/spec/rack/bug/panels/sql_panel_spec.rb +45 -45
- data/spec/rack/bug/panels/templates_panel_spec.rb +18 -18
- data/spec/rack/bug/panels/timer_panel_spec.rb +12 -12
- data/spec/rack/toolbar_spec.rb +34 -28
- data/spec/spec_helper.rb +19 -9
- metadata +44 -13
- data/README.rdoc +0 -29
- data/VERSION +0 -1
@@ -4,22 +4,23 @@ module Rack::Bug
|
|
4
4
|
describe LogPanel do
|
5
5
|
before do
|
6
6
|
LogPanel.reset
|
7
|
-
|
7
|
+
rack_env "rack-bug.panel_classes", [LogPanel]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
describe "heading" do
|
11
11
|
it "displays 'Log'" do
|
12
|
-
response =
|
12
|
+
response = get_via_rack "/"
|
13
13
|
response.should have_heading("Log")
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
describe "content" do
|
18
18
|
it "displays recorded log lines" do
|
19
|
-
LogPanel.record("This is a logged message")
|
20
|
-
response =
|
19
|
+
LogPanel.record("This is a logged message", 0)
|
20
|
+
response = get_via_rack "/"
|
21
21
|
response.should contain("This is a logged message")
|
22
|
+
response.should contain("DEBUG")
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
25
|
-
end
|
26
|
+
end
|
@@ -3,19 +3,19 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
|
3
3
|
module Rack::Bug
|
4
4
|
describe MemoryPanel do
|
5
5
|
before do
|
6
|
-
|
6
|
+
rack_env "rack-bug.panel_classes", [MemoryPanel]
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
describe "heading" do
|
10
10
|
it "displays the total memory" do
|
11
|
-
response =
|
11
|
+
response = get_via_rack "/"
|
12
12
|
response.should have_heading(/\d+ KB total/)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
it "displays the memory change during the request" do
|
16
|
-
response =
|
16
|
+
response = get_via_rack "/"
|
17
17
|
response.should have_heading(/\d+ KB Δ/)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|
@@ -3,13 +3,13 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
|
3
3
|
module Rack::Bug
|
4
4
|
describe RailsInfoPanel do
|
5
5
|
before do
|
6
|
-
|
6
|
+
rack_env "rack-bug.panel_classes", [RailsInfoPanel]
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
describe "heading" do
|
10
10
|
it "displays the Rails version" do
|
11
11
|
Rails.stub!(:version => "v2.3.0")
|
12
|
-
response =
|
12
|
+
response = get_via_rack "/"
|
13
13
|
response.should have_heading("Rails v2.3.0")
|
14
14
|
end
|
15
15
|
end
|
@@ -17,9 +17,9 @@ module Rack::Bug
|
|
17
17
|
describe "content" do
|
18
18
|
it "displays the Rails::Info properties" do
|
19
19
|
Rails::Info.stub!(:properties => [["Name", "Value"]])
|
20
|
-
response =
|
20
|
+
response = get_via_rack "/"
|
21
21
|
response.should have_row("#rails_info", "Name", "Value")
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -5,53 +5,65 @@ module Rack::Bug
|
|
5
5
|
describe RedisPanel do
|
6
6
|
before do
|
7
7
|
RedisPanel.reset
|
8
|
-
|
8
|
+
rack_env "rack-bug.panel_classes", [RedisPanel]
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
describe "heading" do
|
12
12
|
it "displays the total redis time" do
|
13
|
-
response =
|
13
|
+
response = get_via_rack "/"
|
14
14
|
response.should have_heading("Redis: 0.00ms")
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
describe "content" do
|
19
19
|
describe "usage table" do
|
20
20
|
it "displays the total number of redis calls" do
|
21
|
-
RedisPanel.record(["get, user:1"]) { }
|
22
|
-
response =
|
23
|
-
|
21
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
22
|
+
response = get_via_rack "/"
|
23
|
+
|
24
24
|
# This causes a bus error:
|
25
25
|
# response.should have_selector("th:content('Total Calls') + td", :content => "1")
|
26
26
|
|
27
27
|
response.should have_row("#redis_usage", "Total Calls", "1")
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
it "displays the total redis time" do
|
31
|
-
response =
|
31
|
+
response = get_via_rack "/"
|
32
32
|
response.should have_row("#redis_usage", "Total Time", "0.00ms")
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
describe "breakdown" do
|
37
37
|
it "displays each redis operation" do
|
38
|
-
RedisPanel.record(["get, user:1"]) { }
|
39
|
-
response =
|
38
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
39
|
+
response = get_via_rack "/"
|
40
40
|
response.should have_row("#redis_breakdown", "get")
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "displays the time for redis call" do
|
44
|
-
RedisPanel.record(["get, user:1"]) { }
|
45
|
-
response =
|
44
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
45
|
+
response = get_via_rack "/"
|
46
46
|
response.should have_row("#redis_breakdown", "user:1", TIME_MS_REGEXP)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it "displays the arguments for each redis call" do
|
50
|
-
RedisPanel.record(["get, user:1"]) { }
|
51
|
-
response =
|
50
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
51
|
+
response = get_via_rack "/"
|
52
52
|
response.should have_row("#redis_breakdown", "user:1", "get")
|
53
53
|
end
|
54
|
+
|
55
|
+
it "displays a link to show the backtrace when it's available" do
|
56
|
+
RedisPanel.record(["get, user:1"], Kernel.caller) { }
|
57
|
+
response = get_via_rack "/"
|
58
|
+
response.should have_row("#redis_breakdown", "user:1", "Show Backtrace")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not display a link to show the backtrace when it's not available" do
|
62
|
+
RedisPanel.record(["get, user:1"], []) { }
|
63
|
+
response = get_via_rack "/"
|
64
|
+
response.should_not contain("Show Backtrace")
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
56
68
|
end
|
57
|
-
end
|
69
|
+
end
|
@@ -4,133 +4,133 @@ module Rack::Bug
|
|
4
4
|
describe SQLPanel do
|
5
5
|
before do
|
6
6
|
SQLPanel.reset
|
7
|
-
|
7
|
+
rack_env "rack-bug.panel_classes", [SQLPanel]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
describe "heading" do
|
11
11
|
it "displays the total SQL query count" do
|
12
12
|
SQLPanel.record("SELECT NOW();") { }
|
13
|
-
response =
|
13
|
+
response = get_via_rack "/"
|
14
14
|
response.should have_heading("1 Queries")
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
it "displays the total SQL time" do
|
18
18
|
SQLPanel.record("SELECT NOW();") { }
|
19
|
-
response =
|
19
|
+
response = get_via_rack "/"
|
20
20
|
response.should have_heading(/Queries \(\d+\.\d{2}ms\)/)
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
describe "content" do
|
25
25
|
it "displays each executed SQL query" do
|
26
26
|
SQLPanel.record("SELECT NOW();") { }
|
27
|
-
response =
|
27
|
+
response = get_via_rack "/"
|
28
28
|
response.should have_row("#sql", "SELECT NOW();")
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it "displays the time of each executed SQL query" do
|
32
32
|
SQLPanel.record("SELECT NOW();") { }
|
33
|
-
response =
|
33
|
+
response = get_via_rack "/"
|
34
34
|
response.should have_row("#sql", "SELECT NOW();", TIME_MS_REGEXP)
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def stub_result(results = [[]])
|
39
39
|
columns = results.first
|
40
40
|
fields = columns.map { |c| stub("field", :name => c) }
|
41
41
|
rows = results[1..-1]
|
42
|
-
|
42
|
+
|
43
43
|
result = stub("result", :fetch_fields => fields)
|
44
44
|
result.stub!(:each).and_yield(*rows)
|
45
45
|
return result
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def expect_query(sql, results)
|
49
49
|
conn = stub("connection")
|
50
50
|
ActiveRecord::Base.stub!(:connection => conn)
|
51
51
|
conn.should_receive(:execute).with(sql).and_return(stub_result(results))
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
describe "execute_sql" do
|
55
55
|
it "displays the query results" do
|
56
|
-
|
56
|
+
rack_env "rack-bug.secret_key", "abc"
|
57
57
|
expect_query "SELECT username FROM users",
|
58
58
|
[["username"],
|
59
59
|
["bryan"]]
|
60
|
-
|
61
|
-
response =
|
60
|
+
|
61
|
+
response = get_via_rack "/__rack_bug__/execute_sql", :query => "SELECT username FROM users",
|
62
62
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
63
63
|
response.should contain("SELECT username FROM users")
|
64
64
|
response.should be_ok
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
it "is forbidden when the hash is missing or wrong" do
|
68
|
-
|
69
|
-
|
68
|
+
rack_env "rack-bug.secret_key", 'abc'
|
69
|
+
|
70
70
|
lambda {
|
71
|
-
|
71
|
+
get_via_rack "/__rack_bug__/execute_sql", :query => "SELECT username FROM users",
|
72
72
|
:hash => "foobar"
|
73
73
|
}.should raise_error(SecurityError)
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
it "is not available when the rack-bug.secret_key is nil" do
|
77
|
-
|
78
|
-
|
77
|
+
rack_env "rack-bug.secret_key", nil
|
78
|
+
|
79
79
|
lambda {
|
80
|
-
|
80
|
+
get_via_rack "/__rack_bug__/execute_sql", :query => "SELECT username FROM users",
|
81
81
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
82
82
|
}.should raise_error(SecurityError)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it "is not available when the rack-bug.secret_key is an empty string" do
|
86
|
-
|
87
|
-
|
86
|
+
rack_env "rack-bug.secret_key", ""
|
87
|
+
|
88
88
|
lambda {
|
89
|
-
|
89
|
+
get_via_rack "/__rack_bug__/execute_sql", :query => "SELECT username FROM users",
|
90
90
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
91
91
|
}.should raise_error(SecurityError)
|
92
92
|
end
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
describe "explain_sql" do
|
96
96
|
it "displays the query explain plan" do
|
97
|
-
|
97
|
+
rack_env "rack-bug.secret_key", "abc"
|
98
98
|
expect_query "EXPLAIN SELECT username FROM users",
|
99
99
|
[["table"],
|
100
100
|
["users"]]
|
101
|
-
|
102
|
-
response =
|
101
|
+
|
102
|
+
response = get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
103
103
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
104
104
|
response.should contain("SELECT username FROM users")
|
105
105
|
response.should be_ok
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
it "is forbidden when the hash is missing or wrong" do
|
109
|
-
|
110
|
-
|
109
|
+
rack_env "rack-bug.secret_key", 'abc'
|
110
|
+
|
111
111
|
lambda {
|
112
|
-
|
112
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
113
113
|
:hash => "foobar"
|
114
114
|
}.should raise_error(SecurityError)
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
it "is not available when the rack-bug.secret_key is nil" do
|
118
|
-
|
119
|
-
|
118
|
+
rack_env "rack-bug.secret_key", nil
|
119
|
+
|
120
120
|
lambda {
|
121
|
-
|
121
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
122
122
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
123
123
|
}.should raise_error(SecurityError)
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
it "is not available when the rack-bug.secret_key is an empty string" do
|
127
|
-
|
128
|
-
|
127
|
+
rack_env "rack-bug.secret_key", ""
|
128
|
+
|
129
129
|
lambda {
|
130
|
-
|
130
|
+
get_via_rack "/__rack_bug__/explain_sql", :query => "SELECT username FROM users",
|
131
131
|
:hash => "6f286f55b75716e5c91f16d77d09fa73b353ebc1"
|
132
132
|
}.should raise_error(SecurityError)
|
133
133
|
end
|
134
134
|
end
|
135
135
|
end
|
136
|
-
end
|
136
|
+
end
|
@@ -4,63 +4,63 @@ module Rack::Bug
|
|
4
4
|
describe TemplatesPanel do
|
5
5
|
before do
|
6
6
|
TemplatesPanel.reset
|
7
|
-
|
7
|
+
rack_env "rack-bug.panel_classes", [TemplatesPanel]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
describe "heading" do
|
11
11
|
it "displays the total rendering time" do
|
12
|
-
response =
|
12
|
+
response = get_via_rack "/"
|
13
13
|
response.should have_heading("Templates: 0.00ms")
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
describe "content" do
|
18
18
|
it "displays the template paths" do
|
19
19
|
TemplatesPanel.record("users/show") { }
|
20
|
-
response =
|
20
|
+
response = get_via_rack "/"
|
21
21
|
response.should contain("users/show")
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
it "displays the template children" do
|
25
25
|
TemplatesPanel.record("users/show") do
|
26
26
|
TemplatesPanel.record("users/toolbar") { }
|
27
27
|
end
|
28
|
-
|
29
|
-
response =
|
28
|
+
|
29
|
+
response = get_via_rack "/"
|
30
30
|
response.should have_selector("li", :content => "users/show") do |li|
|
31
31
|
li.should contain("users/toolbar")
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
context "for templates that rendered templates" do
|
36
36
|
it "displays the total time" do
|
37
37
|
TemplatesPanel.record("users/show") do
|
38
38
|
TemplatesPanel.record("users/toolbar") { }
|
39
39
|
end
|
40
|
-
|
41
|
-
response =
|
40
|
+
|
41
|
+
response = get_via_rack "/"
|
42
42
|
response.should have_selector("li", :content => "users/show") do |li|
|
43
43
|
li.should contain(TIME_MS_REGEXP)
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "displays the exclusive time" do
|
48
48
|
TemplatesPanel.record("users/show") do
|
49
49
|
TemplatesPanel.record("users/toolbar") { }
|
50
50
|
end
|
51
|
-
|
52
|
-
response =
|
51
|
+
|
52
|
+
response = get_via_rack "/"
|
53
53
|
response.should have_selector("li", :content => "users/show") do |li|
|
54
54
|
li.should contain(/\d\.\d{2} exclusive/)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
context "for leaf templates" do
|
60
60
|
it "does not display the exclusive time" do
|
61
61
|
TemplatesPanel.record("users/show") { }
|
62
|
-
|
63
|
-
response =
|
62
|
+
|
63
|
+
response = get_via_rack "/"
|
64
64
|
response.should contain("users/show") do |li|
|
65
65
|
li.should_not contain("exclusive")
|
66
66
|
end
|
@@ -68,4 +68,4 @@ module Rack::Bug
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
|
-
end
|
71
|
+
end
|
@@ -3,36 +3,36 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
|
3
3
|
module Rack::Bug
|
4
4
|
describe TimerPanel do
|
5
5
|
before do
|
6
|
-
|
6
|
+
rack_env "rack-bug.panel_classes", [TimerPanel]
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
describe "heading" do
|
10
10
|
it "displays the elapsed time" do
|
11
|
-
response =
|
11
|
+
response = get_via_rack "/"
|
12
12
|
response.should have_heading(TIME_MS_REGEXP)
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
describe "content" do
|
17
17
|
it "displays the user CPU time" do
|
18
|
-
response =
|
18
|
+
response = get_via_rack "/"
|
19
19
|
response.should have_row("#timer", "User CPU time", TIME_MS_REGEXP)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
it "displays the system CPU time" do
|
23
|
-
response =
|
23
|
+
response = get_via_rack "/"
|
24
24
|
response.should have_row("#timer", "System CPU time", TIME_MS_REGEXP)
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
it "displays the total CPU time" do
|
28
|
-
response =
|
28
|
+
response = get_via_rack "/"
|
29
29
|
response.should have_row("#timer", "Total CPU time", TIME_MS_REGEXP)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "displays the elapsed time" do
|
33
|
-
response =
|
33
|
+
response = get_via_rack "/"
|
34
34
|
response.should have_row("#timer", "Elapsed time", TIME_MS_REGEXP)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
-
end
|
38
|
+
end
|