rack-mini-profiler 0.1.23 → 0.1.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.

Potentially problematic release.


This version of rack-mini-profiler might be problematic. Click here for more details.

@@ -2,17 +2,19 @@ module Rack
2
2
  class MiniProfiler
3
3
  class MemcacheStore < AbstractStore
4
4
 
5
- EXPIRE_SECONDS = 60*60*24
5
+ EXPIRES_IN_SECONDS = 60 * 60 * 24
6
6
  MAX_RETRIES = 10
7
7
 
8
- def initialize(client = nil, prefix = "MPMemcacheStore")
8
+ def initialize(args = nil)
9
9
  require 'dalli' unless defined? Dalli
10
- @prefix = prefix
11
- @client = client || Dalli::Client.new(['localhost:11211'])
10
+ args ||= {}
11
+ @prefix = args[:prefix] || "MPMemcacheStore"
12
+ @client = args[:client] || Dalli::Client.new
13
+ @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
12
14
  end
13
15
 
14
16
  def save(page_struct)
15
- @client.set("#{@prefix}#{page_struct['Id']}", Marshal::dump(page_struct), EXPIRE_SECONDS)
17
+ @client.set("#{@prefix}#{page_struct['Id']}", Marshal::dump(page_struct), @expires_in_seconds)
16
18
  end
17
19
 
18
20
  def load(id)
@@ -23,9 +25,9 @@ module Rack
23
25
  end
24
26
 
25
27
  def set_unviewed(user, id)
26
- @client.add("#{@prefix}-#{user}-v", [], EXPIRE_SECONDS)
28
+ @client.add("#{@prefix}-#{user}-v", [], @expires_in_seconds)
27
29
  MAX_RETRIES.times do
28
- break if @client.cas("#{@prefix}-#{user}-v", EXPIRE_SECONDS) do |ids|
30
+ break if @client.cas("#{@prefix}-#{user}-v", @expires_in_seconds) do |ids|
29
31
  ids << id unless ids.include?(id)
30
32
  ids
31
33
  end
@@ -33,9 +35,9 @@ module Rack
33
35
  end
34
36
 
35
37
  def set_viewed(user, id)
36
- @client.add("#{@prefix}-#{user}-v", [], EXPIRE_SECONDS)
38
+ @client.add("#{@prefix}-#{user}-v", [], @expires_in_seconds)
37
39
  MAX_RETRIES.times do
38
- break if @client.cas("#{@prefix}-#{user}-v", EXPIRE_SECONDS) do |ids|
40
+ break if @client.cas("#{@prefix}-#{user}-v", @expires_in_seconds) do |ids|
39
41
  ids.delete id
40
42
  ids
41
43
  end
@@ -1,63 +1,65 @@
1
- module Rack
2
- class MiniProfiler
3
- class MemoryStore < AbstractStore
4
-
5
- EXPIRE_TIMER_CACHE = 3600 * 24
6
-
7
- def initialize(args)
8
- @timer_struct_lock = Mutex.new
9
- @timer_struct_cache = {}
10
- @user_view_lock = Mutex.new
11
- @user_view_cache = {}
12
-
13
- # TODO: fix it to use weak ref, trouble is may be broken in 1.9 so need to use the 'ref' gem
14
- me = self
15
- Thread.new do
16
- while true do
17
- me.cleanup_cache
18
- sleep(3600)
19
- end
20
- end
21
- end
22
-
23
- def save(page_struct)
24
- @timer_struct_lock.synchronize {
25
- @timer_struct_cache[page_struct['Id']] = page_struct
26
- }
27
- end
28
-
29
- def load(id)
30
- @timer_struct_lock.synchronize {
31
- @timer_struct_cache[id]
32
- }
33
- end
34
-
35
- def set_unviewed(user, id)
36
- @user_view_lock.synchronize {
37
- @user_view_cache[user] ||= []
38
- @user_view_cache[user] << id
39
- }
40
- end
41
-
42
- def set_viewed(user, id)
43
- @user_view_lock.synchronize {
44
- @user_view_cache[user] ||= []
45
- @user_view_cache[user].delete(id)
46
- }
47
- end
48
-
49
- def get_unviewed_ids(user)
50
- @user_view_lock.synchronize {
51
- @user_view_cache[user]
52
- }
53
- end
54
-
55
- def cleanup_cache
56
- expire_older_than = ((Time.now.to_f - MiniProfiler::MemoryStore::EXPIRE_TIMER_CACHE) * 1000).to_i
57
- @timer_struct_lock.synchronize {
58
- @timer_struct_cache.delete_if { |k, v| v['Started'] < expire_older_than }
59
- }
60
- end
61
- end
62
- end
63
- end
1
+ module Rack
2
+ class MiniProfiler
3
+ class MemoryStore < AbstractStore
4
+
5
+ EXPIRES_IN_SECONDS = 60 * 60 * 24
6
+
7
+ def initialize(args = nil)
8
+ args ||= {}
9
+ @expires_in_seconds = args[:expires_in] || EXPIRES_IN_SECONDS
10
+ @timer_struct_lock = Mutex.new
11
+ @timer_struct_cache = {}
12
+ @user_view_lock = Mutex.new
13
+ @user_view_cache = {}
14
+
15
+ # TODO: fix it to use weak ref, trouble is may be broken in 1.9 so need to use the 'ref' gem
16
+ me = self
17
+ Thread.new do
18
+ while true do
19
+ me.cleanup_cache
20
+ sleep(3600)
21
+ end
22
+ end
23
+ end
24
+
25
+ def save(page_struct)
26
+ @timer_struct_lock.synchronize {
27
+ @timer_struct_cache[page_struct['Id']] = page_struct
28
+ }
29
+ end
30
+
31
+ def load(id)
32
+ @timer_struct_lock.synchronize {
33
+ @timer_struct_cache[id]
34
+ }
35
+ end
36
+
37
+ def set_unviewed(user, id)
38
+ @user_view_lock.synchronize {
39
+ @user_view_cache[user] ||= []
40
+ @user_view_cache[user] << id
41
+ }
42
+ end
43
+
44
+ def set_viewed(user, id)
45
+ @user_view_lock.synchronize {
46
+ @user_view_cache[user] ||= []
47
+ @user_view_cache[user].delete(id)
48
+ }
49
+ end
50
+
51
+ def get_unviewed_ids(user)
52
+ @user_view_lock.synchronize {
53
+ @user_view_cache[user]
54
+ }
55
+ end
56
+
57
+ def cleanup_cache
58
+ expire_older_than = ((Time.now.to_f - @expires_in_seconds) * 1000).to_i
59
+ @timer_struct_lock.synchronize {
60
+ @timer_struct_cache.delete_if { |k, v| v['Started'] < expire_older_than }
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -2,15 +2,17 @@ module Rack
2
2
  class MiniProfiler
3
3
  class RedisStore < AbstractStore
4
4
 
5
- EXPIRE_SECONDS = 60 * 60 * 24
5
+ EXPIRES_IN_SECONDS = 60 * 60 * 24
6
6
 
7
- def initialize(args)
7
+ def initialize(args = nil)
8
8
  @args = args || {}
9
9
  @prefix = @args.delete(:prefix) || 'MPRedisStore'
10
+ @redis_connection = @args.delete(:connection)
11
+ @expires_in_seconds = @args.delete(:expires_in) || EXPIRES_IN_SECONDS
10
12
  end
11
13
 
12
14
  def save(page_struct)
13
- redis.setex "#{@prefix}#{page_struct['Id']}", EXPIRE_SECONDS, Marshal::dump(page_struct)
15
+ redis.setex "#{@prefix}#{page_struct['Id']}", @expires_in_seconds, Marshal::dump(page_struct)
14
16
  end
15
17
 
16
18
  def load(id)
@@ -32,11 +34,19 @@ module Rack
32
34
  redis.smembers "#{@prefix}-#{user}-v"
33
35
  end
34
36
 
37
+ def diagnostics(user)
38
+ "Redis prefix: #{@prefix}
39
+ Redis location: #{redis.client.host}:#{redis.client.port} db: #{redis.client.db}
40
+ unviewed_ids: #{get_unviewed_ids(user)}
41
+ "
42
+ end
43
+
35
44
  private
36
45
 
37
46
  def redis
47
+ return @redis_connection if @redis_connection
38
48
  require 'redis' unless defined? Redis
39
- Redis.new @args
49
+ @redis_connection ||= Redis.new @args
40
50
  end
41
51
 
42
52
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
- class MiniProfiler
3
- VERSION = '33d69ecf833daec8db07a9a0b6cf0bd3'.freeze
2
+ class MiniProfiler
3
+ VERSION = '843cab636fb537adf19b58eff230ff75'.freeze
4
4
  end
5
5
  end
@@ -8,32 +8,32 @@ class SqlPatches
8
8
  @patched = val
9
9
  end
10
10
 
11
- def self.class_exists?(name)
12
- eval(name + ".class").to_s.eql?('Class')
13
- rescue NameError
14
- false
15
- end
16
-
11
+ def self.class_exists?(name)
12
+ eval(name + ".class").to_s.eql?('Class')
13
+ rescue NameError
14
+ false
15
+ end
16
+
17
17
  def self.module_exists?(name)
18
- eval(name + ".class").to_s.eql?('Module')
19
- rescue NameError
20
- false
21
- end
18
+ eval(name + ".class").to_s.eql?('Module')
19
+ rescue NameError
20
+ false
21
+ end
22
22
  end
23
23
 
24
24
  # The best kind of instrumentation is in the actual db provider, however we don't want to double instrument
25
25
  if SqlPatches.class_exists? "Mysql2::Client"
26
-
26
+
27
27
  class Mysql2::Result
28
28
  alias_method :each_without_profiling, :each
29
29
  def each(*args, &blk)
30
30
  return each_without_profiling(*args, &blk) unless @miniprofiler_sql_id
31
31
 
32
32
  start = Time.now
33
- result = each_without_profiling(*args,&blk)
33
+ result = each_without_profiling(*args,&blk)
34
34
  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
35
35
 
36
- @miniprofiler_sql_id.report_reader_duration(elapsed_time)
36
+ @miniprofiler_sql_id.report_reader_duration(elapsed_time)
37
37
  result
38
38
  end
39
39
  end
@@ -42,7 +42,7 @@ if SqlPatches.class_exists? "Mysql2::Client"
42
42
  alias_method :query_without_profiling, :query
43
43
  def query(*args,&blk)
44
44
  current = ::Rack::MiniProfiler.current
45
- return query_without_profiling(*args,&blk) unless current
45
+ return query_without_profiling(*args,&blk) unless current && current.measure
46
46
 
47
47
  start = Time.now
48
48
  result = query_without_profiling(*args,&blk)
@@ -53,14 +53,14 @@ if SqlPatches.class_exists? "Mysql2::Client"
53
53
 
54
54
  end
55
55
  end
56
-
56
+
57
57
  SqlPatches.patched = true
58
58
  end
59
59
 
60
60
 
61
- # PG patches, keep in mind exec and async_exec have a exec{|r| } semantics that is yet to be implemented
61
+ # PG patches, keep in mind exec and async_exec have a exec{|r| } semantics that is yet to be implemented
62
62
  if SqlPatches.class_exists? "PG::Result"
63
-
63
+
64
64
  class PG::Result
65
65
  alias_method :each_without_profiling, :each
66
66
  alias_method :values_without_profiling, :values
@@ -69,10 +69,10 @@ if SqlPatches.class_exists? "PG::Result"
69
69
  return values_without_profiling(*args, &blk) unless @miniprofiler_sql_id
70
70
 
71
71
  start = Time.now
72
- result = values_without_profiling(*args,&blk)
72
+ result = values_without_profiling(*args,&blk)
73
73
  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
74
74
 
75
- @miniprofiler_sql_id.report_reader_duration(elapsed_time)
75
+ @miniprofiler_sql_id.report_reader_duration(elapsed_time)
76
76
  result
77
77
  end
78
78
 
@@ -80,10 +80,10 @@ if SqlPatches.class_exists? "PG::Result"
80
80
  return each_without_profiling(*args, &blk) unless @miniprofiler_sql_id
81
81
 
82
82
  start = Time.now
83
- result = each_without_profiling(*args,&blk)
83
+ result = each_without_profiling(*args,&blk)
84
84
  elapsed_time = ((Time.now - start).to_f * 1000).round(1)
85
85
 
86
- @miniprofiler_sql_id.report_reader_duration(elapsed_time)
86
+ @miniprofiler_sql_id.report_reader_duration(elapsed_time)
87
87
  result
88
88
  end
89
89
  end
@@ -96,23 +96,23 @@ if SqlPatches.class_exists? "PG::Result"
96
96
  alias_method :prepare_without_profiling, :prepare
97
97
 
98
98
  def prepare(*args,&blk)
99
- # we have no choice but to do this here,
100
- # if we do the check for profiling first, our cache may miss critical stuff
101
-
99
+ # we have no choice but to do this here,
100
+ # if we do the check for profiling first, our cache may miss critical stuff
101
+
102
102
  @prepare_map ||= {}
103
103
  @prepare_map[args[0]] = args[1]
104
104
  # dont leak more than 10k ever
105
105
  @prepare_map = {} if @prepare_map.length > 1000
106
106
 
107
107
  current = ::Rack::MiniProfiler.current
108
- return prepare_without_profiling(*args,&blk) unless current
108
+ return prepare_without_profiling(*args,&blk) unless current && current.measure
109
109
 
110
- prepare_without_profiling(*args,&blk)
110
+ prepare_without_profiling(*args,&blk)
111
111
  end
112
112
 
113
113
  def exec(*args,&blk)
114
114
  current = ::Rack::MiniProfiler.current
115
- return exec_without_profiling(*args,&blk) unless current
115
+ return exec_without_profiling(*args,&blk) unless current && current.measure
116
116
 
117
117
  start = Time.now
118
118
  result = exec_without_profiling(*args,&blk)
@@ -124,7 +124,7 @@ if SqlPatches.class_exists? "PG::Result"
124
124
 
125
125
  def exec_prepared(*args,&blk)
126
126
  current = ::Rack::MiniProfiler.current
127
- return exec_prepared_without_profiling(*args,&blk) unless current
127
+ return exec_prepared_without_profiling(*args,&blk) unless current && current.measure
128
128
 
129
129
  start = Time.now
130
130
  result = exec_prepared_without_profiling(*args,&blk)
@@ -135,10 +135,10 @@ if SqlPatches.class_exists? "PG::Result"
135
135
 
136
136
  result
137
137
  end
138
-
138
+
139
139
  def send_query_prepared(*args,&blk)
140
140
  current = ::Rack::MiniProfiler.current
141
- return send_query_prepared_without_profiling(*args,&blk) unless current
141
+ return send_query_prepared_without_profiling(*args,&blk) unless current && current.measure
142
142
 
143
143
  start = Time.now
144
144
  result = send_query_prepared_without_profiling(*args,&blk)
@@ -149,10 +149,10 @@ if SqlPatches.class_exists? "PG::Result"
149
149
 
150
150
  result
151
151
  end
152
-
152
+
153
153
  def async_exec(*args,&blk)
154
154
  current = ::Rack::MiniProfiler.current
155
- return exec_without_profiling(*args,&blk) unless current
155
+ return exec_without_profiling(*args,&blk) unless current && current.measure
156
156
 
157
157
  start = Time.now
158
158
  result = exec_without_profiling(*args,&blk)
@@ -161,10 +161,10 @@ if SqlPatches.class_exists? "PG::Result"
161
161
 
162
162
  result
163
163
  end
164
-
164
+
165
165
  alias_method :query, :exec
166
166
  end
167
-
167
+
168
168
  SqlPatches.patched = true
169
169
  end
170
170
 
@@ -175,7 +175,7 @@ if SqlPatches.class_exists?("Moped::Node")
175
175
  alias_method :process_without_profiling, :process
176
176
  def process(*args,&blk)
177
177
  current = ::Rack::MiniProfiler.current
178
- return process_without_profiling(*args,&blk) unless current
178
+ return process_without_profiling(*args,&blk) unless current && current.measure
179
179
 
180
180
  start = Time.now
181
181
  result = process_without_profiling(*args,&blk)
@@ -187,19 +187,41 @@ if SqlPatches.class_exists?("Moped::Node")
187
187
  end
188
188
  end
189
189
 
190
+ if SqlPatches.class_exists?("RSolr::Connection") && RSolr::VERSION[0] != "0" # requires at least v1.0.0
191
+ class RSolr::Connection
192
+ alias_method :execute_without_profiling, :execute
193
+ def execute_with_profiling(client, request_context)
194
+ current = ::Rack::MiniProfiler.current
195
+ return execute_without_profiling(client, request_context) unless current && current.measure
196
+
197
+ start = Time.now
198
+ result = execute_without_profiling(client, request_context)
199
+ elapsed_time = ((Time.now - start).to_f * 1000).round(1)
200
+
201
+ data = "#{request_context[:method].upcase} #{request_context[:uri]}"
202
+ if request_context[:method] == :post and request_context[:data]
203
+ data << "\n#{Rack::Utils.unescape(request_context[:data])}"
204
+ end
205
+ result.instance_variable_set("@miniprofiler_sql_id", ::Rack::MiniProfiler.record_sql(data, elapsed_time))
206
+
207
+ result
208
+ end
209
+ alias_method :execute, :execute_with_profiling
210
+ end
211
+ end
190
212
 
191
213
 
192
214
  # Fallback for sequel
193
215
  if SqlPatches.class_exists?("Sequel::Database") && !SqlPatches.patched?
194
- module Sequel
195
- class Database
196
- alias_method :log_duration_original, :log_duration
197
- def log_duration(duration, message)
198
- ::Rack::MiniProfiler.record_sql(message, duration)
199
- log_duration_original(duration, message)
200
- end
201
- end
202
- end
216
+ module Sequel
217
+ class Database
218
+ alias_method :log_duration_original, :log_duration
219
+ def log_duration(duration, message)
220
+ ::Rack::MiniProfiler.record_sql(message, duration)
221
+ log_duration_original(duration, message)
222
+ end
223
+ end
224
+ end
203
225
  end
204
226
 
205
227
 
@@ -207,7 +229,7 @@ end
207
229
  ## fallback for alls sorts of weird dbs
208
230
  if SqlPatches.module_exists?('ActiveRecord') && !SqlPatches.patched?
209
231
  module Rack
210
- class MiniProfiler
232
+ class MiniProfiler
211
233
  module ActiveRecordInstrumentation
212
234
  def self.included(instrumented_class)
213
235
  instrumented_class.class_eval do
@@ -221,12 +243,12 @@ if SqlPatches.module_exists?('ActiveRecord') && !SqlPatches.patched?
221
243
 
222
244
  def log_with_miniprofiler(*args, &block)
223
245
  current = ::Rack::MiniProfiler.current
224
- return log_without_miniprofiler(*args, &block) unless current
246
+ return log_without_miniprofiler(*args, &block) unless current && current.measure
225
247
 
226
248
  sql, name, binds = args
227
249
  t0 = Time.now
228
250
  rval = log_without_miniprofiler(*args, &block)
229
-
251
+
230
252
  # Don't log schema queries if the option is set
231
253
  return rval if Rack::MiniProfiler.config.skip_schema_queries and name =~ /SCHEMA/
232
254
 
@@ -237,7 +259,7 @@ if SqlPatches.module_exists?('ActiveRecord') && !SqlPatches.patched?
237
259
  end
238
260
  end
239
261
 
240
- def self.insert_instrumentation
262
+ def self.insert_instrumentation
241
263
  ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
242
264
  include ::Rack::MiniProfiler::ActiveRecordInstrumentation
243
265
  end