1
0
mirror of https://github.com/Seldaek/monolog.git synced 2025-08-01 10:50:21 +02:00

Custom exception handler (#500)

Add custom exception handler to let the user change the default
behavior when Monolog raise an exception while logging a record.
This commit is contained in:
Vincent Paré
2017-06-27 23:29:27 +02:00
parent fd8c787753
commit 207c91699e
2 changed files with 126 additions and 8 deletions

View File

@@ -133,6 +133,11 @@ class Logger implements LoggerInterface
*/
protected $microsecondTimestamps = true;
/**
* @var callable
*/
protected $exceptionHandler;
/**
* @param string $name The logging channel
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
@@ -329,16 +334,20 @@ class Logger implements LoggerInterface
'extra' => array(),
);
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
while ($handler = current($this->handlers)) {
if (true === $handler->handle($record)) {
break;
try {
foreach ($this->processors as $processor) {
$record = call_user_func($processor, $record);
}
next($this->handlers);
while ($handler = current($this->handlers)) {
if (true === $handler->handle($record)) {
break;
}
next($this->handlers);
}
} catch (\Exception $ex) {
$this->handleException($ex, $record);
}
return true;
@@ -501,6 +510,46 @@ class Logger implements LoggerInterface
return false;
}
/**
* Set a custom exception handler
*
* @param callable $callback
* @return $this
*/
public function setExceptionHandler($callback)
{
if (!is_callable($callback)) {
throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
}
$this->exceptionHandler = $callback;
return $this;
}
/**
* @return callable
*/
public function getExceptionHandler()
{
return $this->exceptionHandler;
}
/**
* Delegates exception management to the custom exception handler,
* or throws the exception if no custom handler is set.
*
* @param Exception $ex
* @param array $record
*/
protected function handleException(\Exception $ex, $record)
{
if ($this->exceptionHandler) {
call_user_func($this->exceptionHandler, $ex, $record);
} else {
throw $ex;
}
}
/**
* Adds a log record at an arbitrary level.
*

View File

@@ -545,4 +545,73 @@ class LoggerTest extends \PHPUnit_Framework_TestCase
'without microseconds' => array(false, PHP_VERSION_ID >= 70100 ? 'assertNotSame' : 'assertSame'),
);
}
/**
* @covers Monolog\Logger::setExceptionHandler
*/
public function testSetExceptionHandler()
{
$logger = new Logger(__METHOD__);
$this->assertNull($logger->getExceptionHandler());
$callback = function ($ex) {
};
$logger->setExceptionHandler($callback);
$this->assertEquals($callback, $logger->getExceptionHandler());
}
/**
* @covers Monolog\Logger::setExceptionHandler
* @expectedException InvalidArgumentException
*/
public function testBadExceptionHandlerType()
{
$logger = new Logger(__METHOD__);
$logger->setExceptionHandler(false);
}
/**
* @covers Monolog\Logger::handleException
* @expectedException Exception
*/
public function testDefaultHandleException()
{
$logger = new Logger(__METHOD__);
$handler = $this->getMock('Monolog\Handler\HandlerInterface');
$handler->expects($this->any())
->method('isHandling')
->will($this->returnValue(true))
;
$handler->expects($this->any())
->method('handle')
->will($this->throwException(new \Exception('Some handler exception')))
;
$logger->pushHandler($handler);
$logger->info('test');
}
/**
* @covers Monolog\Logger::handleException
* @covers Monolog\Logger::addRecord
*/
public function testCustomHandleException()
{
$logger = new Logger(__METHOD__);
$that = $this;
$logger->setExceptionHandler(function ($e, $record) use ($that) {
$that->assertEquals($e->getMessage(), 'Some handler exception');
$that->assertTrue(is_array($record));
$that->assertEquals($record['message'], 'test');
});
$handler = $this->getMock('Monolog\Handler\HandlerInterface');
$handler->expects($this->any())
->method('isHandling')
->will($this->returnValue(true))
;
$handler->expects($this->any())
->method('handle')
->will($this->throwException(new \Exception('Some handler exception')))
;
$logger->pushHandler($handler);
$logger->info('test');
}
}