rack-mini-profiler 0.1.22 → 0.1.27
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.
- checksums.yaml +7 -0
- data/Ruby/CHANGELOG +69 -35
- data/Ruby/README.md +47 -9
- data/Ruby/lib/html/flamegraph.html +351 -0
- data/Ruby/lib/html/includes.css +451 -75
- data/Ruby/lib/html/includes.js +134 -23
- data/Ruby/lib/html/includes.less +38 -35
- data/Ruby/lib/html/includes.tmpl +40 -15
- data/Ruby/lib/html/jquery.1.7.1.js +1 -1
- data/Ruby/lib/html/jquery.tmpl.js +1 -1
- data/Ruby/lib/html/list.js +7 -6
- data/Ruby/lib/html/profile_handler.js +1 -62
- data/Ruby/lib/mini_profiler/client_timer_struct.rb +1 -1
- data/Ruby/lib/mini_profiler/config.rb +58 -52
- data/Ruby/lib/mini_profiler/context.rb +11 -10
- data/Ruby/lib/mini_profiler/custom_timer_struct.rb +22 -0
- data/Ruby/lib/mini_profiler/flame_graph.rb +54 -0
- data/Ruby/lib/mini_profiler/gc_profiler.rb +8 -4
- data/Ruby/lib/mini_profiler/page_timer_struct.rb +7 -2
- data/Ruby/lib/mini_profiler/profiler.rb +207 -157
- data/Ruby/lib/mini_profiler/profiling_methods.rb +131 -108
- data/Ruby/lib/mini_profiler/request_timer_struct.rb +20 -1
- data/Ruby/lib/mini_profiler/sql_timer_struct.rb +1 -1
- data/Ruby/lib/mini_profiler/storage/abstract_store.rb +31 -27
- data/Ruby/lib/mini_profiler/storage/file_store.rb +111 -109
- data/Ruby/lib/mini_profiler/storage/memcache_store.rb +11 -9
- data/Ruby/lib/mini_profiler/storage/memory_store.rb +65 -63
- data/Ruby/lib/mini_profiler/storage/redis_store.rb +54 -44
- data/Ruby/lib/mini_profiler/version.rb +5 -0
- data/Ruby/lib/mini_profiler_rails/railtie.rb +44 -40
- data/Ruby/lib/patches/net_patches.rb +14 -0
- data/Ruby/lib/patches/sql_patches.rb +89 -48
- data/Ruby/lib/rack-mini-profiler.rb +1 -0
- data/rack-mini-profiler.gemspec +1 -1
- metadata +41 -52
data/Ruby/lib/html/includes.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
"use strict";
|
2
|
-
var MiniProfiler = (function (
|
2
|
+
var MiniProfiler = (function () {
|
3
|
+
var $;
|
3
4
|
|
4
5
|
var options,
|
5
6
|
container,
|
@@ -60,11 +61,10 @@ var MiniProfiler = (function ($) {
|
|
60
61
|
}
|
61
62
|
};
|
62
63
|
|
63
|
-
var getClientPerformance = function
|
64
|
+
var getClientPerformance = function() {
|
64
65
|
return window.performance == null ? null : window.performance;
|
65
|
-
}
|
66
|
+
};
|
66
67
|
|
67
|
-
var waitedForEnd = 0;
|
68
68
|
var fetchResults = function (ids) {
|
69
69
|
var clientPerformance, clientProbes, i, j, p, id, idx;
|
70
70
|
|
@@ -126,6 +126,7 @@ var MiniProfiler = (function ($) {
|
|
126
126
|
url: options.path + 'results',
|
127
127
|
data: { id: id, clientPerformance: clientPerformance, clientProbes: clientProbes, popup: 1 },
|
128
128
|
dataType: 'json',
|
129
|
+
global: false,
|
129
130
|
type: 'POST',
|
130
131
|
success: function (json) {
|
131
132
|
fetchedIds.push(id);
|
@@ -364,6 +365,9 @@ var MiniProfiler = (function ($) {
|
|
364
365
|
popupHide(button, popup);
|
365
366
|
}
|
366
367
|
});
|
368
|
+
$(document).bind('keydown', options.toggleShortcut, function(e) {
|
369
|
+
$('.profiler-results').toggle();
|
370
|
+
});
|
367
371
|
};
|
368
372
|
|
369
373
|
var initFullView = function () {
|
@@ -432,6 +436,7 @@ var MiniProfiler = (function ($) {
|
|
432
436
|
// get master page profiler results
|
433
437
|
fetchResults(options.ids);
|
434
438
|
});
|
439
|
+
if (options.startHidden) container.hide();
|
435
440
|
}
|
436
441
|
else {
|
437
442
|
fetchResults(options.ids);
|
@@ -507,20 +512,92 @@ var MiniProfiler = (function ($) {
|
|
507
512
|
});
|
508
513
|
}
|
509
514
|
|
515
|
+
if (typeof (MooTools) != 'undefined' && typeof (Request) != 'undefined') {
|
516
|
+
Request.prototype.addEvents({
|
517
|
+
onComplete: function() {
|
518
|
+
var stringIds = this.xhr.getResponseHeader('X-MiniProfiler-Ids');
|
519
|
+
if (stringIds) {
|
520
|
+
var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds);
|
521
|
+
fetchResults(ids);
|
522
|
+
}
|
523
|
+
}
|
524
|
+
});
|
525
|
+
}
|
526
|
+
|
527
|
+
// add support for AngularJS, which use the basic XMLHttpRequest object.
|
528
|
+
if (window.angular && typeof (XMLHttpRequest) != 'undefined') {
|
529
|
+
var _send = XMLHttpRequest.prototype.send;
|
530
|
+
|
531
|
+
XMLHttpRequest.prototype.send = function sendReplacement(data) {
|
532
|
+
this._onreadystatechange = this.onreadystatechange;
|
533
|
+
|
534
|
+
this.onreadystatechange = function onReadyStateChangeReplacement() {
|
535
|
+
if (this.readyState == 4) {
|
536
|
+
var stringIds = this.getResponseHeader('X-MiniProfiler-Ids');
|
537
|
+
if (stringIds) {
|
538
|
+
var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds);
|
539
|
+
fetchResults(ids);
|
540
|
+
}
|
541
|
+
}
|
542
|
+
|
543
|
+
return this._onreadystatechange.apply(this, arguments);
|
544
|
+
}
|
545
|
+
|
546
|
+
return _send.apply(this, arguments);
|
547
|
+
}
|
548
|
+
}
|
549
|
+
|
510
550
|
// some elements want to be hidden on certain doc events
|
511
551
|
bindDocumentEvents();
|
512
552
|
};
|
513
553
|
|
514
554
|
return {
|
515
555
|
|
516
|
-
init: function (
|
517
|
-
|
518
|
-
|
556
|
+
init: function () {
|
557
|
+
var script = document.getElementById('mini-profiler');
|
558
|
+
if (!script || !script.getAttribute) return;
|
559
|
+
|
560
|
+
options = (function () {
|
561
|
+
var version = script.getAttribute('data-version');
|
562
|
+
var path = script.getAttribute('data-path');
|
563
|
+
|
564
|
+
var currentId = script.getAttribute('data-current-id');
|
565
|
+
|
566
|
+
var ids = script.getAttribute('data-ids');
|
567
|
+
if (ids) ids = ids.split(',');
|
568
|
+
|
569
|
+
var position = script.getAttribute('data-position');
|
570
|
+
|
571
|
+
var toggleShortcut = script.getAttribute('data-toggle-shortcut');
|
572
|
+
|
573
|
+
if (script.getAttribute('data-max-traces'))
|
574
|
+
var maxTraces = parseInt(script.getAttribute('data-max-traces'));
|
575
|
+
|
576
|
+
if (script.getAttribute('data-trivial') === 'true') var trivial = true;
|
577
|
+
if (script.getAttribute('data-children') == 'true') var children = true;
|
578
|
+
if (script.getAttribute('data-controls') == 'true') var controls = true;
|
579
|
+
if (script.getAttribute('data-authorized') == 'true') var authorized = true;
|
580
|
+
if (script.getAttribute('data-start-hidden') == 'true') var startHidden = true;
|
581
|
+
|
582
|
+
return {
|
583
|
+
ids: ids,
|
584
|
+
path: path,
|
585
|
+
version: version,
|
586
|
+
renderPosition: position,
|
587
|
+
showTrivial: trivial,
|
588
|
+
showChildrenTime: children,
|
589
|
+
maxTracesToShow: maxTraces,
|
590
|
+
showControls: controls,
|
591
|
+
currentId: currentId,
|
592
|
+
authorized: authorized,
|
593
|
+
toggleShortcut: toggleShortcut,
|
594
|
+
startHidden: startHidden
|
595
|
+
}
|
596
|
+
})();
|
519
597
|
|
520
598
|
var doInit = function () {
|
521
599
|
// when rendering a shared, full page, this div will exist
|
522
600
|
container = $('.profiler-result-full');
|
523
|
-
|
524
601
|
if (container.length) {
|
525
602
|
if (window.location.href.indexOf("&trivial=1") > 0) {
|
526
603
|
options.showTrivial = true
|
@@ -547,24 +624,49 @@ var MiniProfiler = (function ($) {
|
|
547
624
|
document.getElementsByTagName('head')[0].appendChild(sc);
|
548
625
|
};
|
549
626
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
627
|
+
var wait = 0;
|
628
|
+
var finish = false;
|
629
|
+
var deferInit = function() {
|
630
|
+
if (finish) return;
|
631
|
+
if (window.performance && window.performance.timing && window.performance.timing.loadEventEnd == 0 && wait < 10000) {
|
632
|
+
setTimeout(deferInit, 100);
|
633
|
+
wait += 100;
|
554
634
|
} else {
|
555
|
-
|
635
|
+
finish = true;
|
636
|
+
init();
|
556
637
|
}
|
638
|
+
};
|
557
639
|
|
558
|
-
|
559
|
-
|
640
|
+
var init = function() {
|
641
|
+
if (options.authorized) {
|
642
|
+
var url = options.path + "includes.css?v=" + options.version;
|
643
|
+
if (document.createStyleSheet) {
|
644
|
+
document.createStyleSheet(url);
|
645
|
+
} else {
|
646
|
+
$('head').append($('<link rel="stylesheet" type="text/css" href="' + url + '" />'));
|
647
|
+
}
|
648
|
+
if (!$.tmpl) {
|
649
|
+
load(options.path + 'jquery.tmpl.js?v=' + options.version, doInit);
|
650
|
+
} else {
|
651
|
+
doInit();
|
652
|
+
}
|
560
653
|
} else {
|
561
654
|
doInit();
|
562
655
|
}
|
656
|
+
};
|
657
|
+
|
658
|
+
if (typeof(jQuery) == 'function') {
|
659
|
+
var jQueryVersion = jQuery.fn.jquery.split('.');
|
563
660
|
}
|
564
|
-
|
565
|
-
|
661
|
+
if (jQueryVersion && (parseInt(jQueryVersion[0]) == 2) || (parseInt(jQueryVersion[0]) < 2 && parseInt(jQueryVersion[1]) >= 7)) {
|
662
|
+
MiniProfiler.jQuery = $ = jQuery;
|
663
|
+
$(deferInit);
|
664
|
+
} else {
|
665
|
+
load(options.path + "jquery.1.7.1.js?v=" + options.version, function() {
|
666
|
+
MiniProfiler.jQuery = $ = jQuery.noConflict(true);
|
667
|
+
$(deferInit);
|
668
|
+
});
|
566
669
|
}
|
567
|
-
|
568
670
|
},
|
569
671
|
|
570
672
|
getClientTimingByName: function (clientTiming, name) {
|
@@ -651,7 +753,7 @@ var MiniProfiler = (function ($) {
|
|
651
753
|
// start adding at the root and recurse down
|
652
754
|
addToResults(root);
|
653
755
|
|
654
|
-
var removeDuration = function
|
756
|
+
var removeDuration = function(list, duration) {
|
655
757
|
|
656
758
|
var newList = [];
|
657
759
|
for (var i = 0; i < list.length; i++) {
|
@@ -675,7 +777,7 @@ var MiniProfiler = (function ($) {
|
|
675
777
|
}
|
676
778
|
|
677
779
|
return newList;
|
678
|
-
}
|
780
|
+
};
|
679
781
|
|
680
782
|
var processTimes = function (elem, parent) {
|
681
783
|
var duration = { start: elem.StartMilliseconds, finish: (elem.StartMilliseconds + elem.DurationMilliseconds) };
|
@@ -697,7 +799,7 @@ var MiniProfiler = (function ($) {
|
|
697
799
|
// sort results by time
|
698
800
|
result.sort(function (a, b) { return a.StartMilliseconds - b.StartMilliseconds; });
|
699
801
|
|
700
|
-
var determineOverlap = function
|
802
|
+
var determineOverlap = function(gap, node) {
|
701
803
|
var overlap = 0;
|
702
804
|
for (var i = 0; i < node.richTiming.length; i++) {
|
703
805
|
var current = node.richTiming[i];
|
@@ -711,7 +813,7 @@ var MiniProfiler = (function ($) {
|
|
711
813
|
overlap += Math.min(gap.finish, current.finish) - Math.max(gap.start, current.start);
|
712
814
|
}
|
713
815
|
return overlap;
|
714
|
-
}
|
816
|
+
};
|
715
817
|
|
716
818
|
var determineGap = function (gap, node, match) {
|
717
819
|
var overlap = determineOverlap(gap, node);
|
@@ -784,7 +886,16 @@ var MiniProfiler = (function ($) {
|
|
784
886
|
return (duration || 0).toFixed(1);
|
785
887
|
}
|
786
888
|
};
|
787
|
-
})(
|
889
|
+
})();
|
890
|
+
|
891
|
+
MiniProfiler.init();
|
892
|
+
|
893
|
+
// jquery.hotkeys.js
|
894
|
+
// https://github.com/jeresig/jquery.hotkeys/blob/master/jquery.hotkeys.js
|
895
|
+
|
896
|
+
(function(d){function h(g){if("string"===typeof g.data){var h=g.handler,j=g.data.toLowerCase().split(" ");g.handler=function(b){if(!(this!==b.target&&(/textarea|select/i.test(b.target.nodeName)||"text"===b.target.type))){var c="keypress"!==b.type&&d.hotkeys.specialKeys[b.which],e=String.fromCharCode(b.which).toLowerCase(),a="",f={};b.altKey&&"alt"!==c&&(a+="alt+");b.ctrlKey&&"ctrl"!==c&&(a+="ctrl+");b.metaKey&&(!b.ctrlKey&&"meta"!==c)&&(a+="meta+");b.shiftKey&&"shift"!==c&&(a+="shift+");c?f[a+c]=
|
897
|
+
!0:(f[a+e]=!0,f[a+d.hotkeys.shiftNums[e]]=!0,"shift+"===a&&(f[d.hotkeys.shiftNums[e]]=!0));c=0;for(e=j.length;c<e;c++)if(f[j[c]])return h.apply(this,arguments)}}}}d.hotkeys={version:"0.8",specialKeys:{8:"backspace",9:"tab",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",
|
898
|
+
109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",191:"/",224:"meta"},shiftNums:{"`":"~",1:"!",2:"@",3:"#",4:"$",5:"%",6:"^",7:"&",8:"*",9:"(","0":")","-":"_","=":"+",";":": ","'":'"',",":"<",".":">","/":"?","\\":"|"}};d.each(["keydown","keyup","keypress"],function(){d.event.special[this]={add:h}})})(jQuery);
|
788
899
|
|
789
900
|
// prettify.js
|
790
901
|
// http://code.google.com/p/google-code-prettify/
|
data/Ruby/lib/html/includes.less
CHANGED
@@ -49,7 +49,7 @@
|
|
49
49
|
// styles shared between popup view and full view
|
50
50
|
.profiler-result
|
51
51
|
{
|
52
|
-
|
52
|
+
|
53
53
|
.profiler-toggle-duration-with-children
|
54
54
|
{
|
55
55
|
float: right;
|
@@ -143,6 +143,9 @@
|
|
143
143
|
float:left;
|
144
144
|
margin-left:0px;
|
145
145
|
}
|
146
|
+
&.profiler-custom-link {
|
147
|
+
float:left;
|
148
|
+
}
|
146
149
|
}
|
147
150
|
}
|
148
151
|
}
|
@@ -189,15 +192,15 @@
|
|
189
192
|
text-align:right;
|
190
193
|
margin-bottom:5px;
|
191
194
|
}
|
192
|
-
|
195
|
+
|
193
196
|
.profiler-gap-info, .profiler-gap-info td { background-color: #ccc;}
|
194
197
|
.profiler-gap-info {
|
195
198
|
.profiler-unit {color: #777;}
|
196
199
|
.profiler-info {text-align: right}
|
197
200
|
&.profiler-trivial-gaps {display: none}
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
+
}
|
202
|
+
|
203
|
+
.profiler-trivial-gap-container { text-align: center;}
|
201
204
|
|
202
205
|
// prettify colors
|
203
206
|
.str{color:maroon}
|
@@ -287,24 +290,24 @@
|
|
287
290
|
}
|
288
291
|
}
|
289
292
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
293
|
+
.profiler-controls {
|
294
|
+
display: block;
|
295
|
+
font-size:12px;
|
296
|
+
font-family: @codeFonts;
|
297
|
+
cursor:default;
|
298
|
+
text-align: center;
|
299
|
+
|
300
|
+
span {
|
301
|
+
border-right: 1px solid @mutedColor;
|
302
|
+
padding-right: 5px;
|
303
|
+
margin-right: 5px;
|
304
|
+
cursor:pointer;
|
305
|
+
}
|
306
|
+
|
307
|
+
span:last-child {
|
308
|
+
border-right: none;
|
309
|
+
}
|
310
|
+
}
|
308
311
|
|
309
312
|
.profiler-popup {
|
310
313
|
display:none;
|
@@ -367,19 +370,19 @@
|
|
367
370
|
}
|
368
371
|
}
|
369
372
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
+
&.profiler-min .profiler-result {
|
374
|
+
display: none;
|
375
|
+
}
|
373
376
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
+
&.profiler-min .profiler-controls span {
|
378
|
+
display: none;
|
379
|
+
}
|
377
380
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
381
|
+
&.profiler-min .profiler-controls .profiler-min-max {
|
382
|
+
border-right: none;
|
383
|
+
padding: 0px;
|
384
|
+
margin: 0px;
|
385
|
+
}
|
383
386
|
}
|
384
387
|
|
385
388
|
// popup results' queries will be displayed in front of this
|
@@ -465,4 +468,4 @@
|
|
465
468
|
}
|
466
469
|
}
|
467
470
|
}
|
468
|
-
}
|
471
|
+
}
|
data/Ruby/lib/html/includes.tmpl
CHANGED
@@ -27,10 +27,13 @@
|
|
27
27
|
{{if HasSqlTimings}}
|
28
28
|
<th colspan="2">query time (ms)</th>
|
29
29
|
{{/if}}
|
30
|
+
{{each CustomTimingNames}}
|
31
|
+
<th colspan="2">${$value.toLowerCase()} (ms)</th>
|
32
|
+
{{/each}}
|
30
33
|
</tr>
|
31
34
|
</thead>
|
32
35
|
<tbody>
|
33
|
-
{{tmpl(Root) "#timingTemplate"}}
|
36
|
+
{{tmpl({timing:Root, page:this.data}) "#timingTemplate"}}
|
34
37
|
</tbody>
|
35
38
|
<tfoot>
|
36
39
|
<tr>
|
@@ -46,6 +49,12 @@
|
|
46
49
|
<span class="profiler-unit">% in sql</span>
|
47
50
|
</td>
|
48
51
|
{{/if}}
|
52
|
+
{{each CustomTimingNames}}
|
53
|
+
<td colspan="2" class="profiler-number profiler-percentage-in-sql" title="${CustomTimingStats[$value].Count} ${$value.toLowerCase()} invocations spent ${MiniProfiler.formatDuration(CustomTimingStats[$value].Duration)} ms of total request time">
|
54
|
+
${MiniProfiler.formatDuration(CustomTimingStats[$value].Duration / DurationMilliseconds * 100)}
|
55
|
+
<span class="profiler-unit">% in ${$value.toLowerCase()}</span>
|
56
|
+
</td>
|
57
|
+
{{/each}}
|
49
58
|
</tr>
|
50
59
|
</tfoot>
|
51
60
|
</table>
|
@@ -114,6 +123,9 @@
|
|
114
123
|
|
115
124
|
<script id="linksTemplate" type="text/x-jquery-tmpl">
|
116
125
|
<a href="${MiniProfiler.shareUrl(Id)}" class="profiler-share-profiler-results" target="_blank">share</a>
|
126
|
+
{{if CustomLink}}
|
127
|
+
<a href="${CustomLink}" class="profiler-custom-link" target="_blank">${CustomLinkName}</a>
|
128
|
+
{{/if}}
|
117
129
|
{{if HasTrivialTimings}}
|
118
130
|
<a class="profiler-toggle-trivial" data-show-on-load="${HasAllTrivialTimings}" title="toggles any rows with < ${TrivialDurationThresholdMilliseconds} ms">
|
119
131
|
show trivial
|
@@ -123,37 +135,50 @@
|
|
123
135
|
|
124
136
|
<script id="timingTemplate" type="text/x-jquery-tmpl">
|
125
137
|
|
126
|
-
<tr class="{{if IsTrivial }}profiler-trivial{{/if}}" data-timing-id="${Id}">
|
127
|
-
<td class="profiler-label" title="{{if Name && Name.length > 45 }}${Name}{{/if}}">
|
128
|
-
<span class="profiler-indent">${MiniProfiler.renderIndent(Depth)}</span> ${Name.slice(0,45)}{{if Name && Name.length > 45 }}...{{/if}}
|
138
|
+
<tr class="{{if timing.IsTrivial }}profiler-trivial{{/if}}" data-timing-id="${timing.Id}">
|
139
|
+
<td class="profiler-label" title="{{if timing.Name && timing.Name.length > 45 }}${timing.Name}{{/if}}">
|
140
|
+
<span class="profiler-indent">${MiniProfiler.renderIndent(timing.Depth)}</span> ${timing.Name.slice(0,45)}{{if timing.Name && timing.Name.length > 45 }}...{{/if}}
|
129
141
|
</td>
|
130
142
|
<td class="profiler-duration" title="duration of this step without any children's durations">
|
131
|
-
${MiniProfiler.formatDuration(DurationWithoutChildrenMilliseconds)}
|
143
|
+
${MiniProfiler.formatDuration(timing.DurationWithoutChildrenMilliseconds)}
|
132
144
|
</td>
|
133
145
|
<td class="profiler-duration profiler-duration-with-children" title="duration of this step and its children">
|
134
|
-
${MiniProfiler.formatDuration(DurationMilliseconds)}
|
146
|
+
${MiniProfiler.formatDuration(timing.DurationMilliseconds)}
|
135
147
|
</td>
|
136
148
|
<td class="profiler-duration time-from-start" title="time elapsed since profiling started">
|
137
|
-
<span class="profiler-unit">+</span>${MiniProfiler.formatDuration(StartMilliseconds)}
|
149
|
+
<span class="profiler-unit">+</span>${MiniProfiler.formatDuration(timing.StartMilliseconds)}
|
138
150
|
</td>
|
139
151
|
|
140
|
-
{{if HasSqlTimings}}
|
141
|
-
<td class="profiler-duration {{if HasDuplicateSqlTimings}}profiler-warning{{/if}}" title="{{if HasDuplicateSqlTimings}}duplicate queries detected - {{/if}}{{if ExecutedReaders > 0 || ExecutedScalars > 0 || ExecutedNonQueries > 0}}${ExecutedReaders} reader, ${ExecutedScalars} scalar, ${ExecutedNonQueries} non-query statements executed{{/if}}">
|
152
|
+
{{if timing.HasSqlTimings}}
|
153
|
+
<td class="profiler-duration {{if timing.HasDuplicateSqlTimings}}profiler-warning{{/if}}" title="{{if timing.HasDuplicateSqlTimings}}duplicate queries detected - {{/if}}{{if timing.ExecutedReaders > 0 || timing.ExecutedScalars > 0 || timing.ExecutedNonQueries > 0}}${timing.ExecutedReaders} reader, ${timing.ExecutedScalars} scalar, ${timing.ExecutedNonQueries} non-query statements executed{{/if}}">
|
142
154
|
<a class="profiler-queries-show">
|
143
|
-
{{if HasDuplicateSqlTimings}}<span class="profiler-nuclear">!</span>{{/if}}
|
144
|
-
${SqlTimings.length} <span class="profiler-unit">sql</span>
|
155
|
+
{{if timing.HasDuplicateSqlTimings}}<span class="profiler-nuclear">!</span>{{/if}}
|
156
|
+
${timing.SqlTimings.length} <span class="profiler-unit">sql</span>
|
145
157
|
</a>
|
146
158
|
</td>
|
147
159
|
<td class="profiler-duration" title="aggregate duration of all queries in this step (excludes children)">
|
148
|
-
${MiniProfiler.formatDuration(SqlTimingsDurationMilliseconds)}
|
160
|
+
${MiniProfiler.formatDuration(timing.SqlTimingsDurationMilliseconds)}
|
149
161
|
</td>
|
150
162
|
{{/if}}
|
151
163
|
|
164
|
+
{{each page.CustomTimingNames}}
|
165
|
+
{{if timing.CustomTimings && timing.CustomTimings[$value]}}
|
166
|
+
<td class="profiler-duration" title="aggregate number of all ${$value.toLowerCase()} invocations in this step (excludes children)">
|
167
|
+
${timing.CustomTimings[$value].length} ${$value.toLowerCase()}
|
168
|
+
</td>
|
169
|
+
<td class="profiler-duration" title="aggregate duration of all ${$value.toLowerCase()} invocations in this step (excludes children)">
|
170
|
+
${MiniProfiler.formatDuration(timing.CustomTimingStats[$value].Duration)}
|
171
|
+
</td>
|
172
|
+
{{else}}
|
173
|
+
<td colspan="2"></td>
|
174
|
+
{{/if}}
|
175
|
+
{{/each}}
|
176
|
+
|
152
177
|
</tr>
|
153
178
|
|
154
|
-
{{if HasChildren}}
|
155
|
-
{{each Children}}
|
156
|
-
{{tmpl($value) "#timingTemplate"}}
|
179
|
+
{{if timing.HasChildren}}
|
180
|
+
{{each timing.Children}}
|
181
|
+
{{tmpl({timing: $value, page: page}) "#timingTemplate"}}
|
157
182
|
{{/each}}
|
158
183
|
{{/if}}
|
159
184
|
|