[BC Break][Debug] #2042 implementation of fatal error logging

This commit is contained in:
Konstantin.Myakshin 2013-04-10 08:14:53 +03:00 committed by Fabien Potencier
parent 6f0a5ad314
commit 7671e5c85d
6 changed files with 63 additions and 20 deletions

View File

@ -48,15 +48,18 @@ class FrameworkExtension extends Extension
// will be used and everything will still work as expected.
$loader->load('translation.xml');
if ($container->getParameter('kernel.debug')) {
$loader->load('debug.xml');
$loader->load('debug.xml');
if ($container->getParameter('kernel.debug')) {
// only HttpKernel needs the debug event dispatcher
$definition = $container->findDefinition('http_kernel');
$arguments = $definition->getArguments();
$arguments[0] = new Reference('debug.event_dispatcher');
$arguments[2] = new Reference('debug.controller_resolver');
$definition->setArguments($arguments);
} else {
$container->removeDefinition('debug.deprecation_logger_listener');
$container->setParameter('debug.container.dump', null);
}
$configuration = $this->getConfiguration($configs, $container);

View File

@ -9,7 +9,7 @@
<parameter key="debug.stopwatch.class">Symfony\Component\Stopwatch\Stopwatch</parameter>
<parameter key="debug.container.dump">%kernel.cache_dir%/%kernel.container_class%.xml</parameter>
<parameter key="debug.controller_resolver.class">Symfony\Component\HttpKernel\Controller\TraceableControllerResolver</parameter>
<parameter key="debug.deprecation_logger_listener.class">Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener</parameter>
<parameter key="debug.errors_logger_listener.class">Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener</parameter>
</parameters>
<services>
@ -28,9 +28,17 @@
<argument type="service" id="debug.stopwatch" />
</service>
<service id="debug.deprecation_logger_listener" class="%debug.deprecation_logger_listener.class%">
<service id="debug.deprecation_logger_listener" class="%debug.errors_logger_listener.class%">
<tag name="kernel.event_subscriber" />
<tag name="monolog.logger" channel="deprecation" />
<argument>deprecation</argument>
<argument type="service" id="logger" on-invalid="null" />
</service>
<service id="debug.emergency_logger_listener" class="%debug.errors_logger_listener.class%">
<tag name="kernel.event_subscriber" />
<tag name="monolog.logger" channel="emergency" />
<argument>emergency</argument>
<argument type="service" id="logger" on-invalid="null" />
</service>
</services>

View File

@ -31,8 +31,9 @@ class Debug
* class loader is also registered.
*
* @param integer $errorReportingLevel The level of error reporting you want
* @param Boolean $displayErrors Display errors (for dev environment) or just log they (production usage)
*/
public static function enable($errorReportingLevel = null)
public static function enable($errorReportingLevel = null, $displayErrors = true)
{
if (static::$enabled) {
return;
@ -42,10 +43,10 @@ class Debug
error_reporting(-1);
ErrorHandler::register($errorReportingLevel);
ErrorHandler::register($errorReportingLevel, $displayErrors);
if ('cli' !== php_sapi_name()) {
ExceptionHandler::register();
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
} elseif (!ini_get('log_errors') || ini_get('error_log') && $displayErrors) {
ini_set('display_errors', 1);
}

View File

@ -18,6 +18,7 @@ use Psr\Log\LoggerInterface;
* ErrorHandler.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
class ErrorHandler
{
@ -43,20 +44,26 @@ class ErrorHandler
private $reservedMemory;
/** @var LoggerInterface */
private static $logger;
private $displayErrors;
/**
* @var LoggerInterface[] Loggers for channels
*/
private static $loggers = array();
/**
* Registers the error handler.
*
* @param integer $level The level at which the conversion to Exception is done (null to use the error_reporting() value and 0 to disable)
* @param Boolean $displayErrors Display errors (for dev environment) or just log they (production usage)
*
* @return The registered error handler
*/
public static function register($level = null)
public static function register($level = null, $displayErrors = true)
{
$handler = new static();
$handler->setLevel($level);
$handler->setDisplayErrors($displayErrors);
ini_set('display_errors', 0);
set_error_handler(array($handler, 'handle'));
@ -71,9 +78,14 @@ class ErrorHandler
$this->level = null === $level ? error_reporting() : $level;
}
public static function setLogger(LoggerInterface $logger)
public function setDisplayErrors($displayErrors)
{
self::$logger = $logger;
$this->displayErrors = $displayErrors;
}
public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
{
self::$loggers[$channel] = $logger;
}
/**
@ -86,7 +98,7 @@ class ErrorHandler
}
if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
if (null !== self::$logger) {
if (isset(self::$loggers['deprecation'])) {
if (version_compare(PHP_VERSION, '5.4', '<')) {
$stack = array_map(
function ($row) {
@ -99,13 +111,13 @@ class ErrorHandler
$stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
}
self::$logger->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
self::$loggers['deprecation']->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
}
return true;
}
if (error_reporting() & $level && $this->level & $level) {
if ($this->displayErrors && error_reporting() & $level && $this->level & $level) {
throw new \ErrorException(sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line), 0, $level, $file, $line);
}
@ -124,6 +136,20 @@ class ErrorHandler
return;
}
if (isset(self::$loggers['emergency'])) {
$fatal = array(
'type' => $type,
'file' => $error['file'],
'line' => $error['line'],
);
self::$loggers['emergency']->emerg($error['message'], $fatal);
}
if (!$this->displayErrors) {
return;
}
// get current exception handler
$exceptionHandler = set_exception_handler(function() {});
restore_exception_handler();

View File

@ -4,6 +4,7 @@ CHANGELOG
2.3.0
-----
* [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor
* deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`,
`Symfony\Component\HttpKernel\Exception\FatalErrorException`, and `Symfony\Component\HttpKernel\Exception\FlattenException`
* deprecated `Symfony\Component\HttpKernel\Kernel::init()``
@ -21,7 +22,7 @@ CHANGELOG
* added ControllerReference to create reference of Controllers (used in the FragmentRenderer class)
* [BC BREAK] renamed TimeDataCollector::getTotalTime() to
TimeDataCollector::getDuration()
* updated the MemoryDataCollector to include the memory used in the
* updated the MemoryDataCollector to include the memory used in the
kernel.terminate event listeners
* moved the Stopwatch classes to a new component
* added TraceableControllerResolver

View File

@ -17,23 +17,27 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Injects the logger into the ErrorHandler, so that it can log deprecation errors.
* Injects the logger into the ErrorHandler, so that it can log various errors.
*
* @author Colin Frei <colin@colinfrei.com>
* @author Konstantin Myakshin <koc-dp@yandex.ru>
*/
class DeprecationLoggerListener implements EventSubscriberInterface
class ErrorsLoggerListener implements EventSubscriberInterface
{
private $channel;
private $logger;
public function __construct(LoggerInterface $logger = null)
public function __construct($channel, LoggerInterface $logger = null)
{
$this->channel = $channel;
$this->logger = $logger;
}
public function injectLogger()
{
if (null !== $this->logger) {
ErrorHandler::setLogger($this->logger);
ErrorHandler::setLogger($this->logger, $this->channel);
}
}