diff --git a/app/Config/core.php b/app/Config/core.php index c705ece8a..44271a6a9 100644 --- a/app/Config/core.php +++ b/app/Config/core.php @@ -70,6 +70,9 @@ * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/Lib/Error. This class needs to implement a render method. * - `log` - boolean - Should Exceptions be logged? + * - `skipLog` - array - list of exceptions to skip for logging. Exceptions that + * extend one of the listed exceptions will also be skipped for logging. + * Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')` * * @see ErrorHandler for more information on exception handling and configuration. */ diff --git a/lib/Cake/Console/Templates/skel/Config/core.php b/lib/Cake/Console/Templates/skel/Config/core.php index c705ece8a..c3e5efa6b 100644 --- a/lib/Cake/Console/Templates/skel/Config/core.php +++ b/lib/Cake/Console/Templates/skel/Config/core.php @@ -70,6 +70,9 @@ * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/Lib/Error. This class needs to implement a render method. * - `log` - boolean - Should Exceptions be logged? + * - `skipLog` - array - list of exceptions to skip for logging. Exceptions that + * extend one of the listed exceptions will also be skipped for logging. + * Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')` * * @see ErrorHandler for more information on exception handling and configuration. */ diff --git a/lib/Cake/Error/ErrorHandler.php b/lib/Cake/Error/ErrorHandler.php index a8867ae88..f5b0decc0 100644 --- a/lib/Cake/Error/ErrorHandler.php +++ b/lib/Cake/Error/ErrorHandler.php @@ -110,9 +110,8 @@ class ErrorHandler { */ public static function handleException(Exception $exception) { $config = Configure::read('Exception'); - if (!empty($config['log'])) { - CakeLog::write(LOG_ERR, self::_getMessage($exception)); - } + self::_log($exception, $config); + $renderer = $config['renderer']; if ($renderer !== 'ExceptionRenderer') { list($plugin, $renderer) = pluginSplit($renderer, true); @@ -159,6 +158,28 @@ class ErrorHandler { return $message; } +/** + * Handles exception logging + * + * @param Exception $exception + * @param array $config + * @return boolean + */ + protected static function _log(Exception $exception, $config) { + if (empty($config['log'])) { + return false; + } + + if (!empty($config['skipLog'])) { + foreach ((array)$config['skipLog'] as $class) { + if ($exception instanceof $class) { + return false; + } + } + } + return CakeLog::write(LOG_ERR, self::_getMessage($exception)); + } + /** * Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own * error handling methods. This function will use Debugger to display errors when debug > 0. And diff --git a/lib/Cake/Test/Case/Error/ErrorHandlerTest.php b/lib/Cake/Test/Case/Error/ErrorHandlerTest.php index 4b150de50..851de4869 100644 --- a/lib/Cake/Test/Case/Error/ErrorHandlerTest.php +++ b/lib/Cake/Test/Case/Error/ErrorHandlerTest.php @@ -195,8 +195,6 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ public function testHandleException() { - $this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.'); - $error = new NotFoundException('Kaboom!'); ob_start(); ErrorHandler::handleException($error); @@ -210,8 +208,6 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ public function testHandleExceptionLog() { - $this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.'); - if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } @@ -224,8 +220,37 @@ class ErrorHandlerTest extends CakeTestCase { $this->assertRegExp('/Kaboom!/', $result, 'message missing.'); $log = file(LOGS . 'error.log'); - $this->assertRegExp('/\[NotFoundException\] Kaboom!/', $log[0], 'message missing.'); - $this->assertRegExp('/\#0.*ErrorHandlerTest->testHandleExceptionLog/', $log[2], 'Stack trace missing.'); + $this->assertContains('[NotFoundException] Kaboom!', $log[0], 'message missing.'); + $this->assertContains('ErrorHandlerTest->testHandleExceptionLog', $log[2], 'Stack trace missing.'); + } + +/** + * test handleException generating log. + * + * @return void + */ + public function testHandleExceptionLogSkipping() { + if (file_exists(LOGS . 'error.log')) { + unlink(LOGS . 'error.log'); + } + Configure::write('Exception.log', true); + Configure::write('Exception.skipLog', array('NotFoundException')); + $notFound = new NotFoundException('Kaboom!'); + $forbidden = new ForbiddenException('Fooled you!'); + + ob_start(); + ErrorHandler::handleException($notFound); + $result = ob_get_clean(); + $this->assertRegExp('/Kaboom!/', $result, 'message missing.'); + + ob_start(); + ErrorHandler::handleException($forbidden); + $result = ob_get_clean(); + $this->assertRegExp('/Fooled you!/', $result, 'message missing.'); + + $log = file(LOGS . 'error.log'); + $this->assertNotContains('[NotFoundException] Kaboom!', $log[0], 'message should not be logged.'); + $this->assertContains('[ForbiddenException] Fooled you!', $log[0], 'message missing.'); } /** @@ -257,8 +282,6 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ public function testHandleFatalErrorPage() { - $this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.'); - $line = __LINE__; ob_start(); @@ -286,8 +309,6 @@ class ErrorHandlerTest extends CakeTestCase { * @return void */ public function testHandleFatalErrorLog() { - $this->skipIf(file_exists(APP . 'app_error.php'), 'App error exists cannot run.'); - if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); }