Adding new debugging toolbar
Needs a UI cleanup still, but for the most part is working.
This commit is contained in:
parent
fca12118de
commit
0de3082ca4
11 changed files with 350 additions and 4 deletions
|
|
@ -97,6 +97,7 @@ production.
|
|||
* (bug 32666) Special:ActiveUsers now allows a subpage to be used as the
|
||||
username (eg. Special:ActiveUsers/Username)
|
||||
* New JavaScript variable wgPageContentLanguage
|
||||
* Added new debugging toolbar, enabled with $wgDebugToolbar
|
||||
|
||||
=== Bug fixes in 1.19 ===
|
||||
* $wgUploadNavigationUrl should be used for file redlinks if.
|
||||
|
|
|
|||
|
|
@ -374,7 +374,7 @@ class Article extends Page {
|
|||
*/
|
||||
public function view() {
|
||||
global $wgUser, $wgOut, $wgRequest, $wgParser;
|
||||
global $wgUseFileCache, $wgUseETag;
|
||||
global $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
|
||||
|
||||
wfProfileIn( __METHOD__ );
|
||||
|
||||
|
|
@ -429,7 +429,7 @@ class Article extends Page {
|
|||
}
|
||||
|
||||
# Try client and file cache
|
||||
if ( $oldid === 0 && $this->mPage->checkTouched() ) {
|
||||
if ( !$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched() ) {
|
||||
if ( $wgUseETag ) {
|
||||
$wgOut->setETag( $parserCache->getETag( $this, $parserOptions ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -436,6 +436,9 @@ $wgAutoloadLocalClasses = array(
|
|||
'ResultWrapper' => 'includes/db/DatabaseUtility.php',
|
||||
'SQLiteField' => 'includes/db/DatabaseSqlite.php',
|
||||
|
||||
# includes/debug
|
||||
'MWDebug' => 'includes/debug/Debug.php',
|
||||
|
||||
# includes/diff
|
||||
'_DiffEngine' => 'includes/diff/DairikiDiff.php',
|
||||
'_DiffOp' => 'includes/diff/DairikiDiff.php',
|
||||
|
|
|
|||
|
|
@ -4160,6 +4160,14 @@ $wgParserTestRemote = false;
|
|||
*/
|
||||
$wgWikiID = false;
|
||||
|
||||
/**
|
||||
* Display the new debugging toolbar. This also enables profiling on database
|
||||
* queries and other useful output.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
$wgDebugToolbar = false;
|
||||
|
||||
/** @} */ # end of profiling, testing and debugging }
|
||||
|
||||
/************************************************************************//**
|
||||
|
|
|
|||
|
|
@ -835,6 +835,8 @@ function wfDebug( $text, $logonly = false ) {
|
|||
wfErrorLog( $text, $wgDebugLogFile );
|
||||
}
|
||||
}
|
||||
|
||||
MWDebug::debugMsg( $text );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -328,6 +328,8 @@ if ( $wgCookieSecure === 'detect' ) {
|
|||
$wgCookieSecure = ( substr( $wgServer, 0, 6 ) === 'https:' );
|
||||
}
|
||||
|
||||
MWDebug::init();
|
||||
|
||||
if ( !defined( 'MW_COMPILED' ) ) {
|
||||
if ( !MWInit::classExists( 'AutoLoader' ) ) {
|
||||
require_once( "$IP/includes/AutoLoader.php" );
|
||||
|
|
@ -392,6 +394,7 @@ if ( $wgCommandLineMode ) {
|
|||
}
|
||||
}
|
||||
wfDebug( "$debug\n" );
|
||||
MWDebug::processRequest( $wgRequest );
|
||||
}
|
||||
|
||||
wfProfileOut( $fname . '-misc1' );
|
||||
|
|
|
|||
|
|
@ -531,13 +531,15 @@ abstract class Skin extends ContextSource {
|
|||
protected function generateDebugHTML() {
|
||||
global $wgShowDebug;
|
||||
|
||||
$html = MWDebug::getDebugHTML();
|
||||
|
||||
if ( $wgShowDebug ) {
|
||||
$listInternals = $this->formatDebugHTML( $this->getOutput()->mDebugtext );
|
||||
return "\n<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">" .
|
||||
$html .= "\n<hr />\n<strong>Debug data:</strong><ul id=\"mw-debug-html\">" .
|
||||
$listInternals . "</ul>\n";
|
||||
}
|
||||
|
||||
return '';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -840,9 +840,13 @@ abstract class DatabaseBase implements DatabaseType {
|
|||
throw new MWException( 'Tainted query found' );
|
||||
}
|
||||
|
||||
$queryId = MWDebug::query( $sql, $fname, $isMaster );
|
||||
|
||||
# Do the query and handle errors
|
||||
$ret = $this->doQuery( $commentedSql );
|
||||
|
||||
MWDebug::queryTime( $queryId );
|
||||
|
||||
# Try reconnecting if the connection was lost
|
||||
if ( false === $ret && $this->wasErrorReissuable() ) {
|
||||
# Transaction is gone, like it or not
|
||||
|
|
|
|||
|
|
@ -489,6 +489,10 @@ return array(
|
|||
'debugScripts' => 'resources/mediawiki/mediawiki.log.js',
|
||||
'debugRaw' => false,
|
||||
),
|
||||
'mediawiki.debug' => array(
|
||||
'scripts' => 'resources/mediawiki/mediawiki.debug.js',
|
||||
'styles' => 'resources/mediawiki/mediawiki.debug.css',
|
||||
),
|
||||
'mediawiki.htmlform' => array(
|
||||
'scripts' => 'resources/mediawiki/mediawiki.htmlform.js',
|
||||
),
|
||||
|
|
|
|||
111
resources/mediawiki/mediawiki.debug.css
Normal file
111
resources/mediawiki/mediawiki.debug.css
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
.mw-debug {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background-color: #eee;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.mw-debug pre {
|
||||
font-family: Monaco, "Consolas", "Lucida Console", "Courier New", monospace;
|
||||
font-size: 11px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.mw-debug ul {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mw-debug li {
|
||||
padding: 2px 5px;
|
||||
width: 100%;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.mw-debug-bit {
|
||||
min-height: 25px;
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
border-right: 1px solid #ccc;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.mw-debug-pane {
|
||||
max-height: 300px;
|
||||
overflow: scroll;
|
||||
border-top: 2px solid #ccc;
|
||||
display: none;
|
||||
font-size: 11px;
|
||||
background-color: #e1eff2;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mw-debug-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#mw-debug-querylist tr {
|
||||
|
||||
}
|
||||
|
||||
#mw-debug-querylist td {
|
||||
padding: 2px 5px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.mw-debug-query-time {
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request table {
|
||||
width: 100%;
|
||||
margin: 10px 0 30px;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request tr,
|
||||
#mw-debug-pane-request th,
|
||||
#mw-debug-pane-request td,
|
||||
#mw-debug-pane-request table {
|
||||
border: 1px solid #D0DBB3;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request th,
|
||||
#mw-debug-pane-request td {
|
||||
font-size: 12px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request th {
|
||||
background-color: #F1F7E2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#mw-debug-pane-request td {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#mw-debug-pane-querylist table {
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
#mw-debug-pane-includes li,
|
||||
#mw-debug-pane-querylist tr td {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
#mw-debug-pane-includes li:nth-child(odd),
|
||||
#mw-debug-pane-querylist tr:nth-child(odd) td {
|
||||
background-color: #ddd;
|
||||
}
|
||||
208
resources/mediawiki/mediawiki.debug.js
Normal file
208
resources/mediawiki/mediawiki.debug.js
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* Javascript for the new debug toolbar, enabled with $wgDebugToolbar
|
||||
*
|
||||
* @author John Du Hart
|
||||
* @since 1.19
|
||||
*/
|
||||
|
||||
( function( $ ) {
|
||||
|
||||
var debug = mw.Debug = {
|
||||
/**
|
||||
* Toolbar container element
|
||||
*
|
||||
* @var {jQuery}
|
||||
*/
|
||||
$container: null,
|
||||
|
||||
/**
|
||||
* Array containing data for the debug toolbar
|
||||
*
|
||||
* @var {Array}
|
||||
*/
|
||||
data: {},
|
||||
|
||||
/**
|
||||
* Initializes the debugging pane
|
||||
*
|
||||
* @param {Array} data
|
||||
*/
|
||||
init: function( data ) {
|
||||
this.data = data;
|
||||
this.buildHtml();
|
||||
|
||||
// Insert the container into the DOM
|
||||
$( 'body' ).append( this.$container );
|
||||
|
||||
$( '.mw-debug-panelink' ).click( this.switchPane );
|
||||
},
|
||||
|
||||
/**
|
||||
* Switches between panes
|
||||
*
|
||||
* @todo Store cookie for last pane open
|
||||
* @context {Element}
|
||||
* @param {jQuery.Event} e
|
||||
*/
|
||||
switchPane: function( e ) {
|
||||
var currentPaneId = debug.$container.data( 'currentPane' ),
|
||||
requestedPaneId = $(this).parent().attr( 'id' ).substr( 9 ),
|
||||
$currentPane = $( '#mw-debug-pane-' + currentPaneId ),
|
||||
$requestedPane = $( '#mw-debug-pane-' + requestedPaneId );
|
||||
e.preventDefault();
|
||||
|
||||
// Hide the current pane
|
||||
if ( requestedPaneId === currentPaneId ) {
|
||||
$currentPane.slideUp();
|
||||
debug.$container.data( 'currentPane', null );
|
||||
return;
|
||||
}
|
||||
|
||||
debug.$container.data( 'currentPane', requestedPaneId );
|
||||
|
||||
if ( currentPaneId === undefined || currentPaneId === null ) {
|
||||
$requestedPane.slideDown();
|
||||
} else {
|
||||
$currentPane.hide();
|
||||
$requestedPane.show();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs the HTML for the debugging toolbar
|
||||
*/
|
||||
buildHtml: function() {
|
||||
this.$container = $( '<div></div>' )
|
||||
.attr({
|
||||
id: 'mw-debug-container',
|
||||
class: 'mw-debug'
|
||||
});
|
||||
|
||||
var html = '';
|
||||
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-mwversion">'
|
||||
+ '<a href="//www.mediawiki.org/">MediaWiki</a>: '
|
||||
+ this.data.mwVersion + '</div>';
|
||||
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-phpversion">'
|
||||
+ '<a href="//www.php.net/">PHP</a>: '
|
||||
+ this.data.phpVersion + '</div>';
|
||||
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-time">'
|
||||
+ 'Time: ' + this.data.time.toFixed( 5 ) + 's</div>';
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-memory">'
|
||||
+ 'Memory: ' + this.data.memory + ' (<span title="Peak usage">'
|
||||
+ this.data.memoryPeak + '</span>)</div>';
|
||||
|
||||
var queryLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-query-link">Queries: '
|
||||
+ this.data.queries.length + '</a>';
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-querylist">'
|
||||
+ queryLink + '</div>';
|
||||
|
||||
var debugLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-debuglog-link">Debug Log ('
|
||||
+ this.data.debugLog.length + ' lines)</a>';
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-debuglog">'
|
||||
+ debugLink + '</div>';
|
||||
|
||||
var requestLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-request-link">Request</a>';
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-request">'
|
||||
+ requestLink + '</div>';
|
||||
|
||||
var filesLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-files-includes">'
|
||||
+ this.data.includes.length + ' Files Included</a>';
|
||||
html += '<div class="mw-debug-bit" id="mw-debug-includes">'
|
||||
+ filesLink + '</div>';
|
||||
|
||||
html += '<div class="mw-debug-pane" id="mw-debug-pane-querylist">'
|
||||
+ this.buildQueryTable() + '</div>';
|
||||
html += '<div class="mw-debug-pane" id="mw-debug-pane-debuglog">'
|
||||
+ this.buildDebugLogTable() + '</div>';
|
||||
html += '<div class="mw-debug-pane" id="mw-debug-pane-request">'
|
||||
+ this.buildRequestPane() + '</div>';
|
||||
html += '<div class="mw-debug-pane" id="mw-debug-pane-includes">'
|
||||
+ this.buildIncludesPane() + '</div>';
|
||||
|
||||
this.$container.html( html );
|
||||
},
|
||||
|
||||
/**
|
||||
* Query list pane
|
||||
*/
|
||||
buildQueryTable: function() {
|
||||
var html = '<table id="mw-debug-querylist">';
|
||||
|
||||
for ( var i = 0, length = this.data.queries.length; i < length; i++ ) {
|
||||
var query = this.data.queries[i];
|
||||
|
||||
html += '<tr><td>' + ( i + 1 ) + '</td>';
|
||||
|
||||
html += '<td>' + query.sql + '</td>';
|
||||
html += '<td><span class="mw-debug-query-time">(' + query.time.toFixed( 4 ) + 'ms)</span> ' + query.function + '</td>';
|
||||
|
||||
html += '</tr>';
|
||||
}
|
||||
|
||||
html += '</table>';
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
/**
|
||||
* Legacy debug log pane
|
||||
*/
|
||||
buildDebugLogTable: function() {
|
||||
var html = '<ul>';
|
||||
|
||||
for ( var i = 0, length = this.data.debugLog.length; i < length; i++ ) {
|
||||
var line = this.data.debugLog[i];
|
||||
html += '<li>' + line.replace( /\n/g, "<br />\n" ) + '</li>';
|
||||
}
|
||||
|
||||
return html + '</ul>';
|
||||
},
|
||||
|
||||
/**
|
||||
* Request information pane
|
||||
*/
|
||||
buildRequestPane: function() {
|
||||
var buildTable = function( title, data ) {
|
||||
var t = '<h2>' + title + '</h2>'
|
||||
+ '<table> <tr> <th>Key</th> <th>Value</th> </tr>';
|
||||
|
||||
for ( var key in data ) {
|
||||
if ( !data.hasOwnProperty( key ) ) {
|
||||
continue;
|
||||
}
|
||||
var value = data[key];
|
||||
|
||||
t += '<tr><th>' + key + '</th><td>' + value + '</td></tr>';
|
||||
}
|
||||
|
||||
t += '</table>';
|
||||
return t;
|
||||
};
|
||||
|
||||
var html = this.data.request.method + ' ' + this.data.request.url;
|
||||
html += buildTable( 'Headers', this.data.request.headers );
|
||||
html += buildTable( 'Parameters', this.data.request.params );
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
/**
|
||||
* Included files pane
|
||||
*/
|
||||
buildIncludesPane: function() {
|
||||
var html = '<ul>';
|
||||
|
||||
for ( var i = 0, l = this.data.includes.length; i < l; i++ ) {
|
||||
var file = this.data.includes[i];
|
||||
html += '<li><span class="mw-debug-right">' + file.size + '</span> ' + file.name + '</li>';
|
||||
}
|
||||
|
||||
html += '</ul>';
|
||||
return html;
|
||||
}
|
||||
};
|
||||
|
||||
} )( jQuery );
|
||||
Loading…
Reference in a new issue