Added error reporting.
This commit is contained in:
parent
edc3cb03fc
commit
88dfe7a950
3 changed files with 80 additions and 65 deletions
|
@ -126,6 +126,8 @@ if (PHP_SAPI === 'cli') {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
ob_start($app->inDebugMode() ? null : 'ob_gzhandler');
|
||||
|
||||
$storage_dir = $app->getStoragePath();
|
||||
if (!$storage_dir->isReadable()
|
||||
|| !$storage_dir->isWritable()) {
|
||||
|
@ -133,10 +135,6 @@ if (PHP_SAPI === 'cli') {
|
|||
exit;
|
||||
}
|
||||
|
||||
if (!$app->inDebugMode()) {
|
||||
ob_start('ob_gzhandler');
|
||||
}
|
||||
|
||||
$app->startTemplating();
|
||||
$tpl = $app->getTemplating();
|
||||
|
||||
|
|
|
@ -61,9 +61,13 @@ class Application extends ApplicationBase
|
|||
{
|
||||
parent::__construct();
|
||||
$this->debugMode = $debug;
|
||||
ExceptionHandler::register();
|
||||
ExceptionHandler::debug($this->debugMode);
|
||||
$this->configInstance = new ConfigManager($configFile);
|
||||
|
||||
ExceptionHandler::register(
|
||||
$debug,
|
||||
$this->configInstance->get('Exceptions', 'report_url', 'string', null),
|
||||
$this->configInstance->get('Exceptions', 'hash_key', 'string', null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,12 @@ class ExceptionHandler
|
|||
*/
|
||||
private static $reportUrl = null;
|
||||
|
||||
/**
|
||||
* HMAC key that will be used to sign the request.
|
||||
* @var string
|
||||
*/
|
||||
private static $reportSign = null;
|
||||
|
||||
/**
|
||||
* Whether debug mode is active.
|
||||
* If true (or in CLI) a backtrace will be displayed.
|
||||
|
@ -25,19 +31,19 @@ class ExceptionHandler
|
|||
*/
|
||||
private static $debugMode = false;
|
||||
|
||||
/**
|
||||
* Internal bool used to prevent an infinite loop when the templating engine is not available.
|
||||
* @var bool
|
||||
*/
|
||||
private static $failSafe = false;
|
||||
|
||||
/**
|
||||
* Registers the exception handler and make it so all errors are thrown as ErrorExceptions.
|
||||
* @param bool $debugMode
|
||||
* @param string|null $reportUrl
|
||||
* @param string|null $reportSign
|
||||
*/
|
||||
public static function register(): void
|
||||
public static function register(bool $debugMode, ?string $reportUrl = null, ?string $reportSign = null): void
|
||||
{
|
||||
set_exception_handler([static::class, 'exception']);
|
||||
set_error_handler([static::class, 'error']);
|
||||
self::$debugMode = $debugMode;
|
||||
self::$reportUrl = $reportUrl;
|
||||
self::$reportSign = $reportSign;
|
||||
set_exception_handler([self::class, 'exception']);
|
||||
set_error_handler([self::class, 'error']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,15 +55,6 @@ class ExceptionHandler
|
|||
restore_error_handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns debug mode on or off.
|
||||
* @param bool $mode
|
||||
*/
|
||||
public static function debug(bool $mode): void
|
||||
{
|
||||
static::$debugMode = $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual handler for rendering and reporting exceptions.
|
||||
* Checks if the exception is extends on HttpException,
|
||||
|
@ -66,14 +63,13 @@ class ExceptionHandler
|
|||
*/
|
||||
public static function exception(Throwable $exception): void
|
||||
{
|
||||
$is_http = is_subclass_of($exception, HttpException::class);
|
||||
$report = !static::$debugMode && !$is_http && static::$reportUrl !== null;
|
||||
$report = !self::$debugMode && self::$reportUrl !== null;
|
||||
|
||||
if ($report) {
|
||||
static::report($exception);
|
||||
self::report($exception);
|
||||
}
|
||||
|
||||
static::render($exception, $report);
|
||||
self::render($exception, $report);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,59 +88,76 @@ class ExceptionHandler
|
|||
/**
|
||||
* Shoots a POST request to the report URL.
|
||||
* @todo Implement this.
|
||||
* @param Throwable $exception
|
||||
* @param Throwable $throwable
|
||||
*/
|
||||
private static function report(Throwable $exception): void
|
||||
private static function report(Throwable $throwable): bool
|
||||
{
|
||||
// send POST request with json encoded exception to destination
|
||||
if (!strlen(self::$reportUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!($curl = curl_init(self::$reportUrl))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$json = json_encode([
|
||||
'git' => [
|
||||
'branch' => git_branch(),
|
||||
'hash' => git_commit_hash(true),
|
||||
],
|
||||
'exception' => [
|
||||
'type' => get_class($throwable),
|
||||
'message' => $throwable->getMessage(),
|
||||
'code' => $throwable->getCode(),
|
||||
'file' => str_replace(dirname(__DIR__, 1), '', $throwable->getFile()),
|
||||
'line' => $throwable->getLine(),
|
||||
'trace' => $throwable->getTraceAsString(),
|
||||
],
|
||||
]);
|
||||
|
||||
$headers = [
|
||||
'Content-Type: application/json;charset=utf-8',
|
||||
];
|
||||
|
||||
if (strlen(self::$reportSign)) {
|
||||
$headers[] = 'X-Misuzu-Signature: sha256=' . hash_hmac('sha256', $json, self::$reportSign);
|
||||
}
|
||||
|
||||
$setOpts = curl_setopt_array($curl, [
|
||||
CURLOPT_TCP_NODELAY => true,
|
||||
CURLOPT_POSTFIELDS => $json,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
]);
|
||||
|
||||
if (!$setOpts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return curl_exec($curl) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders exceptions.
|
||||
* In debug or cli mode a backtrace is displayed.
|
||||
* Otherwise if the error extends on HttpException the respective error code is set.
|
||||
* If the View alias is still available the script will attempt to render a path 'errors/{error code}.twig'.
|
||||
* @param Throwable $exception
|
||||
* @param bool $reported
|
||||
*/
|
||||
private static function render(Throwable $exception, bool $reported): void
|
||||
{
|
||||
$is_http = false;//$exception instanceof HttpException;
|
||||
|
||||
if (PHP_SAPI === 'cli' || (!$is_http && static::$debugMode)) {
|
||||
if (PHP_SAPI !== 'cli' && !headers_sent()) {
|
||||
http_response_code(500);
|
||||
header('Content-Type: text/plain');
|
||||
}
|
||||
if (PHP_SAPI !== 'cli' && !headers_sent()) {
|
||||
ob_clean();
|
||||
http_response_code(500);
|
||||
header('Content-Type: text/plain');
|
||||
}
|
||||
|
||||
if (PHP_SAPI === 'cli' || self::$debugMode) {
|
||||
echo $exception;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
echo 'Something broke!';
|
||||
|
||||
$http_code = $is_http ? $exception->httpCode : 500;
|
||||
http_response_code($http_code);
|
||||
|
||||
static::$failSafe = true;
|
||||
/*if (!static::$failSafe && View::available()) {
|
||||
static::$failSafe = true;
|
||||
$template = "errors.{$http_code}";
|
||||
$namespace = View::findNamespace($template);
|
||||
|
||||
if ($namespace !== null) {
|
||||
echo View::render("@{$namespace}.{$template}", compact('reported'));
|
||||
return;
|
||||
if ($reported) {
|
||||
echo PHP_EOL . 'Information about this error has been sent to the devs.';
|
||||
}
|
||||
}*/
|
||||
|
||||
if ($is_http) {
|
||||
echo "Error {$http_code}";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Something broke!";
|
||||
|
||||
if ($reported) {
|
||||
echo "<br>The error has been reported to the developers.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue