rack-mini-profiler 0.10.2 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|