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.
Files changed (59) hide show
  1. data/History.txt +21 -0
  2. data/README.md +115 -0
  3. data/Rakefile +6 -19
  4. data/Thorfile +109 -0
  5. data/lib/rack/bug.rb +4 -2
  6. data/lib/rack/bug/filtered_backtrace.rb +38 -0
  7. data/lib/rack/bug/options.rb +4 -4
  8. data/lib/rack/bug/panel.rb +12 -12
  9. data/lib/rack/bug/panel_app.rb +8 -8
  10. data/lib/rack/bug/panels/active_record_panel.rb +11 -11
  11. data/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb +3 -3
  12. data/lib/rack/bug/panels/cache_panel.rb +1 -1
  13. data/lib/rack/bug/panels/cache_panel/memcache_extension.rb +4 -4
  14. data/lib/rack/bug/panels/cache_panel/panel_app.rb +11 -11
  15. data/lib/rack/bug/panels/cache_panel/stats.rb +20 -20
  16. data/lib/rack/bug/panels/log_panel.rb +27 -10
  17. data/lib/rack/bug/panels/log_panel/rails_extension.rb +2 -2
  18. data/lib/rack/bug/panels/memory_panel.rb +8 -8
  19. data/lib/rack/bug/panels/rails_info_panel.rb +5 -5
  20. data/lib/rack/bug/panels/redis_panel.rb +3 -3
  21. data/lib/rack/bug/panels/redis_panel/redis_extension.rb +3 -3
  22. data/lib/rack/bug/panels/redis_panel/stats.rb +17 -13
  23. data/lib/rack/bug/panels/request_variables_panel.rb +7 -7
  24. data/lib/rack/bug/panels/sphinx_panel.rb +44 -0
  25. data/lib/rack/bug/panels/sphinx_panel/sphinx_extension.rb +13 -0
  26. data/lib/rack/bug/panels/sphinx_panel/stats.rb +96 -0
  27. data/lib/rack/bug/panels/sql_panel.rb +1 -1
  28. data/lib/rack/bug/panels/sql_panel/panel_app.rb +7 -7
  29. data/lib/rack/bug/panels/sql_panel/query.rb +13 -23
  30. data/lib/rack/bug/panels/sql_panel/sql_extension.rb +2 -2
  31. data/lib/rack/bug/panels/templates_panel.rb +1 -1
  32. data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +1 -1
  33. data/lib/rack/bug/panels/templates_panel/rendering.rb +14 -14
  34. data/lib/rack/bug/panels/templates_panel/trace.rb +8 -8
  35. data/lib/rack/bug/panels/timer_panel.rb +10 -10
  36. data/lib/rack/bug/params_signature.rb +18 -18
  37. data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +7 -5
  38. data/lib/rack/bug/render.rb +16 -16
  39. data/lib/rack/bug/toolbar.rb +39 -33
  40. data/lib/rack/bug/views/panels/log.html.erb +4 -6
  41. data/lib/rack/bug/views/panels/redis.html.erb +14 -0
  42. data/lib/rack/bug/views/panels/sphinx.html.erb +32 -0
  43. data/rack-bug.gemspec +102 -97
  44. data/spec/fixtures/config.ru +3 -1
  45. data/spec/fixtures/sample_app.rb +7 -6
  46. data/spec/rack/bug/panels/active_record_panel_spec.rb +6 -6
  47. data/spec/rack/bug/panels/cache_panel_spec.rb +46 -46
  48. data/spec/rack/bug/panels/log_panel_spec.rb +8 -7
  49. data/spec/rack/bug/panels/memory_panel_spec.rb +6 -6
  50. data/spec/rack/bug/panels/rails_info_panel_spec.rb +5 -5
  51. data/spec/rack/bug/panels/redis_panel_spec.rb +31 -19
  52. data/spec/rack/bug/panels/sql_panel_spec.rb +45 -45
  53. data/spec/rack/bug/panels/templates_panel_spec.rb +18 -18
  54. data/spec/rack/bug/panels/timer_panel_spec.rb +12 -12
  55. data/spec/rack/toolbar_spec.rb +34 -28
  56. data/spec/spec_helper.rb +19 -9
  57. metadata +44 -13
  58. data/README.rdoc +0 -29
  59. 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, *command_args)
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, *command_args)
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
@@ -52,4 +52,4 @@ module Rack
52
52
  end
53
53
 
54
54
  end
55
- end
55
+ 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
- attr_reader :backtrace
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
@@ -5,7 +5,7 @@ if defined?(ActiveRecord) && defined?(ActiveRecord::ConnectionAdapters)
5
5
  log_without_rack_bug(sql, name, &block)
6
6
  end
7
7
  end
8
-
8
+
9
9
  alias_method_chain :log, :rack_bug
10
10
  end
11
- end
11
+ end
@@ -41,4 +41,4 @@ module Rack
41
41
  end
42
42
 
43
43
  end
44
- end
44
+ end
@@ -9,4 +9,4 @@ if defined?(ActionView) && defined?(ActionView::Template)
9
9
 
10
10
  alias_method_chain :render_template, :rack_bug
11
11
  end
12
- end
12
+ 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