wested-rack-bug 0.2.2.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 (78) hide show
  1. data/.gitignore +3 -0
  2. data/History.txt +0 -0
  3. data/MIT-LICENSE.txt +19 -0
  4. data/README.rdoc +29 -0
  5. data/Rakefile +20 -0
  6. data/Thorfile +109 -0
  7. data/VERSION +1 -0
  8. data/lib/rack/bug.rb +43 -0
  9. data/lib/rack/bug/options.rb +89 -0
  10. data/lib/rack/bug/panel.rb +50 -0
  11. data/lib/rack/bug/panel_app.rb +33 -0
  12. data/lib/rack/bug/panels/active_record_panel.rb +45 -0
  13. data/lib/rack/bug/panels/active_record_panel/activerecord_extensions.rb +18 -0
  14. data/lib/rack/bug/panels/cache_panel.rb +50 -0
  15. data/lib/rack/bug/panels/cache_panel/memcache_extension.rb +129 -0
  16. data/lib/rack/bug/panels/cache_panel/panel_app.rb +48 -0
  17. data/lib/rack/bug/panels/cache_panel/stats.rb +97 -0
  18. data/lib/rack/bug/panels/log_panel.rb +39 -0
  19. data/lib/rack/bug/panels/log_panel/rails_extension.rb +11 -0
  20. data/lib/rack/bug/panels/memory_panel.rb +27 -0
  21. data/lib/rack/bug/panels/rails_info_panel.rb +23 -0
  22. data/lib/rack/bug/panels/redis_panel.rb +44 -0
  23. data/lib/rack/bug/panels/redis_panel/redis_extension.rb +14 -0
  24. data/lib/rack/bug/panels/redis_panel/stats.rb +48 -0
  25. data/lib/rack/bug/panels/request_variables_panel.rb +25 -0
  26. data/lib/rack/bug/panels/sql_panel.rb +55 -0
  27. data/lib/rack/bug/panels/sql_panel/panel_app.rb +37 -0
  28. data/lib/rack/bug/panels/sql_panel/query.rb +73 -0
  29. data/lib/rack/bug/panels/sql_panel/sql_extension.rb +11 -0
  30. data/lib/rack/bug/panels/templates_panel.rb +44 -0
  31. data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +12 -0
  32. data/lib/rack/bug/panels/templates_panel/rendering.rb +67 -0
  33. data/lib/rack/bug/panels/templates_panel/trace.rb +34 -0
  34. data/lib/rack/bug/panels/timer_panel.rb +40 -0
  35. data/lib/rack/bug/params_signature.rb +65 -0
  36. data/lib/rack/bug/public/__rack_bug__/bookmarklet.html +10 -0
  37. data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +215 -0
  38. data/lib/rack/bug/public/__rack_bug__/bug.css +211 -0
  39. data/lib/rack/bug/public/__rack_bug__/bug.js +84 -0
  40. data/lib/rack/bug/public/__rack_bug__/jquery-1.3.2.js +4376 -0
  41. data/lib/rack/bug/public/__rack_bug__/jquery.tablesorter.min.js +1 -0
  42. data/lib/rack/bug/public/__rack_bug__/spinner.gif +0 -0
  43. data/lib/rack/bug/render.rb +66 -0
  44. data/lib/rack/bug/toolbar.rb +137 -0
  45. data/lib/rack/bug/views/error.html.erb +16 -0
  46. data/lib/rack/bug/views/panels/active_record.html.erb +17 -0
  47. data/lib/rack/bug/views/panels/cache.html.erb +93 -0
  48. data/lib/rack/bug/views/panels/execute_sql.html.erb +32 -0
  49. data/lib/rack/bug/views/panels/explain_sql.html.erb +32 -0
  50. data/lib/rack/bug/views/panels/log.html.erb +23 -0
  51. data/lib/rack/bug/views/panels/profile_sql.html.erb +32 -0
  52. data/lib/rack/bug/views/panels/rails_info.html.erb +19 -0
  53. data/lib/rack/bug/views/panels/redis.html.erb +32 -0
  54. data/lib/rack/bug/views/panels/request_variables.html.erb +107 -0
  55. data/lib/rack/bug/views/panels/sql.html.erb +43 -0
  56. data/lib/rack/bug/views/panels/templates.html.erb +7 -0
  57. data/lib/rack/bug/views/panels/timer.html.erb +19 -0
  58. data/lib/rack/bug/views/panels/view_cache.html.erb +19 -0
  59. data/lib/rack/bug/views/redirect.html.erb +16 -0
  60. data/lib/rack/bug/views/toolbar.html.erb +42 -0
  61. data/spec/fixtures/config.ru +8 -0
  62. data/spec/fixtures/dummy_panel.rb +2 -0
  63. data/spec/fixtures/sample_app.rb +29 -0
  64. data/spec/rack/bug/panels/active_record_panel_spec.rb +30 -0
  65. data/spec/rack/bug/panels/cache_panel_spec.rb +159 -0
  66. data/spec/rack/bug/panels/log_panel_spec.rb +25 -0
  67. data/spec/rack/bug/panels/memory_panel_spec.rb +21 -0
  68. data/spec/rack/bug/panels/rails_info_panel_spec.rb +25 -0
  69. data/spec/rack/bug/panels/redis_panel_spec.rb +57 -0
  70. data/spec/rack/bug/panels/sql_panel_spec.rb +136 -0
  71. data/spec/rack/bug/panels/templates_panel_spec.rb +71 -0
  72. data/spec/rack/bug/panels/timer_panel_spec.rb +38 -0
  73. data/spec/rack/toolbar_spec.rb +100 -0
  74. data/spec/rcov.opts +1 -0
  75. data/spec/spec.opts +1 -0
  76. data/spec/spec_helper.rb +70 -0
  77. data/wested-rack-bug.gemspec +127 -0
  78. metadata +153 -0
@@ -0,0 +1,44 @@
1
+ module Rack
2
+ module Bug
3
+
4
+ class RedisPanel < Panel
5
+ require "rack/bug/panels/redis_panel/redis_extension"
6
+
7
+ autoload :Stats, "rack/bug/panels/redis_panel/stats"
8
+
9
+ def self.record(*redis_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, redis_command_args)
16
+ return result
17
+ end
18
+
19
+ def self.reset
20
+ Thread.current["rack.bug.redis"] = Stats.new
21
+ end
22
+
23
+ def self.stats
24
+ Thread.current["rack.bug.redis"] ||= Stats.new
25
+ end
26
+
27
+ def name
28
+ "redis"
29
+ end
30
+
31
+ def heading
32
+ "Redis: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
33
+ end
34
+
35
+ def content
36
+ result = render_template "panels/redis", :stats => self.class.stats
37
+ self.class.reset
38
+ return result
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ require 'redis'
2
+
3
+ if defined?(Redis)
4
+ Redis.class_eval do
5
+
6
+ def call_command_with_rack_bug(argv)
7
+ Rack::Bug::RedisPanel.record(argv) do
8
+ call_command_without_rack_bug(argv)
9
+ end
10
+ end
11
+
12
+ alias_method_chain :call_command, :rack_bug
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ module Rack
2
+ module Bug
3
+ class RedisPanel
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
+ @command = command_args.inspect
13
+ end
14
+
15
+ def display_time
16
+ "%.2fms" % time
17
+ end
18
+ end
19
+
20
+ attr_reader :calls
21
+ attr_reader :queries
22
+
23
+ def initialize
24
+ @queries = []
25
+ @calls = 0
26
+ @time = 0.0
27
+ end
28
+
29
+ def record_call(time, *command_args)
30
+ @queries << Query.new(time, command_args)
31
+ @calls += 1
32
+ @time += time
33
+ end
34
+
35
+ def display_time
36
+ "%.2fms" % time
37
+ end
38
+
39
+ def time
40
+ @queries.inject(0) do |memo, query|
41
+ memo + query.time
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ module Rack
2
+ module Bug
3
+
4
+ class RequestVariablesPanel < Panel
5
+
6
+ def name
7
+ "request_variables"
8
+ end
9
+
10
+ def before(env)
11
+ @env = env
12
+ end
13
+
14
+ def heading
15
+ "Rack Env"
16
+ end
17
+
18
+ def content
19
+ render_template "panels/request_variables", :request => @request, :env => @env
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,55 @@
1
+ require "digest"
2
+
3
+ module Rack
4
+ module Bug
5
+
6
+ class SQLPanel < Panel
7
+ require "rack/bug/panels/sql_panel/sql_extension"
8
+
9
+ autoload :PanelApp, "rack/bug/panels/sql_panel/panel_app"
10
+ autoload :Query, "rack/bug/panels/sql_panel/query"
11
+
12
+ def panel_app
13
+ PanelApp.new
14
+ end
15
+
16
+ def self.record(sql, backtrace = [], &block)
17
+ return block.call unless Rack::Bug.enabled?
18
+
19
+ start_time = Time.now
20
+ result = block.call
21
+ queries << Query.new(sql, Time.now - start_time, backtrace)
22
+
23
+ return result
24
+ end
25
+
26
+ def self.reset
27
+ Thread.current["rack.test.queries"] = []
28
+ end
29
+
30
+ def self.queries
31
+ Thread.current["rack.test.queries"] ||= []
32
+ end
33
+
34
+ def self.total_time
35
+ (queries.inject(0) { |memo, query| memo + query.time}) * 1_000
36
+ end
37
+
38
+ def name
39
+ "sql"
40
+ end
41
+
42
+ def heading
43
+ "#{self.class.queries.size} Queries (%.2fms)" % self.class.total_time
44
+ end
45
+
46
+ def content
47
+ result = render_template "panels/sql", :queries => self.class.queries
48
+ self.class.reset
49
+ return result
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,37 @@
1
+ module Rack
2
+ module Bug
3
+ class SQLPanel
4
+
5
+ class PanelApp < ::Rack::Bug::PanelApp
6
+
7
+ def dispatch
8
+ case request.path_info
9
+ when "/__rack_bug__/explain_sql" then explain_sql
10
+ when "/__rack_bug__/profile_sql" then profile_sql
11
+ when "/__rack_bug__/execute_sql" then execute_sql
12
+ else not_found
13
+ end
14
+ end
15
+
16
+ def explain_sql
17
+ validate_params
18
+ query = Query.new(params["query"], params["time"].to_f)
19
+ render_template "panels/explain_sql", :result => query.explain, :query => query.sql, :time => query.time
20
+ end
21
+
22
+ def profile_sql
23
+ validate_params
24
+ query = Query.new(params["query"], params["time"].to_f)
25
+ render_template "panels/profile_sql", :result => query.profile, :query => query.sql, :time => query.time
26
+ end
27
+
28
+ def execute_sql
29
+ validate_params
30
+ query = Query.new(params["query"], params["time"].to_f)
31
+ render_template "panels/execute_sql", :result => query.execute, :query => query.sql, :time => query.time
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,73 @@
1
+ module Rack
2
+ module Bug
3
+ class SQLPanel
4
+
5
+ class Query
6
+ attr_reader :sql
7
+ attr_reader :time
8
+ attr_reader :backtrace
9
+
10
+ def initialize(sql, time, backtrace = [])
11
+ @sql = sql
12
+ @time = time
13
+ @backtrace = backtrace
14
+ end
15
+
16
+ def human_time
17
+ "%.2fms" % (@time * 1_000)
18
+ end
19
+
20
+ def inspectable?
21
+ sql.strip =~ /^SELECT /i
22
+ end
23
+
24
+ def with_profiling
25
+ self.class.execute("SET PROFILING=1")
26
+ result = yield
27
+ self.class.execute("SET PROFILING=0")
28
+ return result
29
+ end
30
+
31
+ def explain
32
+ self.class.execute "EXPLAIN #{@sql}"
33
+ end
34
+
35
+ def profile
36
+ with_profiling do
37
+ execute
38
+ self.class.execute <<-SQL
39
+ SELECT *
40
+ FROM information_schema.profiling
41
+ WHERE query_id = (SELECT query_id FROM information_schema.profiling ORDER BY query_id DESC LIMIT 1)
42
+ SQL
43
+ end
44
+ end
45
+
46
+ def execute
47
+ self.class.execute(@sql)
48
+ end
49
+
50
+ def valid_hash?(secret_key, possible_hash)
51
+ hash = Digest::SHA1.hexdigest [secret_key, @sql].join(":")
52
+ possible_hash == hash
53
+ end
54
+
55
+ def self.execute(sql)
56
+ ActiveRecord::Base.connection.execute(sql)
57
+ 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
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ if defined?(ActiveRecord) && defined?(ActiveRecord::ConnectionAdapters)
2
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
3
+ def log_with_rack_bug(sql, name, &block)
4
+ Rack::Bug::SQLPanel.record(sql, Kernel.caller) do
5
+ log_without_rack_bug(sql, name, &block)
6
+ end
7
+ end
8
+
9
+ alias_method_chain :log, :rack_bug
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ module Rack
2
+ module Bug
3
+
4
+ class TemplatesPanel < Panel
5
+ require "rack/bug/panels/templates_panel/actionview_extension"
6
+
7
+ autoload :Trace, "rack/bug/panels/templates_panel/trace"
8
+ autoload :Rendering, "rack/bug/panels/templates_panel/rendering"
9
+
10
+ def self.record(template, &block)
11
+ return block.call unless Rack::Bug.enabled?
12
+
13
+ template_trace.start(template)
14
+ result = block.call
15
+ template_trace.finished(template)
16
+ return result
17
+ end
18
+
19
+ def self.reset
20
+ Thread.current["rack.bug.template_trace"] = Trace.new
21
+ end
22
+
23
+ def self.template_trace
24
+ Thread.current["rack.bug.template_trace"] ||= Trace.new
25
+ end
26
+
27
+ def name
28
+ "templates"
29
+ end
30
+
31
+ def heading
32
+ "Templates: %.2fms" % (self.class.template_trace.total_time * 1_000)
33
+ end
34
+
35
+ def content
36
+ result = render_template "panels/templates", :template_trace => self.class.template_trace
37
+ self.class.reset
38
+ return result
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ if defined?(ActionView) && defined?(ActionView::Template)
2
+ ActionView::Template.class_eval do
3
+
4
+ def render_template_with_rack_bug(*args, &block)
5
+ Rack::Bug::TemplatesPanel.record(path_without_format_and_extension) do
6
+ render_template_without_rack_bug(*args, &block)
7
+ end
8
+ end
9
+
10
+ alias_method_chain :render_template, :rack_bug
11
+ end
12
+ end
@@ -0,0 +1,67 @@
1
+ module Rack
2
+ module Bug
3
+ class TemplatesPanel
4
+
5
+ class Rendering
6
+ attr_accessor :name
7
+ attr_accessor :start_time
8
+ attr_accessor :end_time
9
+ attr_accessor :parent
10
+ attr_reader :children
11
+
12
+
13
+ def initialize(name)
14
+ @name = name
15
+ @children = []
16
+ end
17
+
18
+ def add(rendering)
19
+ @children << rendering
20
+ rendering.parent = self
21
+ end
22
+
23
+ def time
24
+ @end_time - @start_time
25
+ end
26
+
27
+ def exclusive_time
28
+ time - child_time
29
+ end
30
+
31
+ def child_time
32
+ children.inject(0.0) { |memo, c| memo + c.time }
33
+ end
34
+
35
+ def time_summary
36
+ if children.any?
37
+ "%.2fms, %.2f exclusive" % [time * 1_000, exclusive_time * 1_000]
38
+ else
39
+ "%.2fms" % (time * 1_000)
40
+ end
41
+ end
42
+ def html
43
+ <<-HTML
44
+ <li>
45
+ <p>#{name} (#{time_summary})</p>
46
+
47
+ #{children_html}
48
+ </li>
49
+ HTML
50
+ end
51
+
52
+ def children_html
53
+ return "" unless children.any?
54
+
55
+ <<-HTML
56
+ <ul>#{joined_children_html}</ul>
57
+ HTML
58
+ end
59
+
60
+ def joined_children_html
61
+ children.map { |c| c.html }.join
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,34 @@
1
+ module Rack
2
+ module Bug
3
+ class TemplatesPanel
4
+
5
+ class Trace
6
+
7
+ def start(template_name)
8
+ rendering = Rendering.new(template_name)
9
+ rendering.start_time = Time.now
10
+ @current.add(rendering)
11
+ @current = rendering
12
+ end
13
+
14
+ def finished(template_name)
15
+ @current.end_time = Time.now
16
+ @current = @current.parent
17
+ end
18
+
19
+ def initialize
20
+ @current = root
21
+ end
22
+
23
+ def total_time
24
+ root.child_time
25
+ end
26
+
27
+ def root
28
+ @root ||= Rendering.new("root")
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end