rack-mini-profiler 0.10.2 → 0.10.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +14 -0
- data/lib/html/includes.css +303 -461
- data/lib/html/includes.js +16 -7
- data/lib/html/{includes.less → includes.scss} +50 -49
- data/lib/html/includes.tmpl +1 -1
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/profiler.rb +3 -13
- data/lib/mini_profiler/storage/redis_store.rb +30 -11
- data/lib/mini_profiler/timer_struct/sql.rb +5 -2
- data/lib/mini_profiler/version.rb +1 -1
- data/lib/patches/db/mysql2.rb +1 -1
- data/lib/patches/db/oracle_enhanced.rb +1 -1
- data/lib/patches/db/pg.rb +32 -7
- data/rack-mini-profiler.gemspec +2 -3
- metadata +8 -22
data/lib/html/includes.js
CHANGED
@@ -366,7 +366,7 @@ var MiniProfiler = (function () {
|
|
366
366
|
};
|
367
367
|
|
368
368
|
var bindDocumentEvents = function () {
|
369
|
-
$(document).
|
369
|
+
$(document).on('click.mini-profiler keyup.mini-profiler', function (e) {
|
370
370
|
|
371
371
|
// this happens on every keystroke, and :visible is crazy expensive in IE <9
|
372
372
|
// and in this case, the display:none check is sufficient.
|
@@ -399,19 +399,19 @@ var MiniProfiler = (function () {
|
|
399
399
|
popupHide(button, popup);
|
400
400
|
}
|
401
401
|
});
|
402
|
-
$(document).
|
402
|
+
$(document).on('keydown.mini-profiler', options.toggleShortcut, function(e) {
|
403
403
|
$('.profiler-results').toggle();
|
404
404
|
});
|
405
405
|
|
406
406
|
if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
|
407
|
-
$(document).
|
407
|
+
$(document).on('page:change.mini-profiler turbolinks:load.mini-profiler', function() {
|
408
408
|
unbindDocumentEvents();
|
409
409
|
});
|
410
410
|
}
|
411
411
|
};
|
412
412
|
|
413
413
|
var unbindDocumentEvents = function() {
|
414
|
-
$(document).
|
414
|
+
$(document).off('.mini-profiler');
|
415
415
|
};
|
416
416
|
|
417
417
|
var initFullView = function () {
|
@@ -500,11 +500,11 @@ var MiniProfiler = (function () {
|
|
500
500
|
// fetch profile results for any ajax calls
|
501
501
|
// note, this does not use $ cause we want to hook into the main jQuery
|
502
502
|
if (jQuery && jQuery(document) && jQuery(document).ajaxComplete) {
|
503
|
-
jQuery(document).
|
503
|
+
jQuery(document).on('ajaxComplete.mini-profiler', jQueryAjaxComplete);
|
504
504
|
}
|
505
505
|
|
506
506
|
if (jQuery && jQuery(document).ajaxStart)
|
507
|
-
jQuery(document).
|
507
|
+
jQuery(document).on('ajaxStart.mini-profiler', function () { ajaxStartTime = new Date(); });
|
508
508
|
|
509
509
|
// fetch results after ASP Ajax calls
|
510
510
|
if (typeof (Sys) != 'undefined' && typeof (Sys.WebForms) != 'undefined' && typeof (Sys.WebForms.PageRequestManager) != 'undefined') {
|
@@ -990,7 +990,16 @@ var MiniProfiler = (function () {
|
|
990
990
|
fetchResultsExposed: function (ids) {
|
991
991
|
return fetchResults(ids);
|
992
992
|
},
|
993
|
-
|
993
|
+
|
994
|
+
formatParameters: function (parameters) {
|
995
|
+
if (parameters != null) {
|
996
|
+
return parameters.map(function(item, index){ return "["+item[0]+", "+ item[1] +"]";}).join(', ');
|
997
|
+
}
|
998
|
+
else {
|
999
|
+
return '';
|
1000
|
+
}
|
1001
|
+
},
|
1002
|
+
|
994
1003
|
formatDuration: function (duration) {
|
995
1004
|
return (duration || 0).toFixed(1);
|
996
1005
|
}
|
@@ -1,17 +1,17 @@
|
|
1
|
-
|
2
|
-
-moz-box-shadow:
|
3
|
-
-webkit-box-shadow:
|
4
|
-
box-shadow:
|
1
|
+
@mixin box-shadow($dx, $dy, $radius, $color) {
|
2
|
+
-moz-box-shadow: $dx $dy $radius $color;
|
3
|
+
-webkit-box-shadow: $dx $dy $radius $color;
|
4
|
+
box-shadow: $dx $dy $radius $color;
|
5
5
|
}
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
$anchorColor: #0077CC;
|
8
|
+
$buttonBorderColor: #888;
|
9
|
+
$numberColor: #111;
|
10
|
+
$textColor: #555;
|
11
|
+
$mutedColor: #aaa;
|
12
|
+
$normalFonts: Helvetica, Arial, sans-serif;
|
13
|
+
$codeFonts: Consolas, monospace, serif;
|
14
|
+
$zindex:2147483640; // near 32bit max 2147483647
|
15
15
|
|
16
16
|
// do some resets
|
17
17
|
.profiler-result, .profiler-queries {
|
@@ -36,7 +36,7 @@
|
|
36
36
|
}
|
37
37
|
a, a:hover {
|
38
38
|
cursor:pointer;
|
39
|
-
color
|
39
|
+
color:$anchorColor;
|
40
40
|
}
|
41
41
|
a {
|
42
42
|
text-decoration:none;
|
@@ -54,37 +54,35 @@
|
|
54
54
|
{
|
55
55
|
float: right;
|
56
56
|
}
|
57
|
-
|
58
57
|
table.profiler-client-timings
|
59
58
|
{
|
60
59
|
margin-top: 10px;
|
61
60
|
}
|
62
|
-
|
63
|
-
font-family:@normalFonts;
|
61
|
+
font-family:$normalFonts;
|
64
62
|
|
65
63
|
.profiler-label {
|
66
|
-
color
|
64
|
+
color:$textColor;
|
67
65
|
overflow:hidden;
|
68
66
|
text-overflow: ellipsis;
|
69
67
|
}
|
70
68
|
|
71
69
|
.profiler-unit {
|
72
|
-
color
|
70
|
+
color:$mutedColor;
|
73
71
|
}
|
74
72
|
|
75
73
|
.profiler-trivial {
|
76
74
|
display:none;
|
77
75
|
td, td * {
|
78
|
-
color
|
76
|
+
color:$mutedColor !important;
|
79
77
|
}
|
80
78
|
}
|
81
79
|
|
82
80
|
pre, code, .profiler-number, .profiler-unit {
|
83
|
-
font-family
|
81
|
+
font-family:$codeFonts;
|
84
82
|
}
|
85
83
|
|
86
84
|
.profiler-number {
|
87
|
-
color
|
85
|
+
color:$numberColor;
|
88
86
|
}
|
89
87
|
|
90
88
|
.profiler-info {
|
@@ -96,11 +94,11 @@
|
|
96
94
|
white-space:nowrap;
|
97
95
|
}
|
98
96
|
}
|
99
|
-
|
97
|
+
|
100
98
|
.profiler-timings {
|
101
99
|
th {
|
102
100
|
background-color:#fff;
|
103
|
-
color
|
101
|
+
color:$mutedColor;
|
104
102
|
text-align:right;
|
105
103
|
}
|
106
104
|
th, td {
|
@@ -110,7 +108,7 @@
|
|
110
108
|
display:none;
|
111
109
|
}
|
112
110
|
.profiler-duration {
|
113
|
-
|
111
|
+
color:$numberColor;
|
114
112
|
text-align:right;
|
115
113
|
}
|
116
114
|
.profiler-indent {
|
@@ -118,7 +116,7 @@
|
|
118
116
|
}
|
119
117
|
.profiler-queries-show {
|
120
118
|
.profiler-number, .profiler-unit {
|
121
|
-
color
|
119
|
+
color:$anchorColor;
|
122
120
|
}
|
123
121
|
}
|
124
122
|
.profiler-queries-duration {
|
@@ -152,7 +150,7 @@
|
|
152
150
|
}
|
153
151
|
|
154
152
|
.profiler-queries {
|
155
|
-
font-family
|
153
|
+
font-family:$normalFonts;
|
156
154
|
|
157
155
|
.profiler-stack-trace {
|
158
156
|
margin-bottom:15px;
|
@@ -179,7 +177,7 @@
|
|
179
177
|
}
|
180
178
|
|
181
179
|
pre {
|
182
|
-
font-family
|
180
|
+
font-family:$codeFonts;
|
183
181
|
white-space:pre-wrap;
|
184
182
|
}
|
185
183
|
|
@@ -240,7 +238,10 @@
|
|
240
238
|
}
|
241
239
|
|
242
240
|
.profiler-nuclear {
|
243
|
-
|
241
|
+
color:#f00;
|
242
|
+
&:hover {
|
243
|
+
color:#f00;
|
244
|
+
}
|
244
245
|
font-weight:bold;
|
245
246
|
padding-right:2px;
|
246
247
|
}
|
@@ -249,23 +250,23 @@
|
|
249
250
|
// ajaxed-in results will be appended to this
|
250
251
|
.profiler-results
|
251
252
|
{
|
252
|
-
z-index
|
253
|
+
z-index:$zindex + 3;
|
253
254
|
position:fixed;
|
254
255
|
top:0px;
|
255
256
|
|
256
|
-
|
257
|
+
$radius:10px;
|
257
258
|
|
258
259
|
&.profiler-left {
|
259
260
|
left:0px;
|
260
261
|
|
261
262
|
&.profiler-no-controls .profiler-totals, &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
262
|
-
-webkit-border-bottom-right-radius:
|
263
|
-
-moz-border-radius-bottomright:
|
264
|
-
border-bottom-right-radius:
|
263
|
+
-webkit-border-bottom-right-radius: $radius;
|
264
|
+
-moz-border-radius-bottomright: $radius;
|
265
|
+
border-bottom-right-radius: $radius;
|
265
266
|
}
|
266
267
|
|
267
268
|
.profiler-button, .profiler-controls {
|
268
|
-
border-right: 1px solid
|
269
|
+
border-right: 1px solid $buttonBorderColor;
|
269
270
|
}
|
270
271
|
}
|
271
272
|
|
@@ -273,20 +274,20 @@
|
|
273
274
|
right:0px;
|
274
275
|
|
275
276
|
&.profiler-no-controls .profiler-totals, &.profiler-no-controls .profiler-result:last-child .profiler-button, .profiler-controls {
|
276
|
-
-webkit-border-bottom-left-radius:
|
277
|
-
-moz-border-radius-bottomleft:
|
278
|
-
border-bottom-left-radius:
|
277
|
+
-webkit-border-bottom-left-radius: $radius;
|
278
|
+
-moz-border-radius-bottomleft: $radius;
|
279
|
+
border-bottom-left-radius: $radius;
|
279
280
|
}
|
280
281
|
|
281
282
|
.profiler-button, .profiler-controls {
|
282
|
-
border-left: 1px solid
|
283
|
+
border-left: 1px solid $buttonBorderColor;
|
283
284
|
}
|
284
285
|
}
|
285
286
|
|
286
287
|
.profiler-button, .profiler-controls {
|
287
288
|
display:none;
|
288
|
-
z-index
|
289
|
-
border-bottom: 1px solid
|
289
|
+
z-index:$zindex;
|
290
|
+
border-bottom: 1px solid $buttonBorderColor;
|
290
291
|
background-color:#fff;
|
291
292
|
padding: 4px 7px;
|
292
293
|
text-align:right;
|
@@ -309,11 +310,11 @@
|
|
309
310
|
|
310
311
|
.profiler-totals {
|
311
312
|
.profiler-reqs {
|
312
|
-
font-family:
|
313
|
+
font-family: $codeFonts;
|
313
314
|
font-size: 10px;
|
314
315
|
margin-left: 6px;
|
315
316
|
&:before {
|
316
|
-
font-family:
|
317
|
+
font-family: $codeFonts;
|
317
318
|
content: "×";
|
318
319
|
margin-right: 1px;
|
319
320
|
}
|
@@ -323,12 +324,12 @@
|
|
323
324
|
.profiler-controls {
|
324
325
|
display: block;
|
325
326
|
font-size:12px;
|
326
|
-
font-family:
|
327
|
+
font-family: $codeFonts;
|
327
328
|
cursor:default;
|
328
329
|
text-align: center;
|
329
330
|
|
330
331
|
span {
|
331
|
-
border-right: 1px solid
|
332
|
+
border-right: 1px solid $mutedColor;
|
332
333
|
padding-right: 5px;
|
333
334
|
margin-right: 5px;
|
334
335
|
cursor:pointer;
|
@@ -341,7 +342,7 @@
|
|
341
342
|
|
342
343
|
.profiler-popup {
|
343
344
|
display:none;
|
344
|
-
z-index
|
345
|
+
z-index:$zindex + 1;
|
345
346
|
position:absolute;
|
346
347
|
background-color:#fff;
|
347
348
|
border: 1px solid #aaa;
|
@@ -350,7 +351,7 @@
|
|
350
351
|
line-height:18px;
|
351
352
|
overflow:auto;
|
352
353
|
|
353
|
-
|
354
|
+
@include box-shadow(0px, 1px, 15px, #555);
|
354
355
|
|
355
356
|
.profiler-info {
|
356
357
|
margin-bottom:3px;
|
@@ -389,7 +390,7 @@
|
|
389
390
|
|
390
391
|
.profiler-queries {
|
391
392
|
display:none;
|
392
|
-
z-index
|
393
|
+
z-index:$zindex + 3;
|
393
394
|
position:absolute;
|
394
395
|
overflow-y:auto;
|
395
396
|
overflow-x:auto;
|
@@ -420,7 +421,7 @@
|
|
420
421
|
|
421
422
|
// popup results' queries will be displayed in front of this
|
422
423
|
.profiler-queries-bg {
|
423
|
-
z-index
|
424
|
+
z-index:$zindex + 2;
|
424
425
|
display:none;
|
425
426
|
background:#000;
|
426
427
|
opacity:0.7;
|
@@ -446,7 +447,7 @@
|
|
446
447
|
|
447
448
|
.profiler-info {
|
448
449
|
font-size: 25px;
|
449
|
-
border-bottom:1px solid
|
450
|
+
border-bottom:1px solid $mutedColor;
|
450
451
|
padding-bottom:3px;
|
451
452
|
margin-bottom:25px;
|
452
453
|
|
data/lib/html/includes.tmpl
CHANGED
@@ -202,7 +202,7 @@
|
|
202
202
|
<td>
|
203
203
|
<div class="query">
|
204
204
|
<pre class="profiler-stack-trace">${s.stack_trace_snippet}</pre>
|
205
|
-
<pre class="prettyprint lang-sql"><code>${s.formatted_command_string}
|
205
|
+
<pre class="prettyprint lang-sql"><code>${s.formatted_command_string}; ${MiniProfiler.formatParameters(s.parameters)}</code></pre>
|
206
206
|
</div>
|
207
207
|
</td>
|
208
208
|
</tr>
|
@@ -158,7 +158,7 @@ module Rack
|
|
158
158
|
path = env['PATH_INFO'].sub('//', '/')
|
159
159
|
|
160
160
|
# Someone (e.g. Rails engine) could change the SCRIPT_NAME so we save it
|
161
|
-
env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME'] = env['SCRIPT_NAME']
|
161
|
+
env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME'] = ENV['PASSENGER_BASE_URI'] || env['SCRIPT_NAME']
|
162
162
|
|
163
163
|
skip_it = (@config.pre_authorize_cb && !@config.pre_authorize_cb.call(env)) ||
|
164
164
|
(@config.skip_paths && @config.skip_paths.any?{ |p| path.start_with?(p) }) ||
|
@@ -334,9 +334,9 @@ module Rack
|
|
334
334
|
|
335
335
|
|
336
336
|
begin
|
337
|
+
@storage.save(page_struct)
|
337
338
|
# no matter what it is, it should be unviewed, otherwise we will miss POST
|
338
339
|
@storage.set_unviewed(page_struct[:user], page_struct[:id])
|
339
|
-
@storage.save(page_struct)
|
340
340
|
|
341
341
|
# inject headers, script
|
342
342
|
if status >= 200 && status < 300
|
@@ -584,17 +584,7 @@ Append the following to your query string:
|
|
584
584
|
# * you have disabled auto append behaviour throught :auto_inject => false flag
|
585
585
|
# * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject
|
586
586
|
def get_profile_script(env)
|
587
|
-
path =
|
588
|
-
# added because the SCRIPT_NAME workaround below then
|
589
|
-
# breaks running under a prefix as permitted by Passenger.
|
590
|
-
"#{ENV['PASSENGER_BASE_URI']}#{@config.base_url_path}"
|
591
|
-
elsif env["action_controller.instance"]
|
592
|
-
# Rails engines break SCRIPT_NAME; the following appears to discard SCRIPT_NAME
|
593
|
-
# since url_for appears documented to return any String argument unmodified
|
594
|
-
env["action_controller.instance"].url_for("#{@config.base_url_path}")
|
595
|
-
else
|
596
|
-
"#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
|
597
|
-
end
|
587
|
+
path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}"
|
598
588
|
|
599
589
|
settings = {
|
600
590
|
:path => path,
|
@@ -14,11 +14,11 @@ module Rack
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def save(page_struct)
|
17
|
-
redis.setex
|
17
|
+
redis.setex prefixed_id(page_struct[:id]), @expires_in_seconds, Marshal::dump(page_struct)
|
18
18
|
end
|
19
19
|
|
20
20
|
def load(id)
|
21
|
-
key =
|
21
|
+
key = prefixed_id(id)
|
22
22
|
raw = redis.get key
|
23
23
|
begin
|
24
24
|
Marshal::load(raw) if raw
|
@@ -30,24 +30,35 @@ module Rack
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def set_unviewed(user, id)
|
33
|
-
key =
|
34
|
-
redis.
|
35
|
-
|
33
|
+
key = user_key(user)
|
34
|
+
if redis.exists(prefixed_id(id))
|
35
|
+
expire_at = Time.now.to_i + redis.ttl(prefixed_id(id))
|
36
|
+
redis.zadd(key, expire_at, id)
|
37
|
+
end
|
38
|
+
redis.expire(key, @expires_in_seconds)
|
36
39
|
end
|
37
40
|
|
38
41
|
def set_all_unviewed(user, ids)
|
39
|
-
key =
|
40
|
-
redis.del
|
41
|
-
ids.each
|
42
|
-
|
42
|
+
key = user_key(user)
|
43
|
+
redis.del(key)
|
44
|
+
ids.each do |id|
|
45
|
+
if redis.exists(prefixed_id(id))
|
46
|
+
expire_at = Time.now.to_i + redis.ttl(prefixed_id(id))
|
47
|
+
redis.zadd(key, expire_at, id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
redis.expire(key, @expires_in_seconds)
|
43
51
|
end
|
44
52
|
|
45
53
|
def set_viewed(user, id)
|
46
|
-
redis.
|
54
|
+
redis.zrem(user_key(user), id)
|
47
55
|
end
|
48
56
|
|
57
|
+
# Remove expired ids from the unviewed sorted set and return the remaining ids
|
49
58
|
def get_unviewed_ids(user)
|
50
|
-
|
59
|
+
key = user_key(user)
|
60
|
+
redis.zremrangebyscore(key, '-inf', Time.now.to_i)
|
61
|
+
redis.zrevrangebyscore(key, '+inf', '-inf')
|
51
62
|
end
|
52
63
|
|
53
64
|
def diagnostics(user)
|
@@ -96,6 +107,14 @@ unviewed_ids: #{get_unviewed_ids(user)}
|
|
96
107
|
|
97
108
|
private
|
98
109
|
|
110
|
+
def user_key(user)
|
111
|
+
"#{@prefix}-#{user}-v"
|
112
|
+
end
|
113
|
+
|
114
|
+
def prefixed_id(id)
|
115
|
+
"#{@prefix}#{id}"
|
116
|
+
end
|
117
|
+
|
99
118
|
def redis
|
100
119
|
@redis_connection ||= begin
|
101
120
|
require 'redis' unless defined? Redis
|