diff --git a/src/Monolog/ErrorHandler.php b/src/Monolog/ErrorHandler.php index 4098c09c..31d98a6f 100644 --- a/src/Monolog/ErrorHandler.php +++ b/src/Monolog/ErrorHandler.php @@ -28,7 +28,7 @@ class ErrorHandler private $logger; private $previousExceptionHandler; - private $uncaughtExceptionLevel; + private $uncaughtExceptionLevelMap; private $previousErrorHandler; private $errorLevelMap; @@ -49,19 +49,19 @@ class ErrorHandler * By default it will handle errors, exceptions and fatal errors * * @param LoggerInterface $logger - * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling - * @param int|false $exceptionLevel a LogLevel::* constant, or false to disable exception handling - * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling + * @param array|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling + * @param array|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling + * @param int|false $fatalLevel a LogLevel::* constant, or false to disable fatal error handling * @return ErrorHandler */ - public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null) + public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevelMap = array(), $fatalLevel = null) { $handler = new static($logger); if ($errorLevelMap !== false) { $handler->registerErrorHandler($errorLevelMap); } - if ($exceptionLevel !== false) { - $handler->registerExceptionHandler($exceptionLevel); + if ($exceptionLevelMap !== false) { + $handler->registerExceptionHandler($exceptionLevelMap); } if ($fatalLevel !== false) { $handler->registerFatalHandler($fatalLevel); @@ -70,10 +70,10 @@ class ErrorHandler return $handler; } - public function registerExceptionHandler($level = null, $callPrevious = true) + public function registerExceptionHandler($levelMap = array(), $callPrevious = true) { $prev = set_exception_handler(array($this, 'handleException')); - $this->uncaughtExceptionLevel = $level; + $this->uncaughtExceptionLevelMap = array_replace($this->defaultExceptionLevelMap(), $levelMap); if ($callPrevious && $prev) { $this->previousExceptionHandler = $prev; } @@ -97,6 +97,14 @@ class ErrorHandler $this->hasFatalErrorHandler = true; } + protected function defaultExceptionLevelMap() + { + return array( + 'ParseError' => LogLevel::CRITICAL, + 'Throwable' => LogLevel::ERROR, + ); + } + protected function defaultErrorLevelMap() { return array( @@ -123,8 +131,16 @@ class ErrorHandler */ public function handleException($e) { + $level = LogLevel::ERROR; + foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) { + if ($e instanceof $class) { + $level = $candidate; + break; + } + } + $this->logger->log( - $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel, + $level, sprintf('Uncaught Exception %s: "%s" at %s line %s', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()), array('exception' => $e) ); diff --git a/tests/Monolog/ErrorHandlerTest.php b/tests/Monolog/ErrorHandlerTest.php index a9a3f301..6d7305c3 100644 --- a/tests/Monolog/ErrorHandlerTest.php +++ b/tests/Monolog/ErrorHandlerTest.php @@ -28,4 +28,31 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase $this->assertCount(2, $handler->getRecords()); $this->assertTrue($handler->hasEmergencyRecords()); } + + public function testHandleException() + { + $logger = new Logger('test', array($handler = new TestHandler)); + $errHandler = new ErrorHandler($logger); + + $errHandler->registerExceptionHandler(array('Monolog\CustomTestException' => Logger::ALERT, 'Throwable' => Logger::WARNING), false); + + try { + throw new CustomCustomException(); + $this->assertCount(1, $handler->getRecords()); + $this->assertTrue($handler->hasAlertRecords()); + } catch (\Throwable $e) {} + try { + throw new CustomTestException(); + $this->assertCount(2, $handler->getRecords()); + $this->assertTrue($handler->hasAlertRecords()); + } catch (\Throwable $e) {} + try { + throw new RuntimeException(); + $this->assertCount(3, $handler->getRecords()); + $this->assertTrue($handler->hasWarningRecords()); + } catch (\Throwable $e) {} + } } + +class CustomTestException extends \Exception {} +class CustomCustomException extends CustomTestException {}