Skip to content

Commit 7e4ecfd

Browse files
committed
Merge pull request #319 from mindsocket/master
Add javascript timing metrics to timing panel onLoad if available
2 parents 25ea0b4 + a686e7b commit 7e4ecfd

File tree

4 files changed

+88
-5
lines changed

4 files changed

+88
-5
lines changed

debug_toolbar/panels/timer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def nav_subtitle(self):
7171
return _('TOTAL: %0.2fms') % stats['total_time']
7272

7373
def title(self):
74-
return _('Resource Usage')
74+
return _('Time')
7575

7676
def url(self):
7777
return ''

debug_toolbar/static/debug_toolbar/js/toolbar.js

+62-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Grab jQuery for use in any of the below
2+
var $djdtjq = jQuery.noConflict(true);
3+
14
window.djdt = (function(window, document, jQuery) {
25
jQuery.cookie = function(name, value, options) { if (typeof value != 'undefined') { options = options || {}; if (value === null) { value = ''; options.expires = -1; } var expires = ''; if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { var date; if (typeof options.expires == 'number') { date = new Date(); date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); } else { date = options.expires; } expires = '; expires=' + date.toUTCString(); } var path = options.path ? '; path=' + (options.path) : ''; var domain = options.domain ? '; domain=' + (options.domain) : ''; var secure = options.secure ? '; secure' : ''; document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); } else { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = $.trim(cookies[i]); if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } };
36
var $ = jQuery;
@@ -226,4 +229,62 @@ window.djdt = (function(window, document, jQuery) {
226229
djdt.init();
227230
});
228231
return djdt;
229-
}(window, document, jQuery.noConflict(true)));
232+
}(window, document, $djdtjq));
233+
234+
235+
(function(window, document, $) {
236+
function _renderPerf() {
237+
// Browser timing remains hidden unless we can successfully access the performance object
238+
var perf = window.performance || window.msPerformance ||
239+
window.webkitPerformance || window.mozPerformance;
240+
if (perf) {
241+
var rowCount = 0,
242+
timingOffset = perf.timing.navigationStart,
243+
timingEnd = perf.timing.loadEventEnd;
244+
var totalTime = timingEnd - timingOffset;
245+
function getLeft(stat) {
246+
return ((perf.timing[stat] - timingOffset) / (totalTime)) * 100.0;
247+
}
248+
function getCSSWidth(stat, endStat) {
249+
var width = ((perf.timing[endStat] - perf.timing[stat]) / (totalTime)) * 100.0;
250+
// Calculate relative percent (same as sql panel logic)
251+
width = 100.0 * width / (100.0 - getLeft(stat));
252+
return (width < 1) ? "2px" : width + "%";
253+
}
254+
function addRow(stat, endStat) {
255+
rowCount++;
256+
var $row = $('<tr class="' + ((rowCount % 2) ? 'djDebugOdd' : 'djDebugEven') + '"></tr>');
257+
if (endStat) {
258+
// Render a start through end bar
259+
$row.html('<td>' + stat.replace('Start', '') + '</td>' +
260+
'<td class="timeline"><div class="djDebugTimeline"><div class="djDebugLineChart" style="left:' + getLeft(stat) + '%;"><strong style="width:' + getCSSWidth(stat, endStat) + ';">&nbsp;</strong></div></div></td>' +
261+
'<td>' + (perf.timing[stat] - timingOffset) + ' (+' + (perf.timing[endStat] - perf.timing[stat]) + ')</td>');
262+
} else {
263+
// Render a point in time
264+
$row.html('<td>' + stat + '</td>' +
265+
'<td class="timeline"><div class="djDebugTimeline"><div class="djDebugLineChart" style="left:' + getLeft(stat) + '%;"><strong style="width:2px;">&nbsp;</strong></div></div></td>' +
266+
'<td>' + (perf.timing[stat] - timingOffset) + '</td>');
267+
}
268+
$('#djDebugBrowserTimingTableBody').append($row);
269+
}
270+
271+
// This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param)
272+
addRow('domainLookupStart', 'domainLookupEnd');
273+
addRow('connectStart', 'connectEnd');
274+
addRow('requestStart', 'responseEnd') // There is no requestEnd
275+
addRow('responseStart', 'responseEnd');
276+
addRow('domLoading', 'domComplete'); // Spans the events below
277+
addRow('domInteractive');
278+
addRow('domContentLoadedEventStart', 'domContentLoadedEventEnd');
279+
addRow('loadEventStart', 'loadEventEnd');
280+
$('#djDebugBrowserTiming').css("display", "block");
281+
}
282+
}
283+
284+
function renderPerf() {
285+
setTimeout(_renderPerf, 0);
286+
}
287+
288+
$(window).bind('load', renderPerf);
289+
290+
}(window, document, $djdtjq));

debug_toolbar/static/debug_toolbar/js/toolbar.min.js

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

debug_toolbar/templates/debug_toolbar/panels/timer.html

+22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{% load i18n %}
2+
<h4>{% trans 'Resource Usage' %}</h4>
23
<table>
34
<colgroup>
45
<col style="width:20%"/>
@@ -19,3 +20,24 @@
1920
{% endfor %}
2021
</tbody>
2122
</table>
23+
24+
<!-- This hidden div is populated and displayed by code in toolbar.js -->
25+
<div id="djDebugBrowserTiming" style="display:none">
26+
<h4>{% trans 'Browser Timing' %}</h4>
27+
<table>
28+
<colgroup>
29+
<col style="width:20%"/>
30+
<col style="width:60%"/>
31+
<col style="width:20%"/>
32+
</colgroup>
33+
<thead>
34+
<tr>
35+
<th>{% trans "Timing Attribute" %}</th>
36+
<th class="timeline">{% trans 'Timeline' %}</th>
37+
<th class="time">{% trans "Milliseconds since navigation start (+length)" %}</th>
38+
</tr>
39+
</thead>
40+
<tbody id="djDebugBrowserTimingTableBody">
41+
</tbody>
42+
</table>
43+
</div>

0 commit comments

Comments
 (0)