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.
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