rack-bug 0.2.1 → 0.3.0
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 +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,11 +4,11 @@ if defined?(Redis)
|
|
4
4
|
Redis.class_eval do
|
5
5
|
|
6
6
|
def call_command_with_rack_bug(argv)
|
7
|
-
Rack::Bug::RedisPanel.record(argv) do
|
7
|
+
Rack::Bug::RedisPanel.record(argv, Kernel.caller) do
|
8
8
|
call_command_without_rack_bug(argv)
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
alias_method_chain :call_command, :rack_bug
|
13
13
|
end
|
14
|
-
end
|
14
|
+
end
|
@@ -1,48 +1,52 @@
|
|
1
1
|
module Rack
|
2
2
|
module Bug
|
3
3
|
class RedisPanel
|
4
|
-
|
4
|
+
|
5
5
|
class Stats
|
6
6
|
class Query
|
7
|
+
include Rack::Bug::FilteredBacktrace
|
8
|
+
|
7
9
|
attr_reader :time
|
8
10
|
attr_reader :command
|
9
|
-
|
10
|
-
def initialize(time,
|
11
|
+
|
12
|
+
def initialize(time, command_args, backtrace)
|
11
13
|
@time = time
|
12
14
|
@command = command_args.inspect
|
15
|
+
@backtrace = backtrace
|
13
16
|
end
|
14
|
-
|
17
|
+
|
15
18
|
def display_time
|
16
19
|
"%.2fms" % time
|
17
20
|
end
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
attr_reader :calls
|
21
24
|
attr_reader :queries
|
22
|
-
|
25
|
+
|
23
26
|
def initialize
|
24
27
|
@queries = []
|
25
28
|
@calls = 0
|
26
29
|
@time = 0.0
|
27
30
|
end
|
28
|
-
|
29
|
-
def record_call(time,
|
30
|
-
@queries << Query.new(time, command_args)
|
31
|
+
|
32
|
+
def record_call(time, command_args, backtrace)
|
33
|
+
@queries << Query.new(time, command_args, backtrace)
|
31
34
|
@calls += 1
|
32
35
|
@time += time
|
33
36
|
end
|
34
|
-
|
37
|
+
|
35
38
|
def display_time
|
36
39
|
"%.2fms" % time
|
37
40
|
end
|
38
|
-
|
41
|
+
|
39
42
|
def time
|
40
43
|
@queries.inject(0) do |memo, query|
|
41
44
|
memo + query.time
|
42
45
|
end
|
43
46
|
end
|
47
|
+
|
44
48
|
end
|
45
|
-
|
49
|
+
|
46
50
|
end
|
47
51
|
end
|
48
|
-
end
|
52
|
+
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
module Rack
|
2
2
|
module Bug
|
3
|
-
|
3
|
+
|
4
4
|
class RequestVariablesPanel < Panel
|
5
|
-
|
5
|
+
|
6
6
|
def name
|
7
7
|
"request_variables"
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def before(env)
|
11
11
|
@env = env
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def heading
|
15
15
|
"Rack Env"
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def content
|
19
19
|
render_template "panels/request_variables", :request => @request, :env => @env
|
20
20
|
end
|
21
21
|
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
|
4
|
+
class SphinxPanel < Panel
|
5
|
+
require "rack/bug/panels/sphinx_panel/sphinx_extension"
|
6
|
+
|
7
|
+
autoload :Stats, "rack/bug/panels/sphinx_panel/stats"
|
8
|
+
|
9
|
+
def self.record(*sphinx_command_args, &block)
|
10
|
+
return block.call unless Rack::Bug.enabled?
|
11
|
+
|
12
|
+
start_time = Time.now
|
13
|
+
result = block.call
|
14
|
+
total_time = Time.now - start_time
|
15
|
+
stats.record_call(total_time * 1_000, sphinx_command_args)
|
16
|
+
return result
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.reset
|
20
|
+
Thread.current["rack.bug.sphinx"] = Stats.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.stats
|
24
|
+
Thread.current["rack.bug.sphinx"] ||= Stats.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
"sphinx"
|
29
|
+
end
|
30
|
+
|
31
|
+
def heading
|
32
|
+
"Sphinx: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
|
33
|
+
end
|
34
|
+
|
35
|
+
def content
|
36
|
+
result = render_template "panels/sphinx", :stats => self.class.stats
|
37
|
+
self.class.reset
|
38
|
+
return result
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'riddle'
|
2
|
+
|
3
|
+
if defined?(Riddle)
|
4
|
+
Riddle::Client.class_eval do
|
5
|
+
def request_with_rack_bug(command, messages)
|
6
|
+
Rack::Bug::SphinxPanel.record(command, messages) do
|
7
|
+
request_without_rack_bug(command, messages)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
alias_method_chain :request, :rack_bug
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Rack
|
2
|
+
module Bug
|
3
|
+
class SphinxPanel
|
4
|
+
|
5
|
+
class Stats
|
6
|
+
class Query
|
7
|
+
attr_reader :time
|
8
|
+
attr_reader :command
|
9
|
+
|
10
|
+
def initialize(time, *command_args)
|
11
|
+
@time = time
|
12
|
+
if command_args.flatten.first == :search
|
13
|
+
@command = "search: " + decode_message(command_args.first.flatten.last).collect{|k,v| "#{k} => #{v}"}.join(", ")
|
14
|
+
else
|
15
|
+
@command = command_args.flatten.first.to_s + ": No more info is available for this Riddle request type"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def display_time
|
20
|
+
"%.2fms" % time
|
21
|
+
end
|
22
|
+
|
23
|
+
def decode_message(m)
|
24
|
+
@m = m.clone
|
25
|
+
params = ActiveSupport::OrderedHash.new
|
26
|
+
|
27
|
+
params[:offset] = consume_int
|
28
|
+
params[:limit] = consume_int
|
29
|
+
params[:match_mode] = consume_int
|
30
|
+
params[:rank_mode] = consume_int
|
31
|
+
params[:sort_mode] = consume_int
|
32
|
+
params[:sort_by] = consume_string
|
33
|
+
params[:query] = consume_string
|
34
|
+
wl = consume_int
|
35
|
+
weights = []
|
36
|
+
wl.times do weights << consume_int end
|
37
|
+
params[:weights] = weights
|
38
|
+
|
39
|
+
params[:index] = consume_string
|
40
|
+
|
41
|
+
consume_string
|
42
|
+
|
43
|
+
params[:id_range] = [consume_64int, consume_64int]
|
44
|
+
params
|
45
|
+
end
|
46
|
+
|
47
|
+
def consume_int
|
48
|
+
i = @m.unpack("N").first
|
49
|
+
@m = @m.slice(4, @m.length - 4)
|
50
|
+
i
|
51
|
+
end
|
52
|
+
|
53
|
+
def consume_64int
|
54
|
+
i = @m.unpack("NN").first
|
55
|
+
@m = @m.slice(8, @m.length - 8)
|
56
|
+
i
|
57
|
+
end
|
58
|
+
|
59
|
+
def consume_string
|
60
|
+
len = consume_int
|
61
|
+
s = @m.slice(0, len)
|
62
|
+
@m = @m.slice(len, @m.length - len)
|
63
|
+
s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :calls
|
68
|
+
attr_reader :queries
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
@queries = []
|
72
|
+
@calls = 0
|
73
|
+
@time = 0.0
|
74
|
+
end
|
75
|
+
|
76
|
+
def record_call(time, *command_args)
|
77
|
+
|
78
|
+
@queries << Query.new(time, command_args)
|
79
|
+
@calls += 1
|
80
|
+
@time += time
|
81
|
+
end
|
82
|
+
|
83
|
+
def display_time
|
84
|
+
"%.2fms" % time
|
85
|
+
end
|
86
|
+
|
87
|
+
def time
|
88
|
+
@queries.inject(0) do |memo, query|
|
89
|
+
memo + query.time
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Rack
|
2
2
|
module Bug
|
3
3
|
class SQLPanel
|
4
|
-
|
4
|
+
|
5
5
|
class PanelApp < ::Rack::Bug::PanelApp
|
6
|
-
|
6
|
+
|
7
7
|
def dispatch
|
8
8
|
case request.path_info
|
9
9
|
when "/__rack_bug__/explain_sql" then explain_sql
|
@@ -12,26 +12,26 @@ module Rack
|
|
12
12
|
else not_found
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def explain_sql
|
17
17
|
validate_params
|
18
18
|
query = Query.new(params["query"], params["time"].to_f)
|
19
19
|
render_template "panels/explain_sql", :result => query.explain, :query => query.sql, :time => query.time
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def profile_sql
|
23
23
|
validate_params
|
24
24
|
query = Query.new(params["query"], params["time"].to_f)
|
25
25
|
render_template "panels/profile_sql", :result => query.profile, :query => query.sql, :time => query.time
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def execute_sql
|
29
29
|
validate_params
|
30
30
|
query = Query.new(params["query"], params["time"].to_f)
|
31
31
|
render_template "panels/execute_sql", :result => query.execute, :query => query.sql, :time => query.time
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
|
-
end
|
37
|
+
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module Rack
|
2
2
|
module Bug
|
3
3
|
class SQLPanel
|
4
|
-
|
4
|
+
|
5
5
|
class Query
|
6
|
+
include Rack::Bug::FilteredBacktrace
|
7
|
+
|
6
8
|
attr_reader :sql
|
7
9
|
attr_reader :time
|
8
|
-
|
9
|
-
|
10
|
+
|
10
11
|
def initialize(sql, time, backtrace = [])
|
11
12
|
@sql = sql
|
12
13
|
@time = time
|
13
14
|
@backtrace = backtrace
|
14
15
|
end
|
15
|
-
|
16
|
+
|
16
17
|
def human_time
|
17
18
|
"%.2fms" % (@time * 1_000)
|
18
19
|
end
|
@@ -20,18 +21,18 @@ module Rack
|
|
20
21
|
def inspectable?
|
21
22
|
sql.strip =~ /^SELECT /i
|
22
23
|
end
|
23
|
-
|
24
|
+
|
24
25
|
def with_profiling
|
25
26
|
self.class.execute("SET PROFILING=1")
|
26
27
|
result = yield
|
27
28
|
self.class.execute("SET PROFILING=0")
|
28
29
|
return result
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
def explain
|
32
33
|
self.class.execute "EXPLAIN #{@sql}"
|
33
34
|
end
|
34
|
-
|
35
|
+
|
35
36
|
def profile
|
36
37
|
with_profiling do
|
37
38
|
execute
|
@@ -42,32 +43,21 @@ module Rack
|
|
42
43
|
SQL
|
43
44
|
end
|
44
45
|
end
|
45
|
-
|
46
|
+
|
46
47
|
def execute
|
47
48
|
self.class.execute(@sql)
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def valid_hash?(secret_key, possible_hash)
|
51
52
|
hash = Digest::SHA1.hexdigest [secret_key, @sql].join(":")
|
52
53
|
possible_hash == hash
|
53
54
|
end
|
54
|
-
|
55
|
+
|
55
56
|
def self.execute(sql)
|
56
57
|
ActiveRecord::Base.connection.execute(sql)
|
57
58
|
end
|
58
|
-
|
59
|
-
def has_backtrace?
|
60
|
-
filtered_backtrace.any?
|
61
|
-
end
|
62
|
-
|
63
|
-
def filtered_backtrace
|
64
|
-
@filtered_backtrace ||= @backtrace.map { |l| l.to_s.strip }.select do |line|
|
65
|
-
line.starts_with?(Rails.root) &&
|
66
|
-
!line.starts_with?(Rails.root.join("vendor"))
|
67
|
-
end
|
68
|
-
end
|
69
59
|
end
|
70
|
-
|
60
|
+
|
71
61
|
end
|
72
62
|
end
|
73
|
-
end
|
63
|
+
end
|
@@ -1,37 +1,37 @@
|
|
1
1
|
module Rack
|
2
2
|
module Bug
|
3
3
|
class TemplatesPanel
|
4
|
-
|
4
|
+
|
5
5
|
class Rendering
|
6
6
|
attr_accessor :name
|
7
7
|
attr_accessor :start_time
|
8
8
|
attr_accessor :end_time
|
9
9
|
attr_accessor :parent
|
10
10
|
attr_reader :children
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
|
13
13
|
def initialize(name)
|
14
14
|
@name = name
|
15
15
|
@children = []
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def add(rendering)
|
19
19
|
@children << rendering
|
20
20
|
rendering.parent = self
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def time
|
24
24
|
@end_time - @start_time
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def exclusive_time
|
28
28
|
time - child_time
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def child_time
|
32
32
|
children.inject(0.0) { |memo, c| memo + c.time }
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def time_summary
|
36
36
|
if children.any?
|
37
37
|
"%.2fms, %.2f exclusive" % [time * 1_000, exclusive_time * 1_000]
|
@@ -43,25 +43,25 @@ module Rack
|
|
43
43
|
<<-HTML
|
44
44
|
<li>
|
45
45
|
<p>#{name} (#{time_summary})</p>
|
46
|
-
|
46
|
+
|
47
47
|
#{children_html}
|
48
48
|
</li>
|
49
49
|
HTML
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
def children_html
|
53
53
|
return "" unless children.any?
|
54
|
-
|
54
|
+
|
55
55
|
<<-HTML
|
56
56
|
<ul>#{joined_children_html}</ul>
|
57
57
|
HTML
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def joined_children_html
|
61
61
|
children.map { |c| c.html }.join
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
end
|
66
66
|
end
|
67
|
-
end
|
67
|
+
end
|