rack-insight 0.5.23 → 0.5.24

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/CHANGELOG CHANGED
@@ -1,5 +1,13 @@
1
1
  == HEAD
2
2
 
3
+ == 0.5.24 / 2013-01-01
4
+
5
+ * Bug Fixes
6
+
7
+ * (Issue #17) Fix 20x performance hit with default log level by changing default log level from `:debug` to `:silent` (Rack::Insight::Logging::VERBOSITY[:silent])
8
+
9
+ * Changed event logging in the instrumentation from `:high` to `:debug` level.
10
+
3
11
  == 0.5.23 / 2012-09-14
4
12
 
5
13
  * New Features
@@ -217,20 +225,20 @@
217
225
  * Can use LoggerPanel on ruby stdlib Logger in non-rails app (Tim Connor)
218
226
 
219
227
  * Bug fixes
220
-
228
+
221
229
  * Fix profile, explain and select in the queries tab, fixes issue #22 (ebertech)
222
-
230
+
223
231
  * Minor fixes
224
-
232
+
225
233
  * Explicitly require 'digest/sha1' (Jérémy Lecour)
226
234
  * Eliminate unreachable code in params signature validation (Tim Connor)
227
235
 
228
236
  * Compatibilty
229
237
 
230
238
  * Make Redis panel compatible with latest redis-rb gem, without breaking older redis-rb versions (Luke Melia)
231
-
239
+
232
240
  * Other
233
-
241
+
234
242
  * Refactoring and code cleanup (Tim Connor)
235
243
  * Testing cleanup - better isolation of Rails vs. non-Rails in tests (Tim Connor)
236
244
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rack-insight (0.5.19)
4
+ rack-insight (0.5.23)
5
5
  rack
6
6
  sqlite3 (>= 1.3.3)
7
7
  uuidtools (>= 2.1.2)
@@ -9,11 +9,15 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- archive-tar-minitar (0.5.2)
13
12
  columnize (0.3.6)
13
+ debugger (1.2.0)
14
+ columnize (>= 0.3.1)
15
+ debugger-linecache (~> 1.1.1)
16
+ debugger-ruby_core_source (~> 1.1.3)
17
+ debugger-linecache (1.1.2)
18
+ debugger-ruby_core_source (>= 1.1.1)
19
+ debugger-ruby_core_source (1.1.3)
14
20
  diff-lcs (1.1.3)
15
- linecache19 (0.5.12)
16
- ruby_core_source (>= 0.1.4)
17
21
  nokogiri (1.5.4)
18
22
  rack (1.3.5)
19
23
  rack-protection (1.1.4)
@@ -39,19 +43,9 @@ GEM
39
43
  rspec-expectations (2.11.2)
40
44
  diff-lcs (~> 1.1.3)
41
45
  rspec-mocks (2.11.2)
42
- ruby-debug-base19 (0.11.25)
43
- columnize (>= 0.3.1)
44
- linecache19 (>= 0.5.11)
45
- ruby_core_source (>= 0.1.4)
46
- ruby-debug19 (0.11.6)
47
- columnize (>= 0.3.1)
48
- linecache19 (>= 0.5.11)
49
- ruby-debug-base19 (>= 0.11.19)
50
46
  ruby2ruby (1.2.5)
51
47
  ruby_parser (~> 2.0)
52
48
  sexp_processor (~> 3.0)
53
- ruby_core_source (0.1.5)
54
- archive-tar-minitar (>= 0.5.2)
55
49
  ruby_parser (2.3.1)
56
50
  sexp_processor (~> 3.0)
57
51
  sexp_processor (3.2.0)
@@ -71,12 +65,12 @@ PLATFORMS
71
65
  ruby
72
66
 
73
67
  DEPENDENCIES
68
+ debugger
74
69
  rack-insight!
75
70
  rake
76
71
  redcarpet
77
72
  reek (>= 1.2.8)
78
73
  roodi (>= 2.1.0)
79
74
  rspec (>= 2.11.0)
80
- ruby-debug19
81
75
  sinatra
82
76
  webrat
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Rack::Insight
1
+ Rack::Insight [![Dependency Status](https://gemnasium.com/pboling/rack-insight.png)](https://gemnasium.com/pboling/rack-insight) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/pboling/rack-insight) [![Build Status](https://secure.travis-ci.org/pboling/rack-insight.png?branch=master)](https://travis-ci.org/pboling/rack-insight) [![Endorse Me](http://api.coderwall.com/pboling/endorsecount.png)](http://coderwall.com/pboling)
2
2
  =============
3
3
 
4
4
  Rack::Insight began life as an fork of Logical::Insight by LRDesign.
@@ -43,10 +43,10 @@ Features
43
43
  * SQL (Failing specs, and I don't use it, someone please pull me a fix!)
44
44
  * Active Record (Failing specs, and I don't use it, someone please pull me a fix!)
45
45
  * Other bundled panels:
46
+ * Sphinx (thanks to Oggy for updating this to the rack-insight panel API)
46
47
  * Redis
47
48
  * Speedtracer
48
- * Retired panels - if needed they could come back quickly:
49
- * Sphinx
49
+ * Panels under construction:
50
50
  * Mongo
51
51
  * The API for adding your own panels is simple and very powerful
52
52
  * Consistent interface to instrument application code
@@ -54,6 +54,13 @@ Features
54
54
  * Easy to add sub-applications for more detailed reports (c.f. SQLPanel)
55
55
  * Ask me (pboling) if you need help with this.
56
56
 
57
+ Build Status
58
+ ---------------------------
59
+
60
+ Travis-ci: [![Build Status](https://secure.travis-ci.org/pboling/rack-insight.png?branch=master)](https://travis-ci.org/pboling/rack-insight) - Please help if you have time!
61
+
62
+ CodeClimate: [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/pboling/rack-insight)
63
+
57
64
  Rails quick start
58
65
  ---------------------------
59
66
 
@@ -153,7 +160,8 @@ Specify the set of panels you want, in the order you want them to appear:
153
160
  templates_panel
154
161
  cache_panel
155
162
  log_panel
156
- memory_panel
163
+ memory_panel,
164
+ sphinx_panel
157
165
  ]
158
166
 
159
167
  By default panel files are looked up by prepending "rack/insight/panels/" and requiring them.
@@ -211,7 +219,7 @@ Restrict access using a password:
211
219
 
212
220
  #### custom file path for the request recording database ####
213
221
 
214
- Logical Rack::Insight uses SQLite to store data from requests, and outputs a database
222
+ Rack::Insight uses SQLite to store data from requests, and outputs a database
215
223
  file in the root directory. If you need the file to be created at another
216
224
  location (i.e. Heroku), you can pass a custom file path.
217
225
 
@@ -241,7 +249,7 @@ Setup the probes for the magic panel in a `before_initialize` block in your appl
241
249
  Custom Panels
242
250
  -------------
243
251
 
244
- See Magic Panels above, remove teh is_magic declaration, and add your own methods.
252
+ See Magic Panels above, remove the is_magic declaration, and add your own methods.
245
253
  Look at the panels bundled with this gem for pointers. Here are some important methods to watch for:
246
254
 
247
255
  * initialize
@@ -259,7 +267,7 @@ Authors
259
267
  Thanks
260
268
  ------
261
269
  Rack::Insight owes a lot to both LogicalInsight and Rack::Bug, as the basis projects. There's a lot of smart
262
- in there. Many thanks to Evan, Judson, and Bryan for building them.
270
+ in there. Many thanks to Judson, and Bryan for building them.
263
271
 
264
272
  Inspiration for Rack::Bug is primarily from the Django debug toolbar.
265
273
  Additional ideas from Rails footnotes, Rack's ShowException middleware, Oink,
@@ -273,6 +281,8 @@ MIT. See LICENSE in this directory.
273
281
  Notes
274
282
  -----
275
283
 
284
+ The ActiveRecord panel doesn't seem to work currently. Probably something minor, but haven't had time to look into it.
285
+
276
286
  Legacy files: would like to re-include them, but they need work
277
287
 
278
288
  lib/rack/insight/views/panels/mongo.html.erb
@@ -280,9 +290,5 @@ Legacy files: would like to re-include them, but they need work
280
290
  lib/rack/insight/panels/mongo_panel/stats.rb
281
291
  lib/rack/insight/panels/mongo_panel.rb
282
292
 
283
- lib/rack/insight/views/panels/sphinx.html.erb
284
- lib/rack/insight/panels/sphinx_panel/stats.rb
285
- lib/rack/insight/panels/sphinx_panel.rb
286
-
287
293
  This one is mostly just a curiosity
288
294
  lib/rack/insight/panels/speedtracer_panel/profiling.rb
@@ -1,7 +1,7 @@
1
1
  require 'rack'
2
2
  require "digest/sha1"
3
- require "rack/insight/config"
4
3
  require "rack/insight/logging"
4
+ require "rack/insight/config"
5
5
  require "rack/insight/filtered_backtrace"
6
6
  require "rack/insight/options"
7
7
  require 'rack/insight/magic_insight'
@@ -8,7 +8,7 @@ module Rack::Insight
8
8
  @log_file = STDOUT
9
9
  @log_level = ::Logger::DEBUG
10
10
  @logger = nil
11
- @verbosity = true
11
+ @verbosity = Rack::Insight::Logging::VERBOSITY[:silent]
12
12
  @rails_log_copy = true
13
13
  @filtered_backtrace = true
14
14
  @panel_configs = {
@@ -20,6 +20,7 @@ module Rack::Insight
20
20
  'Dalli::Client' => [:instance, :perform] } },
21
21
  :active_record => {:probes => {'ActiveRecord' => [:class, :allocate]}},
22
22
  # :log_panel => The log panel configures its probes in its initializer
23
+ :sphinx => {:probes => {'Riddle::Client' => [:instance, :request]}},
23
24
  :sql => {:probes => Hash[%w{ PostgreSQLAdapter MysqlAdapter SQLiteAdapter
24
25
  Mysql2Adapter OracleEnhancedAdapter }.map do |adapter|
25
26
  ["ActiveRecord::ConnectionAdapters::#{adapter}", [:instance, :execute]]
@@ -47,8 +48,8 @@ module Rack::Insight
47
48
  :log_level => @log_level,
48
49
  :rails_log_copy => @rails_log_copy, # Only has effect when logger is the Rack::Insight::Logger, or a logger behaving like it
49
50
  # Can set a specific verbosity: Rack::Insight::Logging::VERBOSITY[:debug]
50
- :verbosity => @verbosity, # true is equivalent to relying soley on the log level of each logged message
51
- :filtered_backtrace => @filtered_backtrace, # Full backtraces, or filtered ones?
51
+ :verbosity => @verbosity, # true is equivalent to relying solely on the log level of each logged message
52
+ :filtered_backtrace => @filtered_backtrace, # Full back-traces, or filtered ones?
52
53
  :panel_configs => @panel_configs, # Allow specific panels to have their own configurations, and make it extensible
53
54
  :silence_magic_insight_warnings => @silence_magic_insight_warnings, # Should Rack::Insight warn when the MagicInsight is used?
54
55
  :database => @database # a hash. Keys :raise_encoding_errors, and :raise_decoding_errors are self explanatory
@@ -71,7 +71,7 @@ module Rack::Insight
71
71
  end
72
72
 
73
73
  def start_event(method_call, arguments)
74
- if verbose(:high)
74
+ if verbose(:debug)
75
75
  logger.debug{ "Starting event: #{method_call.context} #{method_call.kind} #{method_call.method}" }
76
76
  end
77
77
 
@@ -82,7 +82,7 @@ module Rack::Insight
82
82
 
83
83
  def finish_event(method_call, arguments, start_time, result)
84
84
  timing = Timing.new(@start, start_time, Time.now)
85
- if verbose(:high)
85
+ if verbose(:debug)
86
86
  logger.debug{ "Finishing event: #{method_call.context} #{method_call.kind} #{method_call.method}" }
87
87
  end
88
88
  collectors_for(method_call).each do |collector|
@@ -1,40 +1,47 @@
1
1
  module Rack::Insight
2
-
3
2
  class RedisPanel < Panel
4
- require "rack/insight/panels/redis_panel/redis_extension"
5
-
6
3
  require "rack/insight/panels/redis_panel/stats"
7
4
 
8
- self.has_table = false
9
-
10
- def self.record(redis_command_args, backtrace, &block)
11
- return block.call unless Rack::Insight.enabled?
12
-
13
- start_time = Time.now
14
- result = block.call
15
- total_time = Time.now - start_time
16
- stats.record_call(total_time * 1_000, redis_command_args, backtrace)
17
- return result
5
+ def initialize(app)
6
+ super
7
+
8
+ unless is_probing?
9
+ probe(self) do
10
+ if defined?(Redis::Client)
11
+ # Redis >= 3.0.0
12
+ instrument "Redis::Client" do
13
+ instance_probe :call
14
+ end
15
+ elsif defined?(Redis)
16
+ # Redis < 3.0.0
17
+ instrument "Redis" do
18
+ instance_probe :call_command
19
+ end
20
+ end
21
+ end
22
+ end
18
23
  end
19
24
 
20
- def self.reset
21
- Thread.current["rack-insight.redis"] = Stats.new
25
+ def request_start(env, start)
26
+ @stats = Stats.new
22
27
  end
23
28
 
24
- def self.stats
25
- Thread.current["rack-insight.redis"] ||= Stats.new
29
+ def request_finish(env, status, headers, body, timing)
30
+ store(env, @stats)
31
+ @stats = nil
26
32
  end
27
33
 
28
- def heading
29
- "Redis: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
34
+ def after_detect(method_call, timing, args, message)
35
+ @stats.record_call(timing.duration, args, method_call)
30
36
  end
31
37
 
32
- def content
33
- result = render_template "panels/redis", :stats => self.class.stats
34
- self.class.reset
35
- return result
38
+ def heading_for_request(number)
39
+ stats = retrieve(number).first
40
+ "Redis: %.2fms (#{stats.queries.size} calls)" % stats.time
36
41
  end
37
42
 
43
+ def content_for_request(number)
44
+ render_template "panels/redis", :stats => retrieve(number).first
45
+ end
38
46
  end
39
-
40
47
  end
@@ -8,10 +8,10 @@ module Rack::Insight
8
8
  attr_reader :time
9
9
  attr_reader :command
10
10
 
11
- def initialize(time, command_args, backtrace)
11
+ def initialize(time, command_args, method_call)
12
12
  @time = time
13
13
  @command = command_args.inspect
14
- @backtrace = backtrace
14
+ @backtrace = method_call.backtrace
15
15
  end
16
16
 
17
17
  def display_time
@@ -28,8 +28,8 @@ module Rack::Insight
28
28
  @time = 0.0
29
29
  end
30
30
 
31
- def record_call(time, command_args, backtrace)
32
- @queries << Query.new(time, command_args, backtrace)
31
+ def record_call(time, command_args, method_call)
32
+ @queries << Query.new(time, command_args, method_call)
33
33
  @calls += 1
34
34
  @time += time
35
35
  end
@@ -1,39 +1,27 @@
1
1
  module Rack::Insight
2
-
3
2
  class SphinxPanel < Panel
4
- require "rack/insight/panels/sphinx_panel/sphinx_extension"
5
3
  require "rack/insight/panels/sphinx_panel/stats"
6
4
 
7
- self.has_table = false
8
-
9
- def self.record(*sphinx_command_args, &block)
10
- return block.call unless Rack::Insight.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
5
+ def request_start(env, start)
6
+ @stats = Stats.new
17
7
  end
18
8
 
19
- def self.reset
20
- Thread.current["rack-insight.sphinx"] = Stats.new
9
+ def request_finish(env, status, headers, body, timing)
10
+ store(env, @stats)
11
+ @stats = nil
21
12
  end
22
13
 
23
- def self.stats
24
- Thread.current["rack-insight.sphinx"] ||= Stats.new
14
+ def after_detect(method_call, timing, args, message)
15
+ @stats.record_call(timing.duration, args, method_call)
25
16
  end
26
17
 
27
- def heading
28
- "Sphinx: %.2fms (#{self.class.stats.queries.size} calls)" % self.class.stats.time
18
+ def heading_for_request(number)
19
+ stats = retrieve(number).first
20
+ "Sphinx: %.2fms (#{stats.queries.size} calls)" % stats.time
29
21
  end
30
22
 
31
- def content
32
- result = render_template "panels/sphinx", :stats => self.class.stats
33
- self.class.reset
34
- return result
23
+ def content_for_request(number)
24
+ render_template "panels/sphinx", :stats => retrieve(number).first
35
25
  end
36
-
37
26
  end
38
-
39
27
  end
@@ -3,16 +3,28 @@ module Rack::Insight
3
3
 
4
4
  class Stats
5
5
  class Query
6
+ include Rack::Insight::FilteredBacktrace
7
+
8
+ require 'riddle/client'
9
+ MatchModes = Riddle::Client::MatchModes.invert
10
+ RankModes = Riddle::Client::RankModes.invert
11
+ SortModes = Riddle::Client::SortModes.invert
12
+ AttributeTypes = Riddle::Client::AttributeTypes.invert
13
+ GroupFunctions = Riddle::Client::GroupFunctions.invert
14
+ FilterTypes = Riddle::Client::FilterTypes.invert
15
+
6
16
  attr_reader :time
7
17
  attr_reader :command
8
18
 
9
- def initialize(time, *command_args)
19
+ def initialize(time, command_args, method_call)
20
+ riddle_command, messages = *command_args
10
21
  @time = time
11
- if command_args.flatten.first == :search
12
- @command = "search: " + decode_message(command_args.first.flatten.last).collect{|k,v| "#{k} => #{v}"}.join(", ")
22
+ if riddle_command == :search
23
+ @command = "search: " + decode_message(messages.first).inspect
13
24
  else
14
- @command = command_args.flatten.first.to_s + ": No more info is available for this Sphinx request type"
25
+ @command = command_args.inspect + ": No more info is available for this Sphinx request type"
15
26
  end
27
+ @backtrace = method_call.backtrace
16
28
  end
17
29
 
18
30
  def display_time
@@ -23,43 +35,136 @@ module Rack::Insight
23
35
  @m = m.clone
24
36
  params = ActiveSupport::OrderedHash.new
25
37
 
38
+ # Mode, Limits
26
39
  params[:offset] = consume_int
27
40
  params[:limit] = consume_int
28
- params[:match_mode] = consume_int
29
- params[:rank_mode] = consume_int
30
- params[:sort_mode] = consume_int
31
- params[:sort_by] = consume_string
41
+ params[:match_mode] = MatchModes[consume_int]
42
+
43
+ # Ranking
44
+ params[:rank_mode] = RankModes[consume_int]
45
+ if params[:rank_mode] == :expr
46
+ params[:rank_expr] = consume_string
47
+ end
48
+
49
+ # Sort Mode
50
+ params[:sorting] = {
51
+ mode: SortModes[consume_int],
52
+ by: consume_string,
53
+ }
54
+
55
+ # Query
32
56
  params[:query] = consume_string
33
- wl = consume_int
34
- weights = []
35
- wl.times do weights << consume_int end
36
- params[:weights] = weights
37
57
 
58
+ # Weights
59
+ params[:weights] = (1..consume_int).map { consume_int }
60
+
61
+ # Index
38
62
  params[:index] = consume_string
39
63
 
40
- consume_string
64
+ # ID Range
65
+ consume_int
66
+ params[:id_range] = consume_64int..consume_64int
67
+
68
+ # Filters
69
+ params[:filters] = (1..consume_int).map do
70
+ attribute = consume_string
71
+ type = FilterTypes[consume_int]
72
+ values =
73
+ case type
74
+ when :values
75
+ (1..consume_int).map { consume_64int }
76
+ when :range
77
+ consume_64int..consume_64int
78
+ when :float_range
79
+ consume_float..consume_float
80
+ end
81
+ exclude = consume_int
82
+ {attribute: attribute, values: values, exclude: exclude}
83
+ end
84
+
85
+ # Grouping
86
+ params[:group] = {
87
+ function: GroupFunctions[consume_int],
88
+ by: consume_string,
89
+ max_matches: consume_int,
90
+ clause: consume_string,
91
+ retry: {cutoff: consume_int, count: consume_int, delay: consume_int},
92
+ distinct: consume_string,
93
+ }
94
+
95
+ # Anchor Point
96
+ if consume_int == 0
97
+ params[:anchor] = nil
98
+ else
99
+ params[:anchor] = {
100
+ attributes: [consume_string, consume_string],
101
+ values: [consume_int, consume_int],
102
+ }
103
+ end
104
+
105
+ # Per Index Weights
106
+ per_index_weights = params[:per_index_weights] = {}
107
+ (1..consume_int).each do |key, value|
108
+ key = consume_string
109
+ value = consume_int
110
+ per_index_weights[key] = value
111
+ end
112
+
113
+ # Max Query Time
114
+ params[:max_query_time] = consume_int
115
+
116
+ # Per Field Weights
117
+ per_field_weights = params[:per_field_weights] = {}
118
+ (1..consume_int).each do |key, value|
119
+ key = consume_string
120
+ value = consume_int
121
+ per_field_weights[key] = value
122
+ end
123
+
124
+ params[:comments] = consume_string
125
+
126
+ return params if Riddle::Client::Versions[:search] < 0x116
127
+
128
+ # Overrides
129
+ overrides = params[:overrides] = {}
130
+ (1..consume_int).each do
131
+ key = consume_string
132
+ type = AttributeTypes[consume_int]
133
+ method =
134
+ case type
135
+ when :float
136
+ :consume_float
137
+ when :bigint
138
+ :consume_64int
139
+ else
140
+ :consume_int
141
+ end
142
+ values = (1..consume_int).map { send(method) }
143
+ overrides[key] = values
144
+ end
145
+
146
+ params[:select] = consume_string
147
+
148
+ @m.empty? or
149
+ params[:unknown] = @m
41
150
 
42
- params[:id_range] = [consume_64int, consume_64int]
43
151
  params
44
152
  end
45
153
 
46
154
  def consume_int
47
- i = @m.unpack("N").first
48
- @m = @m.slice(4, @m.length - 4)
49
- i
155
+ @m.slice!(0, 4).unpack("N").first
50
156
  end
51
157
 
52
158
  def consume_64int
53
- i = @m.unpack("NN").first
54
- @m = @m.slice(8, @m.length - 8)
55
- i
159
+ @m.slice!(0, 8).unpack("NN").first
160
+ end
161
+
162
+ def consume_float
163
+ @m.slice!(0, 4).unpack('N').pack('L*').unpack('f').first
56
164
  end
57
165
 
58
166
  def consume_string
59
- len = consume_int
60
- s = @m.slice(0, len)
61
- @m = @m.slice(len, @m.length - len)
62
- s
167
+ @m.slice!(0, consume_int)
63
168
  end
64
169
  end
65
170
 
@@ -72,9 +177,8 @@ module Rack::Insight
72
177
  @time = 0.0
73
178
  end
74
179
 
75
- def record_call(time, *command_args)
76
-
77
- @queries << Query.new(time, command_args)
180
+ def record_call(time, command_args, method_call)
181
+ @queries << Query.new(time, command_args, method_call)
78
182
  @calls += 1
79
183
  @time += time
80
184
  end
@@ -1266,150 +1266,150 @@ jQuery.each({
1266
1266
  function num(elem, prop) {
1267
1267
  return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
1268
1268
  }
1269
- var expando = "jQuery" + now(), uuid = 0, windowData = {};
1270
-
1271
- jQuery.extend({
1272
- cache: {},
1273
-
1274
- data: function( elem, name, data ) {
1275
- elem = elem == window ?
1276
- windowData :
1277
- elem;
1278
-
1279
- var id = elem[ expando ];
1280
-
1281
- // Compute a unique ID for the element
1282
- if ( !id )
1283
- id = elem[ expando ] = ++uuid;
1284
-
1285
- // Only generate the data cache if we're
1286
- // trying to access or manipulate it
1287
- if ( name && !jQuery.cache[ id ] )
1288
- jQuery.cache[ id ] = {};
1289
-
1290
- // Prevent overriding the named cache with undefined values
1291
- if ( data !== undefined )
1292
- jQuery.cache[ id ][ name ] = data;
1293
-
1294
- // Return the named cache data, or the ID for the element
1295
- return name ?
1296
- jQuery.cache[ id ][ name ] :
1297
- id;
1298
- },
1299
-
1300
- removeData: function( elem, name ) {
1301
- elem = elem == window ?
1302
- windowData :
1303
- elem;
1304
-
1305
- var id = elem[ expando ];
1306
-
1307
- // If we want to remove a specific section of the element's data
1308
- if ( name ) {
1309
- if ( jQuery.cache[ id ] ) {
1310
- // Remove the section of cache data
1311
- delete jQuery.cache[ id ][ name ];
1312
-
1313
- // If we've removed all the data, remove the element's cache
1314
- name = "";
1315
-
1316
- for ( name in jQuery.cache[ id ] )
1317
- break;
1318
-
1319
- if ( !name )
1320
- jQuery.removeData( elem );
1321
- }
1322
-
1323
- // Otherwise, we want to remove all of the element's data
1324
- } else {
1325
- // Clean up the element expando
1326
- try {
1327
- delete elem[ expando ];
1328
- } catch(e){
1329
- // IE has trouble directly removing the expando
1330
- // but it's ok with using removeAttribute
1331
- if ( elem.removeAttribute )
1332
- elem.removeAttribute( expando );
1333
- }
1334
-
1335
- // Completely remove the data cache
1336
- delete jQuery.cache[ id ];
1337
- }
1338
- },
1339
- queue: function( elem, type, data ) {
1340
- if ( elem ){
1341
-
1342
- type = (type || "fx") + "queue";
1343
-
1344
- var q = jQuery.data( elem, type );
1345
-
1346
- if ( !q || jQuery.isArray(data) )
1347
- q = jQuery.data( elem, type, jQuery.makeArray(data) );
1348
- else if( data )
1349
- q.push( data );
1350
-
1351
- }
1352
- return q;
1353
- },
1354
-
1355
- dequeue: function( elem, type ){
1356
- var queue = jQuery.queue( elem, type ),
1357
- fn = queue.shift();
1358
-
1359
- if( !type || type === "fx" )
1360
- fn = queue[0];
1361
-
1362
- if( fn !== undefined )
1363
- fn.call(elem);
1364
- }
1365
- });
1366
-
1367
- jQuery.fn.extend({
1368
- data: function( key, value ){
1369
- var parts = key.split(".");
1370
- parts[1] = parts[1] ? "." + parts[1] : "";
1371
-
1372
- if ( value === undefined ) {
1373
- var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1374
-
1375
- if ( data === undefined && this.length )
1376
- data = jQuery.data( this[0], key );
1377
-
1378
- return data === undefined && parts[1] ?
1379
- this.data( parts[0] ) :
1380
- data;
1381
- } else
1382
- return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
1383
- jQuery.data( this, key, value );
1384
- });
1385
- },
1386
-
1387
- removeData: function( key ){
1388
- return this.each(function(){
1389
- jQuery.removeData( this, key );
1390
- });
1391
- },
1392
- queue: function(type, data){
1393
- if ( typeof type !== "string" ) {
1394
- data = type;
1395
- type = "fx";
1396
- }
1397
-
1398
- if ( data === undefined )
1399
- return jQuery.queue( this[0], type );
1400
-
1401
- return this.each(function(){
1402
- var queue = jQuery.queue( this, type, data );
1403
-
1404
- if( type == "fx" && queue.length == 1 )
1405
- queue[0].call(this);
1406
- });
1407
- },
1408
- dequeue: function(type){
1409
- return this.each(function(){
1410
- jQuery.dequeue( this, type );
1411
- });
1412
- }
1269
+ var expando = "jQuery" + now(), uuid = 0, windowData = {};
1270
+
1271
+ jQuery.extend({
1272
+ cache: {},
1273
+
1274
+ data: function( elem, name, data ) {
1275
+ elem = elem == window ?
1276
+ windowData :
1277
+ elem;
1278
+
1279
+ var id = elem[ expando ];
1280
+
1281
+ // Compute a unique ID for the element
1282
+ if ( !id )
1283
+ id = elem[ expando ] = ++uuid;
1284
+
1285
+ // Only generate the data cache if we're
1286
+ // trying to access or manipulate it
1287
+ if ( name && !jQuery.cache[ id ] )
1288
+ jQuery.cache[ id ] = {};
1289
+
1290
+ // Prevent overriding the named cache with undefined values
1291
+ if ( data !== undefined )
1292
+ jQuery.cache[ id ][ name ] = data;
1293
+
1294
+ // Return the named cache data, or the ID for the element
1295
+ return name ?
1296
+ jQuery.cache[ id ][ name ] :
1297
+ id;
1298
+ },
1299
+
1300
+ removeData: function( elem, name ) {
1301
+ elem = elem == window ?
1302
+ windowData :
1303
+ elem;
1304
+
1305
+ var id = elem[ expando ];
1306
+
1307
+ // If we want to remove a specific section of the element's data
1308
+ if ( name ) {
1309
+ if ( jQuery.cache[ id ] ) {
1310
+ // Remove the section of cache data
1311
+ delete jQuery.cache[ id ][ name ];
1312
+
1313
+ // If we've removed all the data, remove the element's cache
1314
+ name = "";
1315
+
1316
+ for ( name in jQuery.cache[ id ] )
1317
+ break;
1318
+
1319
+ if ( !name )
1320
+ jQuery.removeData( elem );
1321
+ }
1322
+
1323
+ // Otherwise, we want to remove all of the element's data
1324
+ } else {
1325
+ // Clean up the element expando
1326
+ try {
1327
+ delete elem[ expando ];
1328
+ } catch(e){
1329
+ // IE has trouble directly removing the expando
1330
+ // but it's ok with using removeAttribute
1331
+ if ( elem.removeAttribute )
1332
+ elem.removeAttribute( expando );
1333
+ }
1334
+
1335
+ // Completely remove the data cache
1336
+ delete jQuery.cache[ id ];
1337
+ }
1338
+ },
1339
+ queue: function( elem, type, data ) {
1340
+ if ( elem ){
1341
+
1342
+ type = (type || "fx") + "queue";
1343
+
1344
+ var q = jQuery.data( elem, type );
1345
+
1346
+ if ( !q || jQuery.isArray(data) )
1347
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
1348
+ else if( data )
1349
+ q.push( data );
1350
+
1351
+ }
1352
+ return q;
1353
+ },
1354
+
1355
+ dequeue: function( elem, type ){
1356
+ var queue = jQuery.queue( elem, type ),
1357
+ fn = queue.shift();
1358
+
1359
+ if( !type || type === "fx" )
1360
+ fn = queue[0];
1361
+
1362
+ if( fn !== undefined )
1363
+ fn.call(elem);
1364
+ }
1365
+ });
1366
+
1367
+ jQuery.fn.extend({
1368
+ data: function( key, value ){
1369
+ var parts = key.split(".");
1370
+ parts[1] = parts[1] ? "." + parts[1] : "";
1371
+
1372
+ if ( value === undefined ) {
1373
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1374
+
1375
+ if ( data === undefined && this.length )
1376
+ data = jQuery.data( this[0], key );
1377
+
1378
+ return data === undefined && parts[1] ?
1379
+ this.data( parts[0] ) :
1380
+ data;
1381
+ } else
1382
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
1383
+ jQuery.data( this, key, value );
1384
+ });
1385
+ },
1386
+
1387
+ removeData: function( key ){
1388
+ return this.each(function(){
1389
+ jQuery.removeData( this, key );
1390
+ });
1391
+ },
1392
+ queue: function(type, data){
1393
+ if ( typeof type !== "string" ) {
1394
+ data = type;
1395
+ type = "fx";
1396
+ }
1397
+
1398
+ if ( data === undefined )
1399
+ return jQuery.queue( this[0], type );
1400
+
1401
+ return this.each(function(){
1402
+ var queue = jQuery.queue( this, type, data );
1403
+
1404
+ if( type == "fx" && queue.length == 1 )
1405
+ queue[0].call(this);
1406
+ });
1407
+ },
1408
+ dequeue: function(type){
1409
+ return this.each(function(){
1410
+ jQuery.dequeue( this, type );
1411
+ });
1412
+ }
1413
1413
  });/*!
1414
1414
  * Sizzle CSS Selector Engine - v0.9.3
1415
1415
  * Copyright 2009, The Dojo Foundation
@@ -1,7 +1,7 @@
1
1
  module Rack
2
2
  module Insight
3
3
 
4
- VERSION = '0.5.23'
4
+ VERSION = '0.5.24'
5
5
 
6
6
  end
7
7
  end
@@ -16,6 +16,7 @@
16
16
  <tr>
17
17
  <th>Time&nbsp;(ms)</th>
18
18
  <th>Command</th>
19
+ <th class="backtrace"></th>
19
20
  </tr>
20
21
  </thead>
21
22
  <tbody>
@@ -24,7 +25,20 @@
24
25
  <tr class="<%= i % 2 == 0 ? "even" : "odd" %>">
25
26
  <td><%= query.display_time %></td>
26
27
  <td><%= query.command %></td>
28
+ <td><%= "<a href='#' class='reveal_backtrace'>Show Backtrace</a>" if query.has_backtrace? %></td>
27
29
  </tr>
30
+ <% if query.has_backtrace? %>
31
+ <tr style="display:none">
32
+ <td></td>
33
+ <td colspan="2">
34
+ <ul>
35
+ <% query.filtered_backtrace.each do |line| %>
36
+ <li><%=h line %></li>
37
+ <% end %>
38
+ </ul>
39
+ </td>
40
+ </tr>
41
+ <% end %>
28
42
  <% i += 1 %>
29
43
  <% end %>
30
44
  </tbody>
@@ -11,7 +11,7 @@
11
11
  @import url(/__insight__/insight.css);
12
12
  </style>
13
13
  <script>
14
- $(function($) {
14
+ jQuery(function($) {
15
15
  $.insight.request_id = <%= request_id %>
16
16
  if(document.readCookie('rack-insight_position')) {
17
17
  $('#rack-insight').removeClass('rack-insight_top rack-insight_bottom')
data/rack-insight.gemspec CHANGED
@@ -34,7 +34,5 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency "rspec", ">= 2.11.0"
35
35
  s.add_development_dependency "sinatra"
36
36
  s.add_development_dependency "webrat"
37
- s.add_development_dependency "ruby-debug19"
38
-
39
-
37
+ s.add_development_dependency "debugger"
40
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-insight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.23
4
+ version: 0.5.24
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-09-14 00:00:00.000000000 Z
15
+ date: 2013-01-02 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rack
@@ -175,7 +175,7 @@ dependencies:
175
175
  - !ruby/object:Gem::Version
176
176
  version: '0'
177
177
  - !ruby/object:Gem::Dependency
178
- name: ruby-debug19
178
+ name: debugger
179
179
  requirement: !ruby/object:Gem::Requirement
180
180
  none: false
181
181
  requirements:
@@ -251,7 +251,6 @@ files:
251
251
  - lib/rack/insight/panels/mongo_panel/stats.rb
252
252
  - lib/rack/insight/panels/rails_info_panel.rb
253
253
  - lib/rack/insight/panels/redis_panel.rb
254
- - lib/rack/insight/panels/redis_panel/redis_extension.rb
255
254
  - lib/rack/insight/panels/redis_panel/stats.rb
256
255
  - lib/rack/insight/panels/request_variables_panel.rb
257
256
  - lib/rack/insight/panels/speedtracer_panel.rb
@@ -387,4 +386,3 @@ test_files:
387
386
  - spec/rcov.opts
388
387
  - spec/spec.opts
389
388
  - spec/spec_helper.rb
390
- has_rdoc:
@@ -1,25 +0,0 @@
1
- if defined?(Redis)
2
- Redis.class_eval do
3
- if Redis.methods.include?('call_command') # older versions of redis-rb
4
- def call_command_with_insight(*argv)
5
- Rack::Insight::RedisPanel.record(argv, Kernel.caller) do
6
- call_command_without_insight(*argv)
7
- end
8
- end
9
-
10
- alias_method_chain :call_command, :insight
11
-
12
- elsif defined?(Redis::Client) # newer versions of redis-rb
13
-
14
- Redis::Client.class_eval do
15
- def call_with_insight(command, &block)
16
- Rack::Insight::RedisPanel.record(command, Kernel.caller) do
17
- call_without_insight(command, &block)
18
- end
19
- end
20
- end
21
-
22
- Redis::Client.alias_method_chain :call, :insight
23
- end
24
- end
25
- end