42 E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR,
54 set_exception_handler(
'MWExceptionHandler::handleException' );
55 set_error_handler(
'MWExceptionHandler::handleError' );
58 self::$reservedMemory = str_repeat(
' ', 16384 );
59 register_shutdown_function(
'MWExceptionHandler::handleFatalError' );
77 }
catch ( Exception $e2 ) {
94 $services = MediaWikiServices::getInstance();
95 if ( !
$services->isServiceDisabled(
'DBLoadBalancerFactory' ) ) {
100 $services->getDBLoadBalancerFactory()->rollbackMasterChanges( __METHOD__ );
107 self::logException( $e2, self::CAUGHT_BY_HANDLER );
111 self::logException(
$e, self::CAUGHT_BY_HANDLER );
129 self::rollbackMasterChangesAndLog(
$e );
152 $level, $message, $file =
null,
$line =
null
154 if ( in_array( $level, self::$fatalErrorTypes ) ) {
155 return call_user_func_array(
156 'MWExceptionHandler::handleFatalError', func_get_args()
163 case E_RECOVERABLE_ERROR:
164 $levelName =
'Error';
165 $severity = LogLevel::ERROR;
169 case E_COMPILE_WARNING:
171 $levelName =
'Warning';
172 $severity = LogLevel::WARNING;
176 $levelName =
'Notice';
177 $severity = LogLevel::INFO;
180 $levelName =
'Strict Standards';
181 $severity = LogLevel::DEBUG;
184 case E_USER_DEPRECATED:
185 $levelName =
'Deprecated';
186 $severity = LogLevel::INFO;
189 $levelName =
'Unknown error';
190 $severity = LogLevel::ERROR;
194 $e =
new ErrorException(
"PHP $levelName: $message", 0, $level, $file,
$line );
195 self::logError(
$e,
'error', $severity );
224 $level =
null, $message =
null, $file =
null,
$line =
null,
229 self::$reservedMemory =
null;
231 if ( $level ===
null ) {
233 if ( static::$handledFatalCallback ) {
239 $lastError = error_get_last();
240 if ( $lastError !==
null ) {
241 $level = $lastError[
'type'];
242 $message = $lastError[
'message'];
243 $file = $lastError[
'file'];
244 $line = $lastError[
'line'];
251 if ( !in_array( $level, self::$fatalErrorTypes ) ) {
257 $msg =
"[{exception_id}] PHP Fatal Error: {$message}";
262 if ( preg_match(
"/Class (undefined: \w+|'\w+' not found)/", $msg ) ) {
267MediaWiki or an installed extension
requires this class but it is not embedded directly in
MediaWiki's git repository and must be installed separately by the end user.
269Please see <a
href=
"https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries">mediawiki.org</a>
for help on installing the required components.
280 $trace = $trace ?: debug_backtrace();
281 $logger = LoggerFactory::getInstance(
'fatal' );
282 $logger->error( $msg, [
283 'fatal_exception' => [
284 'class' =>
'ErrorException',
285 'message' =>
"PHP Fatal Error: {$message}",
289 'trace' => static::redactTrace( $trace ),
292 'caught_by' => self::CAUGHT_BY_HANDLER
297 static::$handledFatalCallback =
true;
312 return self::prettyPrintTrace( self::getRedactedTrace(
$e ) );
327 foreach ( $trace as $level => $frame ) {
328 if ( isset( $frame[
'file'] ) && isset( $frame[
'line'] ) ) {
329 $text .=
"{$pad}#{$level} {$frame['file']}({$frame['line']}): ";
335 $text .=
"{$pad}#{$level} [internal function]: ";
338 if ( isset( $frame[
'class'] ) && isset( $frame[
'type'] ) && isset( $frame[
'function'] ) ) {
339 $text .= $frame[
'class'] . $frame[
'type'] . $frame[
'function'];
340 } elseif ( isset( $frame[
'function'] ) ) {
341 $text .= $frame[
'function'];
343 $text .=
'NO_FUNCTION_GIVEN';
346 if ( isset( $frame[
'args'] ) ) {
347 $text .=
'(' . implode(
', ', $frame[
'args'] ) .
")\n";
354 $text .=
"{$pad}#{$level} {main}";
371 return static::redactTrace(
$e->getTrace() );
385 return array_map(
function ( $frame ) {
386 if ( isset( $frame[
'args'] ) ) {
387 $frame[
'args'] = array_map(
function ( $arg ) {
388 return is_object( $arg ) ? get_class( $arg ) : gettype( $arg );
408 return WebRequest::getRequestId();
434 $id = WebRequest::getRequestId();
436 $file =
$e->getFile();
438 $message =
$e->getMessage();
439 $url = self::getURL() ?:
'[no req]';
441 return "[$id] $url $type from line $line of $file: $message";
455 $file =
$e->getFile();
457 $message =
$e->getMessage();
459 return "[{exception_id}] {exception_url} $type from line $line of $file: $message";
467 $reqId = WebRequest::getRequestId();
469 return '[' . $reqId .
'] '
470 . gmdate(
'Y-m-d H:i:s' ) .
': '
471 .
'Fatal exception of type "' .
$type .
'"';
488 'exception_id' => WebRequest::getRequestId(),
489 'exception_url' => self::getURL() ?:
'[no req]',
490 'caught_by' => $catcher
510 'id' => WebRequest::getRequestId(),
511 'type' => get_class(
$e ),
512 'file' =>
$e->getFile(),
513 'line' =>
$e->getLine(),
514 'message' =>
$e->getMessage(),
515 'code' =>
$e->getCode(),
516 'url' => self::getURL() ?:
null,
517 'caught_by' => $catcher
520 if (
$e instanceof ErrorException &&
521 ( error_reporting() &
$e->getSeverity() ) === 0
524 $data[
'suppressed'] =
true;
528 $data[
'backtrace'] = self::getRedactedTrace(
$e );
531 $previous =
$e->getPrevious();
532 if ( $previous !==
null ) {
533 $data[
'previous'] = self::getStructuredExceptionData( $previous, $catcher );
594 $e, $pretty =
false, $escaping = 0, $catcher = self::CAUGHT_BY_OTHER
596 return FormatJson::encode(
597 self::getStructuredExceptionData(
$e, $catcher ),
615 $logger = LoggerFactory::getInstance(
'exception' );
617 self::getLogNormalMessage(
$e ),
618 self::getLogContext(
$e, $catcher )
621 $json = self::jsonSerializeException(
$e,
false, FormatJson::ALL_OK, $catcher );
622 if ( $json !==
false ) {
623 $logger = LoggerFactory::getInstance(
'exception-json' );
624 $logger->error( $json, [
'private' =>
true ] );
627 Hooks::run(
'LogException', [
$e,
false ] );
640 ErrorException
$e, $channel, $level = LogLevel::ERROR
642 $catcher = self::CAUGHT_BY_HANDLER;
646 $suppressed = ( error_reporting() &
$e->getSeverity() ) === 0;
648 $logger = LoggerFactory::getInstance( $channel );
651 self::getLogNormalMessage(
$e ),
652 self::getLogContext(
$e, $catcher )
657 $json = self::jsonSerializeException(
$e,
false, FormatJson::ALL_OK, $catcher );
658 if ( $json !==
false ) {
659 $logger = LoggerFactory::getInstance(
"{$channel}-json" );
660 $logger->log( $level, $json, [
'private' =>
true ] );
$wgLogExceptionBacktrace
If true, send the exception backtrace to the error log.
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
if(! $wgDBerrorLogTZ) $wgRequest
WebRequest clone which takes values from a provided array.
Handler class for MWExceptions.
static handleError( $level, $message, $file=null, $line=null)
Handler for set_error_handler() callback notifications.
static getRedactedTraceAsString( $e)
Generate a string representation of an exception's stack trace.
static handleFatalError( $level=null, $message=null, $file=null, $line=null, $context=null, $trace=null)
Dual purpose callback used as both a set_error_handler() callback and a registered shutdown function.
static jsonSerializeException( $e, $pretty=false, $escaping=0, $catcher=self::CAUGHT_BY_OTHER)
Serialize an Exception object to JSON.
static getLogMessage( $e)
Get a message formatting the exception message and its origin.
static getPublicLogMessage( $e)
static prettyPrintTrace(array $trace, $pad='')
Generate a string representation of a stacktrace.
static getLogNormalMessage( $e)
Get a normalised message for formatting with PSR-3 log event context.
static logError(ErrorException $e, $channel, $level=LogLevel::ERROR)
Log an exception that wasn't thrown but made to wrap an error.
static rollbackMasterChangesAndLog( $e)
Roll back any open database transactions and log the stack trace of the exception.
static report( $e)
Report an exception to the user.
static getStructuredExceptionData( $e, $catcher=self::CAUGHT_BY_OTHER)
Get a structured representation of an Exception.
static redactTrace(array $trace)
Redact a stacktrace generated by Exception::getTrace(), debug_backtrace() or similar means.
static logException( $e, $catcher=self::CAUGHT_BY_OTHER)
Log an exception to the exception log (if enabled).
static installHandler()
Install handlers with PHP.
static $handledFatalCallback
static getRedactedTrace( $e)
Return a copy of an exception's backtrace as an array.
static getLogId( $e)
Get the ID for this exception.
static getURL()
If the exception occurred in the course of responding to a request, returns the requested URL.
static getLogContext( $e, $catcher=self::CAUGHT_BY_OTHER)
Get a PSR-3 log event context from an Exception.
static handleException( $e)
Exception handler which simulates the appropriate catch() handling:
static output( $e, $mode, $eNew=null)
returning false will NOT prevent logging a wrapping ErrorException $suppressed
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title after the basic globals have been set but before ordinary actions take place or wrap services the preferred way to define a new service is the $wgServiceWiringFiles array $services
returning false will NOT prevent logging $e