Make $wgShowExceptionDetails=false more feasible for production

* Make the HTML error message prettier, with a nice red box and
  instructions to modify LocalSettings.php hidden in an HTML comment.
* Show the exception class name, since that's pretty safe.
* Show a random "log ID" to the user, and also send it to the exception
  log, to allow easier log correlation.
* Optionally send backtraces to the error log, enabled by default.

Change-Id: Ie92e46032b3d194c4217119567847a38a53be577
This commit is contained in:
Tim Starling 2012-05-08 09:53:58 +10:00
parent ec299eabb6
commit 70841c5867
3 changed files with 31 additions and 4 deletions

View file

@ -54,6 +54,8 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
* (bug 22887) Add warning and tracking category for preprocessor errors
* (bug 31704) Allow selection of associated namespace on the watchlist
* (bug 5445) Now remove autoblocks when a user is unblocked.
* Added $wgLogExceptionBacktrace, on by default, to allow logging of exception
backtraces.
=== Bug fixes in 1.20 ===
* (bug 30245) Use the correct way to construct a log page title.

View file

@ -4141,6 +4141,11 @@ $wgShowExceptionDetails = false;
*/
$wgShowDBErrorBacktrace = false;
/**
* If true, send the exception backtrace to the error log
*/
$wgLogExceptionBacktrace = true;
/**
* Expose backend server host names through the API and various HTML comments
*/

View file

@ -15,6 +15,8 @@
* @ingroup Exception
*/
class MWException extends Exception {
var $logId;
/**
* Should the exception use $wgOut to output the error ?
* @return bool
@ -111,9 +113,14 @@ class MWException extends Exception {
'</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) .
"</p>\n";
} else {
return "<p>Set <b><tt>\$wgShowExceptionDetails = true;</tt></b> " .
return
"<div class=\"errorbox\">" .
'[' . $this->getLogId() . '] ' .
gmdate( 'Y-m-d H:i:s' ) .
": Fatal exception of type " . get_class( $this ) . "</div>\n" .
"<!-- Set \$wgShowExceptionDetails = true; " .
"at the bottom of LocalSettings.php to show detailed " .
"debugging information.</p>";
"debugging information. -->";
}
}
@ -142,6 +149,13 @@ class MWException extends Exception {
return $this->msg( 'internalerror', "Internal error" );
}
function getLogId() {
if ( $this->logId === null ) {
$this->logId = wfRandomString( 8 );
}
return $this->logId;
}
/**
* Return the requested URL and point to file and line number from which the
* exception occured
@ -151,6 +165,7 @@ class MWException extends Exception {
function getLogMessage() {
global $wgRequest;
$id = $this->getLogId();
$file = $this->getFile();
$line = $this->getLine();
$message = $this->getMessage();
@ -164,7 +179,7 @@ class MWException extends Exception {
$url = '[no req]';
}
return "$url Exception from line $line of $file: $message";
return "[$id] $url Exception from line $line of $file: $message";
}
/** Output the exception report using HTML */
@ -198,11 +213,16 @@ class MWException extends Exception {
* It will be either HTML or plain text based on isCommandLine().
*/
function report() {
global $wgLogExceptionBacktrace;
$log = $this->getLogMessage();
if ( $log ) {
if ( $wgLogExceptionBacktrace ) {
wfDebugLog( 'exception', $log . "\n" . $this->getTraceAsString() . "\n" );
} else {
wfDebugLog( 'exception', $log );
}
}
if ( defined( 'MW_API' ) ) {
// Unhandled API exception, we can't be sure that format printer is alive