gentooboontoo-rack-bug 0.3.0.edge

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 (92) hide show
  1. data/.gitignore +3 -0
  2. data/History.txt +46 -0
  3. data/MIT-LICENSE.txt +19 -0
  4. data/README.md +120 -0
  5. data/Rakefile +23 -0
  6. data/Thorfile +113 -0
  7. data/lib/rack/bug/autoloading.rb +25 -0
  8. data/lib/rack/bug/filtered_backtrace.rb +38 -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/activerecord_extensions.rb +18 -0
  13. data/lib/rack/bug/panels/active_record_panel.rb +45 -0
  14. data/lib/rack/bug/panels/cache_panel/dalli_extension.rb +16 -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/cache_panel.rb +51 -0
  19. data/lib/rack/bug/panels/log_panel/logger_extension.rb +24 -0
  20. data/lib/rack/bug/panels/log_panel.rb +56 -0
  21. data/lib/rack/bug/panels/memory_panel.rb +27 -0
  22. data/lib/rack/bug/panels/mongo_panel/mongo_extension.rb +27 -0
  23. data/lib/rack/bug/panels/mongo_panel/stats.rb +48 -0
  24. data/lib/rack/bug/panels/mongo_panel.rb +44 -0
  25. data/lib/rack/bug/panels/rails_info_panel.rb +23 -0
  26. data/lib/rack/bug/panels/redis_panel/redis_extension.rb +28 -0
  27. data/lib/rack/bug/panels/redis_panel/stats.rb +52 -0
  28. data/lib/rack/bug/panels/redis_panel.rb +44 -0
  29. data/lib/rack/bug/panels/request_variables_panel.rb +52 -0
  30. data/lib/rack/bug/panels/sphinx_panel/sphinx_extension.rb +25 -0
  31. data/lib/rack/bug/panels/sphinx_panel/stats.rb +96 -0
  32. data/lib/rack/bug/panels/sphinx_panel.rb +44 -0
  33. data/lib/rack/bug/panels/sql_panel/panel_app.rb +37 -0
  34. data/lib/rack/bug/panels/sql_panel/query.rb +63 -0
  35. data/lib/rack/bug/panels/sql_panel/sql_extension.rb +11 -0
  36. data/lib/rack/bug/panels/sql_panel.rb +55 -0
  37. data/lib/rack/bug/panels/templates_panel/actionview_extension.rb +12 -0
  38. data/lib/rack/bug/panels/templates_panel/rendering.rb +67 -0
  39. data/lib/rack/bug/panels/templates_panel/trace.rb +34 -0
  40. data/lib/rack/bug/panels/templates_panel.rb +47 -0
  41. data/lib/rack/bug/panels/timer_panel.rb +40 -0
  42. data/lib/rack/bug/params_signature.rb +63 -0
  43. data/lib/rack/bug/public/__rack_bug__/bookmarklet.html +10 -0
  44. data/lib/rack/bug/public/__rack_bug__/bookmarklet.js +217 -0
  45. data/lib/rack/bug/public/__rack_bug__/bug.css +220 -0
  46. data/lib/rack/bug/public/__rack_bug__/bug.js +84 -0
  47. data/lib/rack/bug/public/__rack_bug__/jquery-1.3.2.js +4376 -0
  48. data/lib/rack/bug/public/__rack_bug__/jquery.tablesorter.min.js +1 -0
  49. data/lib/rack/bug/public/__rack_bug__/spinner.gif +0 -0
  50. data/lib/rack/bug/rack_static_bug_avoider.rb +16 -0
  51. data/lib/rack/bug/redirect_interceptor.rb +27 -0
  52. data/lib/rack/bug/render.rb +67 -0
  53. data/lib/rack/bug/toolbar.rb +64 -0
  54. data/lib/rack/bug/views/error.html.erb +16 -0
  55. data/lib/rack/bug/views/panels/active_record.html.erb +17 -0
  56. data/lib/rack/bug/views/panels/cache.html.erb +93 -0
  57. data/lib/rack/bug/views/panels/execute_sql.html.erb +38 -0
  58. data/lib/rack/bug/views/panels/explain_sql.html.erb +38 -0
  59. data/lib/rack/bug/views/panels/log.html.erb +21 -0
  60. data/lib/rack/bug/views/panels/mongo.html.erb +32 -0
  61. data/lib/rack/bug/views/panels/profile_sql.html.erb +38 -0
  62. data/lib/rack/bug/views/panels/rails_info.html.erb +19 -0
  63. data/lib/rack/bug/views/panels/redis.html.erb +46 -0
  64. data/lib/rack/bug/views/panels/request_variables.html.erb +29 -0
  65. data/lib/rack/bug/views/panels/sphinx.html.erb +32 -0
  66. data/lib/rack/bug/views/panels/sql.html.erb +41 -0
  67. data/lib/rack/bug/views/panels/templates.html.erb +7 -0
  68. data/lib/rack/bug/views/panels/timer.html.erb +19 -0
  69. data/lib/rack/bug/views/panels/view_cache.html.erb +19 -0
  70. data/lib/rack/bug/views/redirect.html.erb +16 -0
  71. data/lib/rack/bug/views/toolbar.html.erb +42 -0
  72. data/lib/rack/bug.rb +82 -0
  73. data/rack-bug.gemspec +155 -0
  74. data/spec/custom_matchers.rb +21 -0
  75. data/spec/fixtures/config.ru +8 -0
  76. data/spec/fixtures/dummy_panel.rb +2 -0
  77. data/spec/fixtures/sample_app.rb +46 -0
  78. data/spec/rack/bug/panels/active_record_panel_spec.rb +30 -0
  79. data/spec/rack/bug/panels/cache_panel_spec.rb +167 -0
  80. data/spec/rack/bug/panels/log_panel_spec.rb +43 -0
  81. data/spec/rack/bug/panels/memory_panel_spec.rb +22 -0
  82. data/spec/rack/bug/panels/mongo_panel_spec.rb +51 -0
  83. data/spec/rack/bug/panels/rails_info_panel_spec.rb +40 -0
  84. data/spec/rack/bug/panels/redis_panel_spec.rb +69 -0
  85. data/spec/rack/bug/panels/sql_panel_spec.rb +146 -0
  86. data/spec/rack/bug/panels/templates_panel_spec.rb +71 -0
  87. data/spec/rack/bug/panels/timer_panel_spec.rb +38 -0
  88. data/spec/rack/bug_spec.rb +137 -0
  89. data/spec/rcov.opts +1 -0
  90. data/spec/spec.opts +1 -0
  91. data/spec/spec_helper.rb +44 -0
  92. metadata +245 -0
@@ -0,0 +1,129 @@
1
+ if defined?(Memcached)
2
+ Memcached.class_eval do
3
+
4
+ def set_with_rack_bug(key, value, timeout=0, marshal=true)
5
+ Rack::Bug::CachePanel.record(:set, key) do
6
+ set_without_rack_bug(key, value, timeout, marshal)
7
+ end
8
+ end
9
+
10
+ def add_with_rack_bug(key, value, timeout=0, marshal=true)
11
+ Rack::Bug::CachePanel.record(:add, key) do
12
+ add_without_rack_bug(key, value, timeout, marshal)
13
+ end
14
+ end
15
+
16
+ def increment_with_rack_bug(key, offset=1)
17
+ Rack::Bug::CachePanel.record(:incr, key) do
18
+ increment_without_rack_bug(key, offset)
19
+ end
20
+ end
21
+
22
+ def decrement_with_rack_bug(key, offset=1)
23
+ Rack::Bug::CachePanel.record(:decr, key) do
24
+ decrement_without_rack_bug(key, offset)
25
+ end
26
+ end
27
+
28
+ def replace_with_rack_bug(key, value, timeout=0, marshal=true)
29
+ Rack::Bug::CachePanel.record(:replace, key) do
30
+ replace_without_rack_bug(key, value, timeout, marshal)
31
+ end
32
+ end
33
+
34
+ def append_with_rack_bug(key, value)
35
+ Rack::Bug::CachePanel.record(:append, key) do
36
+ append_without_rack_bug(key, value)
37
+ end
38
+ end
39
+
40
+ def prepend_with_rack_bug(key, value)
41
+ Rack::Bug::CachePanel.record(:prepend, key) do
42
+ prepend_without_rack_bug(key, value)
43
+ end
44
+ end
45
+
46
+ def delete_with_rack_bug(key)
47
+ Rack::Bug::CachePanel.record(:delete, key) do
48
+ delete_without_rack_bug(key)
49
+ end
50
+ end
51
+
52
+ def get_with_rack_bug(keys, marshal=true)
53
+ if keys.is_a? Array
54
+ Rack::Bug::CachePanel.record(:get_multi, *keys) do
55
+ get_without_rack_bug(keys, marshal)
56
+ end
57
+ else
58
+ Rack::Bug::CachePanel.record(:get, keys) do
59
+ get_without_rack_bug(keys, marshal)
60
+ end
61
+ end
62
+ end
63
+
64
+ alias_method_chain :decrement, :rack_bug
65
+ alias_method_chain :get, :rack_bug
66
+ alias_method_chain :increment, :rack_bug
67
+ alias_method_chain :set, :rack_bug
68
+ alias_method_chain :add, :rack_bug
69
+ alias_method_chain :replace, :rack_bug
70
+ alias_method_chain :delete, :rack_bug
71
+ alias_method_chain :prepend, :rack_bug
72
+ alias_method_chain :append, :rack_bug
73
+ end
74
+ end
75
+
76
+ if defined?(MemCache)
77
+ MemCache.class_eval do
78
+
79
+ def decr_with_rack_bug(key, amount = 1)
80
+ Rack::Bug::CachePanel.record(:decr, key) do
81
+ decr_without_rack_bug(key, amount)
82
+ end
83
+ end
84
+
85
+ def get_with_rack_bug(key, raw = false)
86
+ Rack::Bug::CachePanel.record(:get, key) do
87
+ get_without_rack_bug(key, raw)
88
+ end
89
+ end
90
+
91
+ def get_multi_with_rack_bug(*keys)
92
+ Rack::Bug::CachePanel.record(:get_multi, *keys) do
93
+ get_multi_without_rack_bug(*keys)
94
+ end
95
+ end
96
+
97
+ def incr_with_rack_bug(key, amount = 1)
98
+ Rack::Bug::CachePanel.record(:incr, key) do
99
+ incr_without_rack_bug(key, amount)
100
+ end
101
+ end
102
+
103
+ def set_with_rack_bug(key, value, expiry = 0, raw = false)
104
+ Rack::Bug::CachePanel.record(:set, key) do
105
+ set_without_rack_bug(key, value, expiry, raw)
106
+ end
107
+ end
108
+
109
+ def add_with_rack_bug(key, value, expiry = 0, raw = false)
110
+ Rack::Bug::CachePanel.record(:add, key) do
111
+ add_without_rack_bug(key, value, expiry, raw)
112
+ end
113
+ end
114
+
115
+ def delete_with_rack_bug(key, expiry = 0)
116
+ Rack::Bug::CachePanel.record(:delete, key) do
117
+ delete_without_rack_bug(key, expiry)
118
+ end
119
+ end
120
+
121
+ alias_method_chain :decr, :rack_bug
122
+ alias_method_chain :get, :rack_bug
123
+ alias_method_chain :get_multi, :rack_bug
124
+ alias_method_chain :incr, :rack_bug
125
+ alias_method_chain :set, :rack_bug
126
+ alias_method_chain :add, :rack_bug
127
+ alias_method_chain :delete, :rack_bug
128
+ end
129
+ end
@@ -0,0 +1,48 @@
1
+ module Rack
2
+ class Bug
3
+ class CachePanel
4
+
5
+ class PanelApp < ::Rack::Bug::PanelApp
6
+
7
+ def dispatch
8
+ case request.path_info
9
+ when "/__rack_bug__/view_cache" then view_cache
10
+ when "/__rack_bug__/delete_cache" then delete_cache
11
+ when "/__rack_bug__/delete_cache_list" then delete_cache_list
12
+ else not_found
13
+ end
14
+ end
15
+
16
+ def ok
17
+ Rack::Response.new(["OK"]).to_a
18
+ end
19
+
20
+ def view_cache
21
+ validate_params
22
+ render_template "panels/view_cache", :key => params["key"], :value => Rails.cache.read(params["key"])
23
+ end
24
+
25
+ def delete_cache
26
+ validate_params
27
+ raise "Rails not found... can't delete key" unless defined?(Rails)
28
+ Rails.cache.delete(params["key"])
29
+ ok
30
+ end
31
+
32
+ def delete_cache_list
33
+ validate_params
34
+ raise "Rails not found... can't delete key" unless defined?(Rails)
35
+
36
+ params.each do |key, value|
37
+ next unless key =~ /^keys_/
38
+ Rails.cache.delete(value)
39
+ end
40
+
41
+ ok
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,97 @@
1
+ module Rack
2
+ class Bug
3
+ class CachePanel
4
+
5
+ class Stats
6
+ class Query
7
+ attr_reader :method, :time, :hit, :keys
8
+
9
+ def initialize(method, time, hit, keys)
10
+ @method = method
11
+ @time = time
12
+ @hit = hit
13
+ @keys = keys
14
+ end
15
+
16
+ def display_time
17
+ "%.2fms" % time
18
+ end
19
+
20
+ def display_keys
21
+ if keys.size == 1
22
+ keys.first
23
+ else
24
+ keys.join(", ")
25
+ end
26
+ end
27
+ end
28
+
29
+ attr_reader :calls
30
+ attr_reader :keys
31
+ attr_reader :queries
32
+
33
+ def initialize
34
+ @queries = []
35
+ @misses =
36
+ @calls = 0
37
+ @time = 0.0
38
+ @keys = []
39
+ end
40
+
41
+ def record_call(method, time, hit, *keys)
42
+ @queries << Query.new(method, time, hit, keys)
43
+ @calls += 1
44
+ @time += time
45
+ @keys += keys
46
+ end
47
+
48
+ def display_time
49
+ "%.2fms" % time
50
+ end
51
+
52
+ def time
53
+ @queries.inject(0) do |memo, query|
54
+ memo + query.time
55
+ end
56
+ end
57
+
58
+ def gets
59
+ count_queries(:get)
60
+ end
61
+
62
+ def sets
63
+ count_queries(:set)
64
+ end
65
+
66
+ def deletes
67
+ count_queries(:delete)
68
+ end
69
+
70
+ def get_multis
71
+ count_queries(:get_multi)
72
+ end
73
+
74
+ def hits
75
+ @queries.select { |q| [:get, :get_multi].include?(q.method) && q.hit }.size
76
+ end
77
+
78
+ def misses
79
+ @queries.select { |q| [:get, :get_multi].include?(q.method) && !q.hit }.size
80
+ end
81
+
82
+ def count_queries(method)
83
+ @queries.select { |q| q.method == method }.size
84
+ end
85
+
86
+ def queries_to_param
87
+ params = {}
88
+ @queries.each_with_index do |query, index|
89
+ params["keys_#{index}"] = query.keys.first
90
+ end
91
+ params
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,51 @@
1
+ require "rack/bug/panels/cache_panel/memcache_extension"
2
+ require "rack/bug/panels/cache_panel/dalli_extension"
3
+
4
+ module Rack
5
+ class Bug
6
+
7
+ class CachePanel < Panel
8
+ autoload :PanelApp, "rack/bug/panels/cache_panel/panel_app"
9
+ autoload :Stats, "rack/bug/panels/cache_panel/stats"
10
+
11
+ def self.record(method, *keys, &block)
12
+ return block.call unless Rack::Bug.enabled?
13
+
14
+ start_time = Time.now
15
+ result = block.call
16
+ total_time = Time.now - start_time
17
+ hit = result.nil? ? false : true
18
+ stats.record_call(method, total_time * 1_000, hit, *keys)
19
+ return result
20
+ end
21
+
22
+ def self.reset
23
+ Thread.current["rack.bug.cache"] = Stats.new
24
+ end
25
+
26
+ def self.stats
27
+ Thread.current["rack.bug.cache"] ||= Stats.new
28
+ end
29
+
30
+ def panel_app
31
+ PanelApp.new
32
+ end
33
+
34
+ def name
35
+ "cache"
36
+ end
37
+
38
+ def heading
39
+ "Cache: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
40
+ end
41
+
42
+ def content
43
+ result = render_template "panels/cache", :stats => self.class.stats
44
+ self.class.reset
45
+ return result
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ module Rack::Bug::LoggerExtension
2
+ def self.included(target)
3
+ target.send :alias_method, :add_without_rack_bug, :add
4
+ target.send :alias_method, :add, :add_with_rack_bug
5
+ end
6
+
7
+ def add_with_rack_bug(*args, &block)
8
+ logger_return = add_without_rack_bug(*args, &block)
9
+ logged_message = logger_return
10
+ logged_message = args[1] || args[2] unless logged_message.is_a?(String)
11
+ Rack::Bug::LogPanel.record(logged_message, args[0])
12
+ return logger_return
13
+ end
14
+ end
15
+
16
+ if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
17
+ logger = Rails.logger
18
+ elsif defined?(LOGGER)
19
+ logger = LOGGER
20
+ end
21
+
22
+ if logger
23
+ logger.class.send :include, Rack::Bug::LoggerExtension
24
+ end
@@ -0,0 +1,56 @@
1
+ require "rack/bug/panels/log_panel/logger_extension"
2
+
3
+ module Rack
4
+ class Bug
5
+
6
+ class LogPanel < Panel
7
+ class LogEntry
8
+ attr_reader :level, :time, :message
9
+ LEVELS = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
10
+
11
+ def initialize(level, time, message)
12
+ @level = LEVELS[level]
13
+ @time = time
14
+ @message = message
15
+ end
16
+
17
+ def cleaned_message
18
+ @message.to_s.gsub(/\e\[[;\d]+m/, "")
19
+ end
20
+ end
21
+
22
+ def self.record(message, log_level)
23
+ return unless Rack::Bug.enabled?
24
+ return unless message
25
+ Thread.current["rack.bug.logs.start"] ||= Time.now
26
+ timestamp = ((Time.now - Thread.current["rack.bug.logs.start"]) * 1000).to_i
27
+ logs << LogEntry.new(log_level, timestamp, message)
28
+ end
29
+
30
+ def self.reset
31
+ Thread.current["rack.bug.logs"] = []
32
+ Thread.current["rack.bug.logs.start"] = nil
33
+ end
34
+
35
+ def self.logs
36
+ Thread.current["rack.bug.logs"] ||= []
37
+ end
38
+
39
+ def name
40
+ "log"
41
+ end
42
+
43
+ def heading
44
+ "Log"
45
+ end
46
+
47
+ def content
48
+ result = render_template "panels/log", :logs => self.class.logs
49
+ self.class.reset
50
+ return result
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ module Rack
3
+ class Bug
4
+
5
+ class MemoryPanel < Panel
6
+
7
+ def before(env)
8
+ @original_memory = `ps -o rss= -p #{$$}`.to_i
9
+ end
10
+
11
+ def after(env, status, headers, body)
12
+ @total_memory = `ps -o rss= -p #{$$}`.to_i
13
+ @memory_increase = @total_memory - @original_memory
14
+ end
15
+
16
+ def heading
17
+ "#{@memory_increase} KB &#916;, #{@total_memory} KB total"
18
+ end
19
+
20
+ def has_content?
21
+ false
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'mongo'
2
+
3
+ if defined?(Mongo)
4
+ Mongo::Connection.class_eval do
5
+
6
+ def send_message_with_rack_bug(operation, message, log_message=nil)
7
+ Rack::Bug::MongoPanel.record(log_message || message) do
8
+ send_message_without_rack_bug(operation, message, log_message)
9
+ end
10
+ end
11
+ alias_method_chain :send_message, :rack_bug
12
+
13
+ def send_message_with_safe_check_with_rack_bug(operation, message, db_name, log_message=nil, last_error_params=false)
14
+ Rack::Bug::MongoPanel.record(log_message || message) do
15
+ send_message_with_safe_check_without_rack_bug(operation, message, db_name, log_message, last_error_params)
16
+ end
17
+ end
18
+ alias_method_chain :send_message_with_safe_check, :rack_bug
19
+
20
+ def receive_message_with_rack_bug(operation, message, log_message=nil, socket=nil)
21
+ Rack::Bug::MongoPanel.record(log_message || "A logger must be configured to catch receive message commands") do
22
+ receive_message_without_rack_bug(operation, message, log_message, socket)
23
+ end
24
+ end
25
+ alias_method_chain :receive_message, :rack_bug
26
+ end
27
+ end
@@ -0,0 +1,48 @@
1
+ module Rack
2
+ class Bug
3
+ class MongoPanel
4
+
5
+ class Stats
6
+ class Query
7
+ attr_reader :time
8
+ attr_reader :command
9
+
10
+ def initialize(time, command)
11
+ @time = time
12
+ @command = command
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)
30
+ @queries << Query.new(time, command)
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,44 @@
1
+ module Rack
2
+ class Bug
3
+
4
+ class MongoPanel < Panel
5
+ require "rack/bug/panels/mongo_panel/mongo_extension"
6
+
7
+ autoload :Stats, "rack/bug/panels/mongo_panel/stats"
8
+
9
+ def self.record(command, &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, command)
16
+ return result
17
+ end
18
+
19
+ def self.reset
20
+ Thread.current["rack.bug.mongo"] = Stats.new
21
+ end
22
+
23
+ def self.stats
24
+ Thread.current["rack.bug.mongo"] ||= Stats.new
25
+ end
26
+
27
+ def name
28
+ "mongo"
29
+ end
30
+
31
+ def heading
32
+ "Mongo: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
33
+ end
34
+
35
+ def content
36
+ result = render_template "panels/mongo", :stats => self.class.stats
37
+ self.class.reset
38
+ return result
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ module Rack
2
+ class Bug
3
+
4
+ class RailsInfoPanel < Panel
5
+
6
+ def name
7
+ "rails_info"
8
+ end
9
+
10
+ def heading
11
+ return unless (defined?(Rails) && defined?(Rails::Info))
12
+ "Rails #{Rails.version}"
13
+ end
14
+
15
+ def content
16
+ return unless (defined?(Rails) && defined?(Rails::Info))
17
+ render_template "panels/rails_info"
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ require 'redis'
2
+
3
+ if defined?(Redis)
4
+ Redis.class_eval do
5
+ if Redis.methods.include?('call_command') # older versions of redis-rb
6
+ def call_command_with_rack_bug(*argv)
7
+ Rack::Bug::RedisPanel.record(argv, Kernel.caller) do
8
+ call_command_without_rack_bug(*argv)
9
+ end
10
+ end
11
+
12
+ alias_method_chain :call_command, :rack_bug
13
+
14
+ elsif defined?(Redis::Client) # newer versions of redis-rb
15
+
16
+ Redis::Client.class_eval do
17
+ def call_with_rack_bug(*argv)
18
+ Rack::Bug::RedisPanel.record(argv, Kernel.caller) do
19
+ call_without_rack_bug(*argv)
20
+ end
21
+ end
22
+
23
+ alias_method_chain :call, :rack_bug
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+ module Rack
2
+ class Bug
3
+ class RedisPanel
4
+
5
+ class Stats
6
+ class Query
7
+ include Rack::Bug::FilteredBacktrace
8
+
9
+ attr_reader :time
10
+ attr_reader :command
11
+
12
+ def initialize(time, command_args, backtrace)
13
+ @time = time
14
+ @command = command_args.inspect
15
+ @backtrace = backtrace
16
+ end
17
+
18
+ def display_time
19
+ "%.2fms" % time
20
+ end
21
+ end
22
+
23
+ attr_reader :calls
24
+ attr_reader :queries
25
+
26
+ def initialize
27
+ @queries = []
28
+ @calls = 0
29
+ @time = 0.0
30
+ end
31
+
32
+ def record_call(time, command_args, backtrace)
33
+ @queries << Query.new(time, command_args, backtrace)
34
+ @calls += 1
35
+ @time += time
36
+ end
37
+
38
+ def display_time
39
+ "%.2fms" % time
40
+ end
41
+
42
+ def time
43
+ @queries.inject(0) do |memo, query|
44
+ memo + query.time
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ module Rack
2
+ class 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, backtrace, &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, backtrace)
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