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 {
|
} else {
|
||||||
|
ob_start($app->inDebugMode() ? null : 'ob_gzhandler');
|
||||||
|
|
||||||
$storage_dir = $app->getStoragePath();
|
$storage_dir = $app->getStoragePath();
|
||||||
if (!$storage_dir->isReadable()
|
if (!$storage_dir->isReadable()
|
||||||
|| !$storage_dir->isWritable()) {
|
|| !$storage_dir->isWritable()) {
|
||||||
|
@ -133,10 +135,6 @@ if (PHP_SAPI === 'cli') {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$app->inDebugMode()) {
|
|
||||||
ob_start('ob_gzhandler');
|
|
||||||
}
|
|
||||||
|
|
||||||
$app->startTemplating();
|
$app->startTemplating();
|
||||||
$tpl = $app->getTemplating();
|
$tpl = $app->getTemplating();
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,13 @@ class Application extends ApplicationBase
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->debugMode = $debug;
|
$this->debugMode = $debug;
|
||||||
ExceptionHandler::register();
|
|
||||||
ExceptionHandler::debug($this->debugMode);
|
|
||||||
$this->configInstance = new ConfigManager($configFile);
|
$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;
|
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.
|
* Whether debug mode is active.
|
||||||
* If true (or in CLI) a backtrace will be displayed.
|
* If true (or in CLI) a backtrace will be displayed.
|
||||||
|
@ -25,19 +31,19 @@ class ExceptionHandler
|
||||||
*/
|
*/
|
||||||
private static $debugMode = false;
|
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.
|
* 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']);
|
self::$debugMode = $debugMode;
|
||||||
set_error_handler([static::class, 'error']);
|
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();
|
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.
|
* The actual handler for rendering and reporting exceptions.
|
||||||
* Checks if the exception is extends on HttpException,
|
* Checks if the exception is extends on HttpException,
|
||||||
|
@ -66,14 +63,13 @@ class ExceptionHandler
|
||||||
*/
|
*/
|
||||||
public static function exception(Throwable $exception): void
|
public static function exception(Throwable $exception): void
|
||||||
{
|
{
|
||||||
$is_http = is_subclass_of($exception, HttpException::class);
|
$report = !self::$debugMode && self::$reportUrl !== null;
|
||||||
$report = !static::$debugMode && !$is_http && static::$reportUrl !== null;
|
|
||||||
|
|
||||||
if ($report) {
|
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.
|
* Shoots a POST request to the report URL.
|
||||||
* @todo Implement this.
|
* @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.
|
* Renders exceptions.
|
||||||
* In debug or cli mode a backtrace is displayed.
|
* 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 Throwable $exception
|
||||||
* @param bool $reported
|
* @param bool $reported
|
||||||
*/
|
*/
|
||||||
private static function render(Throwable $exception, bool $reported): void
|
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()) {
|
if (PHP_SAPI !== 'cli' && !headers_sent()) {
|
||||||
|
ob_clean();
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
header('Content-Type: text/plain');
|
header('Content-Type: text/plain');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PHP_SAPI === 'cli' || self::$debugMode) {
|
||||||
echo $exception;
|
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 ($is_http) {
|
|
||||||
echo "Error {$http_code}";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Something broke!";
|
|
||||||
|
|
||||||
if ($reported) {
|
if ($reported) {
|
||||||
echo "<br>The error has been reported to the developers.";
|
echo PHP_EOL . 'Information about this error has been sent to the devs.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue