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 22887) Add warning and tracking category for preprocessor errors
* (bug 31704) Allow selection of associated namespace on the watchlist * (bug 31704) Allow selection of associated namespace on the watchlist
* (bug 5445) Now remove autoblocks when a user is unblocked. * (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 fixes in 1.20 ===
* (bug 30245) Use the correct way to construct a log page title. * (bug 30245) Use the correct way to construct a log page title.

View file

@ -4141,6 +4141,11 @@ $wgShowExceptionDetails = false;
*/ */
$wgShowDBErrorBacktrace = 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 * Expose backend server host names through the API and various HTML comments
*/ */

View file

@ -15,6 +15,8 @@
* @ingroup Exception * @ingroup Exception
*/ */
class MWException extends Exception { class MWException extends Exception {
var $logId;
/** /**
* Should the exception use $wgOut to output the error ? * Should the exception use $wgOut to output the error ?
* @return bool * @return bool
@ -111,9 +113,14 @@ class MWException extends Exception {
'</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) . '</p><p>Backtrace:</p><p>' . nl2br( htmlspecialchars( $this->getTraceAsString() ) ) .
"</p>\n"; "</p>\n";
} else { } 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 " . "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" ); 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 * Return the requested URL and point to file and line number from which the
* exception occured * exception occured
@ -151,6 +165,7 @@ class MWException extends Exception {
function getLogMessage() { function getLogMessage() {
global $wgRequest; global $wgRequest;
$id = $this->getLogId();
$file = $this->getFile(); $file = $this->getFile();
$line = $this->getLine(); $line = $this->getLine();
$message = $this->getMessage(); $message = $this->getMessage();
@ -164,7 +179,7 @@ class MWException extends Exception {
$url = '[no req]'; $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 */ /** 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(). * It will be either HTML or plain text based on isCommandLine().
*/ */
function report() { function report() {
global $wgLogExceptionBacktrace;
$log = $this->getLogMessage(); $log = $this->getLogMessage();
if ( $log ) { if ( $log ) {
if ( $wgLogExceptionBacktrace ) {
wfDebugLog( 'exception', $log . "\n" . $this->getTraceAsString() . "\n" );
} else {
wfDebugLog( 'exception', $log ); wfDebugLog( 'exception', $log );
} }
}
if ( defined( 'MW_API' ) ) { if ( defined( 'MW_API' ) ) {
// Unhandled API exception, we can't be sure that format printer is alive // Unhandled API exception, we can't be sure that format printer is alive