Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Logger register shut down #5875

Merged
merged 3 commits into from Mar 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions library/Zend/Log/Logger.php
Expand Up @@ -60,6 +60,13 @@ class Logger implements LoggerInterface
*/
protected static $registeredErrorHandler = false;

/**
* Registered shutdown error handler
*
* @var bool
*/
protected static $registeredFatalErrorShutdownFunction = false;

/**
* Registered exception handler
*
Expand Down Expand Up @@ -154,6 +161,10 @@ public function __construct($options = null)
static::registerErrorHandler($this);
}

if (isset($options['fatal_error_shutdownfunction']) && $options['fatal_error_shutdownfunction'] === true) {
static::registerFatalErrorShutdownFunction($this);
}

} elseif ($options) {
throw new Exception\InvalidArgumentException('Options must be an array or an object implementing \Traversable ');
}
Expand Down Expand Up @@ -554,6 +565,41 @@ public static function unregisterErrorHandler()
static::$registeredErrorHandler = false;
}


/**
* Register a shutdown handler to log fatal errors
*
* @link http://www.php.net/manual/function.register-shutdown-function.php
* @param Logger $logger
* @return bool
*/
public static function registerFatalErrorShutdownFunction(Logger $logger)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a silly question, but is there a specific reason for this method to be on this class?

{
// Only register once per instance
if (static::$registeredFatalErrorShutdownFunction) {
return false;
}

$errorPriorityMap = static::$errorPriorityMap;

register_shutdown_function(function () use ($logger, $errorPriorityMap) {
$error = error_get_last();
if (null !== $error && $error['type'] === E_ERROR) {
$logger->log($errorPriorityMap[E_ERROR],
$error['message'],
array(
'file' => $error['file'],
'line' => $error['line']
)
);
}
});

static::$registeredFatalErrorShutdownFunction = true;
return true;
}


/**
* Register logging system as an exception handler to log PHP exceptions
*
Expand Down
23 changes: 23 additions & 0 deletions tests/ZendTest/Log/LoggerTest.php
Expand Up @@ -410,4 +410,27 @@ public function testErrorHandlerWithStreamWriter()
$this->assertContains('test', $contents);
$this->assertContains('second', $contents);
}

/**
* @runInSeparateProcess
*/
public function testRegisterFatalShutdownFunction()
{
$writer = new MockWriter;
$this->logger->addWriter($writer);

$result = Logger::registerFatalErrorShutdownFunction($this->logger);
$this->assertTrue($result);

// check for single error handler instance
$this->assertFalse(Logger::registerFatalErrorShutdownFunction($this->logger));

$self = $this;
register_shutdown_function(function () use ($writer, $self) {
$self->assertEquals($writer->events[0]['message'], 'Call to undefined method ZendTest\Log\LoggerTest::callToNonExistingMethod()');
});

// Temporary hide errors, because we don't want the fatal error to fail the test
@$this->callToNonExistingMethod();
}
}