rack-mini-profiler 2.3.4 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +65 -68
- data/lib/generators/rack_mini_profiler/USAGE +9 -0
- data/lib/generators/rack_mini_profiler/install_generator.rb +13 -0
- data/lib/generators/{rack_profiler/templates/rack_profiler.rb → rack_mini_profiler/templates/rack_mini_profiler.rb} +1 -1
- data/lib/generators/rack_profiler/install_generator.rb +6 -3
- data/lib/mini_profiler/config.rb +7 -4
- data/lib/mini_profiler/storage/abstract_store.rb +30 -57
- data/lib/mini_profiler/storage/file_store.rb +2 -0
- data/lib/mini_profiler/storage/memory_store.rb +56 -12
- data/lib/mini_profiler/storage/redis_store.rb +144 -61
- data/lib/mini_profiler/storage.rb +7 -0
- data/lib/mini_profiler/timer_struct/base.rb +2 -0
- data/lib/mini_profiler/timer_struct/sql.rb +2 -0
- data/lib/mini_profiler/timer_struct.rb +8 -0
- data/lib/mini_profiler/version.rb +1 -1
- data/lib/{mini_profiler/profiler.rb → mini_profiler.rb} +103 -69
- data/lib/patches/net_patches.rb +18 -17
- data/lib/rack-mini-profiler.rb +1 -24
- data/rack-mini-profiler.gemspec +2 -2
- metadata +12 -8
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'digest'
|
4
|
+
require 'securerandom'
|
4
5
|
|
5
6
|
module Rack
|
6
7
|
class MiniProfiler
|
@@ -133,85 +134,127 @@ unviewed_ids: #{get_unviewed_ids(user)}
|
|
133
134
|
)
|
134
135
|
end
|
135
136
|
|
136
|
-
def push_snapshot(page_struct, config)
|
137
|
-
|
138
|
-
|
137
|
+
def push_snapshot(page_struct, group_name, config)
|
138
|
+
group_zset_key = group_snapshot_zset_key(group_name)
|
139
|
+
group_hash_key = group_snapshot_hash_key(group_name)
|
140
|
+
overview_zset_key = snapshot_overview_zset_key
|
139
141
|
|
140
142
|
id = page_struct[:id]
|
141
|
-
score = page_struct.duration_ms
|
142
|
-
|
143
|
+
score = page_struct.duration_ms.to_s
|
144
|
+
|
145
|
+
per_group_limit = config.max_snapshots_per_group.to_s
|
146
|
+
groups_limit = config.max_snapshot_groups.to_s
|
143
147
|
bytes = Marshal.dump(page_struct)
|
144
148
|
|
145
149
|
lua = <<~LUA
|
146
|
-
local
|
147
|
-
local
|
150
|
+
local group_zset_key = KEYS[1]
|
151
|
+
local group_hash_key = KEYS[2]
|
152
|
+
local overview_zset_key = KEYS[3]
|
153
|
+
|
148
154
|
local id = ARGV[1]
|
149
155
|
local score = tonumber(ARGV[2])
|
150
|
-
local
|
151
|
-
local
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
156
|
+
local group_name = ARGV[3]
|
157
|
+
local per_group_limit = tonumber(ARGV[4])
|
158
|
+
local groups_limit = tonumber(ARGV[5])
|
159
|
+
local prefix = ARGV[6]
|
160
|
+
local bytes = ARGV[7]
|
161
|
+
|
162
|
+
local current_group_score = redis.call("ZSCORE", overview_zset_key, group_name)
|
163
|
+
if current_group_score == false or score > tonumber(current_group_score) then
|
164
|
+
redis.call("ZADD", overview_zset_key, score, group_name)
|
165
|
+
end
|
166
|
+
|
167
|
+
local do_save = true
|
168
|
+
local overview_size = redis.call("ZCARD", overview_zset_key)
|
169
|
+
while (overview_size > groups_limit) do
|
170
|
+
local lowest_group = redis.call("ZRANGE", overview_zset_key, 0, 0)[1]
|
171
|
+
redis.call("ZREM", overview_zset_key, lowest_group)
|
172
|
+
if lowest_group == group_name then
|
173
|
+
do_save = false
|
174
|
+
else
|
175
|
+
local lowest_group_zset_key = prefix .. "-mp-group-snapshot-zset-key-" .. lowest_group
|
176
|
+
local lowest_group_hash_key = prefix .. "-mp-group-snapshot-hash-key-" .. lowest_group
|
177
|
+
redis.call("DEL", lowest_group_zset_key, lowest_group_hash_key)
|
178
|
+
end
|
179
|
+
overview_size = overview_size - 1
|
180
|
+
end
|
181
|
+
|
182
|
+
if do_save then
|
183
|
+
redis.call("ZADD", group_zset_key, score, id)
|
184
|
+
local group_size = redis.call("ZCARD", group_zset_key)
|
185
|
+
while (group_size > per_group_limit) do
|
186
|
+
local lowest_snapshot_id = redis.call("ZRANGE", group_zset_key, 0, 0)[1]
|
187
|
+
redis.call("ZREM", group_zset_key, lowest_snapshot_id)
|
188
|
+
if lowest_snapshot_id == id then
|
189
|
+
do_save = false
|
190
|
+
else
|
191
|
+
redis.call("HDEL", group_hash_key, lowest_snapshot_id)
|
192
|
+
end
|
193
|
+
group_size = group_size - 1
|
194
|
+
end
|
195
|
+
if do_save then
|
196
|
+
redis.call("HSET", group_hash_key, id, bytes)
|
197
|
+
end
|
158
198
|
end
|
159
199
|
LUA
|
160
200
|
redis.eval(
|
161
201
|
lua,
|
162
|
-
keys: [
|
163
|
-
argv: [id, score,
|
202
|
+
keys: [group_zset_key, group_hash_key, overview_zset_key],
|
203
|
+
argv: [id, score, group_name, per_group_limit, groups_limit, @prefix, bytes]
|
164
204
|
)
|
165
205
|
end
|
166
206
|
|
167
|
-
def
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
batch.map! do |id, bytes|
|
181
|
-
begin
|
182
|
-
# rubocop:disable Security/MarshalLoad
|
183
|
-
Marshal.load(bytes)
|
184
|
-
# rubocop:enable Security/MarshalLoad
|
185
|
-
rescue
|
186
|
-
corrupt_snapshots << id
|
187
|
-
nil
|
188
|
-
end
|
207
|
+
def fetch_snapshots_overview
|
208
|
+
overview_zset_key = snapshot_overview_zset_key
|
209
|
+
groups = redis
|
210
|
+
.zrange(overview_zset_key, 0, -1, withscores: true)
|
211
|
+
.map { |(name, worst_score)| [name, { worst_score: worst_score }] }
|
212
|
+
|
213
|
+
prefixed_group_names = groups.map { |(group_name, _)| group_snapshot_zset_key(group_name) }
|
214
|
+
metadata = redis.eval(<<~LUA, keys: prefixed_group_names)
|
215
|
+
local metadata = {}
|
216
|
+
for i, k in ipairs(KEYS) do
|
217
|
+
local best = redis.call("ZRANGE", k, 0, 0, "WITHSCORES")[2]
|
218
|
+
local count = redis.call("ZCARD", k)
|
219
|
+
metadata[i] = {best, count}
|
189
220
|
end
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
221
|
+
return metadata
|
222
|
+
LUA
|
223
|
+
groups.each.with_index do |(_, hash), index|
|
224
|
+
best, count = metadata[index]
|
225
|
+
hash[:best_score] = best.to_f
|
226
|
+
hash[:snapshots_count] = count.to_i
|
227
|
+
end
|
228
|
+
groups.to_h
|
229
|
+
end
|
230
|
+
|
231
|
+
def fetch_snapshots_group(group_name)
|
232
|
+
group_hash_key = group_snapshot_hash_key(group_name)
|
233
|
+
snapshots = []
|
234
|
+
corrupt_snapshots = []
|
235
|
+
redis.hgetall(group_hash_key).each do |id, bytes|
|
236
|
+
# rubocop:disable Security/MarshalLoad
|
237
|
+
snapshots << Marshal.load(bytes)
|
238
|
+
# rubocop:enable Security/MarshalLoad
|
239
|
+
rescue
|
240
|
+
corrupt_snapshots << id
|
194
241
|
end
|
195
242
|
if corrupt_snapshots.size > 0
|
196
|
-
|
197
|
-
pipeline.zrem(zset_key, corrupt_snapshots)
|
198
|
-
pipeline.hdel(hash_key, corrupt_snapshots)
|
199
|
-
end
|
243
|
+
cleanup_corrupt_snapshots(corrupt_snapshots, group_name)
|
200
244
|
end
|
245
|
+
snapshots
|
201
246
|
end
|
202
247
|
|
203
|
-
def load_snapshot(id)
|
204
|
-
|
205
|
-
bytes = redis.hget(
|
248
|
+
def load_snapshot(id, group_name)
|
249
|
+
group_hash_key = group_snapshot_hash_key(group_name)
|
250
|
+
bytes = redis.hget(group_hash_key, id)
|
251
|
+
return if !bytes
|
206
252
|
begin
|
207
253
|
# rubocop:disable Security/MarshalLoad
|
208
254
|
Marshal.load(bytes)
|
209
255
|
# rubocop:enable Security/MarshalLoad
|
210
256
|
rescue
|
211
|
-
|
212
|
-
pipeline.zrem(snapshot_zset_key(), id)
|
213
|
-
pipeline.hdel(hash_key, id)
|
214
|
-
end
|
257
|
+
cleanup_corrupt_snapshots([id], group_name)
|
215
258
|
nil
|
216
259
|
end
|
217
260
|
end
|
@@ -237,12 +280,20 @@ unviewed_ids: #{get_unviewed_ids(user)}
|
|
237
280
|
@snapshot_counter_key ||= "#{@prefix}-mini-profiler-snapshots-counter"
|
238
281
|
end
|
239
282
|
|
240
|
-
def
|
241
|
-
|
283
|
+
def group_snapshot_zset_key(group_name)
|
284
|
+
# if you change this key, remember to change it in the LUA script in
|
285
|
+
# the push_snapshot method as well
|
286
|
+
"#{@prefix}-mp-group-snapshot-zset-key-#{group_name}"
|
242
287
|
end
|
243
288
|
|
244
|
-
def
|
245
|
-
|
289
|
+
def group_snapshot_hash_key(group_name)
|
290
|
+
# if you change this key, remember to change it in the LUA script in
|
291
|
+
# the push_snapshot method as well
|
292
|
+
"#{@prefix}-mp-group-snapshot-hash-key-#{group_name}"
|
293
|
+
end
|
294
|
+
|
295
|
+
def snapshot_overview_zset_key
|
296
|
+
"#{@prefix}-mp-overviewgroup-snapshot-zset-key"
|
246
297
|
end
|
247
298
|
|
248
299
|
def cached_redis_eval(script, script_sha, reraise: true, argv: [], keys: [])
|
@@ -257,12 +308,44 @@ unviewed_ids: #{get_unviewed_ids(user)}
|
|
257
308
|
end
|
258
309
|
end
|
259
310
|
|
311
|
+
def cleanup_corrupt_snapshots(corrupt_snapshots_ids, group_name)
|
312
|
+
group_hash_key = group_snapshot_hash_key(group_name)
|
313
|
+
group_zset_key = group_snapshot_zset_key(group_name)
|
314
|
+
overview_zset_key = snapshot_overview_zset_key
|
315
|
+
lua = <<~LUA
|
316
|
+
local group_hash_key = KEYS[1]
|
317
|
+
local group_zset_key = KEYS[2]
|
318
|
+
local overview_zset_key = KEYS[3]
|
319
|
+
local group_name = ARGV[1]
|
320
|
+
for i, k in ipairs(ARGV) do
|
321
|
+
if k ~= group_name then
|
322
|
+
redis.call("HDEL", group_hash_key, k)
|
323
|
+
redis.call("ZREM", group_zset_key, k)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
if redis.call("ZCARD", group_zset_key) == 0 then
|
327
|
+
redis.call("ZREM", overview_zset_key, group_name)
|
328
|
+
redis.call("DEL", group_hash_key, group_zset_key)
|
329
|
+
else
|
330
|
+
local worst_score = tonumber(redis.call("ZRANGE", group_zset_key, -1, -1, "WITHSCORES")[2])
|
331
|
+
redis.call("ZADD", overview_zset_key, worst_score, group_name)
|
332
|
+
end
|
333
|
+
LUA
|
334
|
+
redis.eval(
|
335
|
+
lua,
|
336
|
+
keys: [group_hash_key, group_zset_key, overview_zset_key],
|
337
|
+
argv: [group_name, *corrupt_snapshots_ids]
|
338
|
+
)
|
339
|
+
end
|
340
|
+
|
260
341
|
# only used in tests
|
261
342
|
def wipe_snapshots_data
|
343
|
+
keys = redis.keys(group_snapshot_hash_key('*'))
|
344
|
+
keys += redis.keys(group_snapshot_zset_key('*'))
|
262
345
|
redis.del(
|
263
|
-
|
264
|
-
|
265
|
-
|
346
|
+
keys,
|
347
|
+
snapshot_overview_zset_key,
|
348
|
+
snapshot_counter_key
|
266
349
|
)
|
267
350
|
end
|
268
351
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mini_profiler/timer_struct/base'
|
4
|
+
require 'mini_profiler/timer_struct/page'
|
5
|
+
require 'mini_profiler/timer_struct/sql'
|
6
|
+
require 'mini_profiler/timer_struct/custom'
|
7
|
+
require 'mini_profiler/timer_struct/client'
|
8
|
+
require 'mini_profiler/timer_struct/request'
|