mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 04:42:40 +01:00
Improve exception reporting behavior for core exceptions
Summary: See <https://github.com/facebook/phabricator/issues/487>. If an exception is thrown too high in the stack for the main exception handling to deal with it, we currently never report a stack trace. Instead: - Always report a stack trace to the error log. - With developer mode, also report a stack trace to the screen. Test Plan: Added a high-level `throw` and hit both cases. Got traces in the log and traces-under-developer-mode on screen. Reviewers: btrahan Reviewed By: btrahan CC: aran Differential Revision: https://secure.phabricator.com/D8022
This commit is contained in:
parent
c9a0ffa1cf
commit
56bcb33a18
2 changed files with 58 additions and 4 deletions
|
@ -198,9 +198,54 @@ final class PhabricatorStartup {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Fatal the request completely in response to an exception, sending a plain
|
||||||
|
* text message to the client. Calls @{method:didFatal} internally.
|
||||||
|
*
|
||||||
|
* @param string Brief description of the exception context, like
|
||||||
|
* `"Rendering Exception"`.
|
||||||
|
* @param Exception The exception itself.
|
||||||
|
* @param bool True if it's okay to show the exception's stack trace
|
||||||
|
* to the user. The trace will always be logged.
|
||||||
|
* @return exit This method **does not return**.
|
||||||
|
*
|
||||||
* @task apocalypse
|
* @task apocalypse
|
||||||
*/
|
*/
|
||||||
public static function didFatal($message) {
|
public static function didEncounterFatalException(
|
||||||
|
$note,
|
||||||
|
Exception $ex,
|
||||||
|
$show_trace) {
|
||||||
|
|
||||||
|
$message = '['.$note.'/'.get_class($ex).'] '.$ex->getMessage();
|
||||||
|
|
||||||
|
$full_message = $message;
|
||||||
|
$full_message .= "\n\n";
|
||||||
|
$full_message .= $ex->getTraceAsString();
|
||||||
|
|
||||||
|
if ($show_trace) {
|
||||||
|
$message = $full_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::didFatal($message, $full_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fatal the request completely, sending a plain text message to the client.
|
||||||
|
*
|
||||||
|
* @param string Plain text message to send to the client.
|
||||||
|
* @param string Plain text message to send to the error log. If not
|
||||||
|
* provided, the client message is used. You can pass a more
|
||||||
|
* detailed message here (e.g., with stack traces) to avoid
|
||||||
|
* showing it to users.
|
||||||
|
* @return exit This method **does not return**.
|
||||||
|
*
|
||||||
|
* @task apocalypse
|
||||||
|
*/
|
||||||
|
public static function didFatal($message, $log_message = null) {
|
||||||
|
if ($log_message === null) {
|
||||||
|
$log_message = $message;
|
||||||
|
}
|
||||||
|
|
||||||
self::endOutputCapture();
|
self::endOutputCapture();
|
||||||
$access_log = self::getGlobal('log.access');
|
$access_log = self::getGlobal('log.access');
|
||||||
|
|
||||||
|
@ -219,7 +264,7 @@ final class PhabricatorStartup {
|
||||||
$replace = true,
|
$replace = true,
|
||||||
$http_error = 500);
|
$http_error = 500);
|
||||||
|
|
||||||
error_log($message);
|
error_log($log_message);
|
||||||
echo $message;
|
echo $message;
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
require_once dirname(dirname(__FILE__)).'/support/PhabricatorStartup.php';
|
require_once dirname(dirname(__FILE__)).'/support/PhabricatorStartup.php';
|
||||||
PhabricatorStartup::didStartup();
|
PhabricatorStartup::didStartup();
|
||||||
|
|
||||||
|
$show_unexpected_traces = false;
|
||||||
try {
|
try {
|
||||||
PhabricatorStartup::loadCoreLibraries();
|
PhabricatorStartup::loadCoreLibraries();
|
||||||
|
|
||||||
PhabricatorEnv::initializeWebEnvironment();
|
PhabricatorEnv::initializeWebEnvironment();
|
||||||
|
$show_unexpected_traces = PhabricatorEnv::getEnvConfig(
|
||||||
|
'phabricator.developer-mode');
|
||||||
|
|
||||||
// This is the earliest we can get away with this, we need env config first.
|
// This is the earliest we can get away with this, we need env config first.
|
||||||
PhabricatorAccessLog::init();
|
PhabricatorAccessLog::init();
|
||||||
|
@ -124,7 +127,10 @@ try {
|
||||||
$ex,
|
$ex,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
PhabricatorStartup::didFatal('[Rendering Exception] '.$ex->getMessage());
|
PhabricatorStartup::didEncounterFatalException(
|
||||||
|
'Rendering Exception',
|
||||||
|
$ex,
|
||||||
|
$show_unexpected_traces);
|
||||||
}
|
}
|
||||||
|
|
||||||
$write_guard->dispose();
|
$write_guard->dispose();
|
||||||
|
@ -137,6 +143,9 @@ try {
|
||||||
|
|
||||||
DarkConsoleXHProfPluginAPI::saveProfilerSample($access_log);
|
DarkConsoleXHProfPluginAPI::saveProfilerSample($access_log);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
PhabricatorStartup::didFatal("[Exception] ".$ex->getMessage());
|
PhabricatorStartup::didEncounterFatalException(
|
||||||
|
'Core Exception',
|
||||||
|
$ex,
|
||||||
|
$show_unexpected_traces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue