rack-mini-profiler 0.1.23 → 0.1.24

Sign up to get free protection for your applications and to get access to all the features.

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