8000 [HttpKernel][DX] Allow the log level of http exceptions to be overridden by mtibben · Pull Request #25533 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[HttpKernel][DX] Allow the log level of http exceptions to be overridden #25533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Split into two listeners
  • Loading branch information
mtibben committed Jan 19, 2018
commit 15b15a5abe1045ad2cc1407bce9f288e28061228
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ public function getConfigTreeBuilder()
$this->addPhpErrorsSection($rootNode);
$this->addWebLinkSection($rootNode);
$this->addLockSection($rootNode);
$this->addHttpExceptionLogLevels($rootNode);

return $treeBuilder;
}
Expand Down Expand Up @@ -902,4 +903,43 @@ private function addWebLinkSection(ArrayNodeDefinition $rootNode)
->end()
;
}

private function addHttpExceptionLogLevels(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('http_exception_log_levels')
->info('The override log levels for http exceptions')
->example(array('403' => 'NOTICE', '404' => 'INFO'))
->useAttributeAsKey('http_exception_log_levels')
->prototype('variable')->end()
->validate()
->always(function ($v) {
$map = array();
foreach ($v as $status => $level) {
if (!(is_int($status) && $status >= 100 && $status <= 599)) {
throw new InvalidConfigurationException(sprintf(
'The configured status code "%s" in framework.http_exception_log_levels is not a valid http status code.',
$status
));
}

$levelConstant = 'Psr\Log\LogLevel::'.$level;
if (!defined($levelConstant)) {
throw new InvalidConfigurationException(sprintf(
'The configured log level "%s" in framework.http_exception_log_levels is invalid as it is not defined in Psr\\Log\\LogLevel.',
$level
));
}

$map[$status] = constant($levelConstant);
}

return $map;
})
->end()
->end()
->end()
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ public function load(array $configs, ContainerBuilder $container)
$container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
$container->setParameter('kernel.default_locale', $config['default_locale']);

$container->setParameter('framework.exception_listener.http_log_levels', $config['http_exception_log_levels']);

if (!$container->hasParameter('debug.file_link_format')) {
if (!$container->hasParameter('templating.helper.code.file_link_format')) {
$links = array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,13 @@
</service>

<service id="services_resetter" class="Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter" public="true" />

<service id="exception_logger" class="Symfony\Component\HttpKernel\EventListener\LoggingExceptionListener">
<tag name="kernel.event_subscriber" />
<tag name="monolog.logger" channel="request" />
<argument type="service" id="logger" on-invalid="null" />
<argument>%framework.exception_listener.http_log_levels%</argument>
</service>

</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
* TwigExtension configuration structure.
Expand Down Expand Up @@ -43,7 +42,6 @@ public function getConfigTreeBuilder()
$this->addGlobalsSection($rootNode);
$this->addTwigOptions($rootNode);
$this->addTwigFormatOptions($rootNode);
$this->addHttpExceptionLogLevels($rootNode);

return $treeBuilder;
}
Expand Down Expand Up @@ -196,43 +194,4 @@ private function addTwigFormatOptions(ArrayNodeDefinition $rootNode)
->end()
;
}

private function addHttpExceptionLogLevels(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('http_exception_log_levels')
->info('The override log levels for http exceptions')
->example(array('403' => 'NOTICE', '404' => 'INFO'))
->useAttributeAsKey('http_exception_log_levels')
->prototype('variable')->end()
->validate()
->always(function ($v) {
$map = array();
foreach ($v as $status => $level) {
if (!(is_int($status) && $status >= 100 && $status <= 599)) {
throw new InvalidConfigurationException(sprintf(
'The configured status code "%s" in twig.http_exception_log_levels is not a valid http status code.',
$status
));
}

$levelConstant = 'Psr\Log\LogLevel::'.$level;
if (!defined($levelConstant)) {
throw new InvalidConfigurationException(sprintf(
'The configured log level "%s" in twig.http_exception_log_levels is invalid as it is not defined in Psr\\Log\\LogLevel.',
$level
));
}

$map[$status] = constant($levelConstant);
}

return $map;
})
->end()
->end()
->end()
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ public function load(array $configs, ContainerBuilder $container)
$config = $this->processConfiguration($configuration, $configs);

$container->setParameter('twig.exception_listener.controller', $config['exception_controller']);
$container->setParameter('twig.exception_listener.http_log_levels', $config['http_exception_log_levels']);

$container->setParameter('twig.form.resources', $config['form_themes']);
$container->setParameter('twig.default_path', $config['default_path']);
Expand Down
3 changes: 1 addition & 2 deletions src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,11 @@
<argument type="service" id="workflow.registry" />
</service>

<service id="twig.exception_listener" class="Symfony\Component\HttpKernel\EventListener\ExceptionListener">
<service id="twig.exception_listener" class="Symfony\Component\HttpKernel\EventListener\RenderControllerExceptionListener">
<tag name="kernel.event_subscriber" />
<tag name="monolog.logger" channel="request" />
<argument>%twig.exception_listener.controller%</argument>
<argument type="service" id="logger" on-invalid="null" />
<argument>%twig.exception_listener.http_log_levels%</argument>
</service>

<service id="twig.controller.exception" class="Symfony\Bundle\TwigBundle\Controller\ExceptionController" public="true">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Component\HttpKernel\EventListener;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
Expand All @@ -24,22 +23,24 @@
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1 and will be removed in 5.0, use "%s" or "%s" instead.', ExceptionListener::class, RenderControllerExceptionListener::class, LoggingExceptionListener::class), E_USER_DEPRECATED);

/**
* ExceptionListener.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @deprecated since Symfony 4.1, use RenderControllerExceptionListener or LoggingExceptionListener instead
*/
class ExceptionListener implements EventSubscriberInterface
{
protected $controller;
protected $logger;
protected $httpStatusCodeLogLevel;

public function __construct($controller, LoggerInterface $logger = null, array $httpStatusCodeLogLevel = array())
public function __construct($controller, LoggerInterface $logger = null)
{
$this->controller = $controller;
$this->logger = $logger;
$this->httpStatusCodeLogLevel = $httpStatusCodeLogLevel;
}

public function logKernelException(GetResponseForExceptionEvent $event)
Expand Down Expand Up @@ -97,21 +98,6 @@ public static function getSubscribedEvents()
);
}

protected function getExceptionLogLevel(\Exception $exception): string
{
$logLevel = LogLevel::CRITICAL;
if ($exception instanceof HttpExceptionInterface) {
$statusCode = $exception->getStatusCode();
if (isset($this->httpStatusCodeLogLevel[$statusCode])) {
$logLevel = $this->httpStatusCodeLogLevel[$statusCode];
} elseif ($statusCode >= 400 && $statusCode < 500) {
$logLevel = LogLevel::WARNING;
}
}

return $logLevel;
}

/**
* Logs an exception.
*
Expand All @@ -121,7 +107,11 @@ protected function getExceptionLogLevel(\Exception $exception): string
protected function logException(\Exception $exception, $message)
{
if (null !== $this->logger) {
$this->logger->log($this->getExceptionLogLevel($exception), $message, array('exception' => $exception));
if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
$this->logger->critical($message, array('exception' => $exception));
} else {
$this->logger->error($message, array('exception' => $exception));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\EventListener;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;

class LoggingExceptionListener implements EventSubscriberInterface
{
protected $logger;
protected $httpStatusCodeLogLevel;

public function __construct(LoggerInterface $logger = null, array $httpStatusCodeLogLevel = array())
{
$this->logger = $logger ?: new NullLogger();
$this->httpStatusCodeLogLevel = $httpStatusCodeLogLevel;
}

public function logKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$level = $this->getExceptionLogLevel($exception);
$message = sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine());

$this->logger->log($level, $message, array('exception' => $exception));
}

public static function getSubscribedEvents(): array
{
return array(
KernelEvents::EXCEPTION => array(
array('logKernelException', 2048),
),
);
}

protected function getExceptionLogLevel(\Exception $exception): string
{
$logLevel = LogLevel::CRITICAL;
if ($exception instanceof HttpExceptionInterface) {
$statusCode = $exception->getStatusCode();
if (isset($this->httpStatusCodeLogLevel[$statusCode])) {
$logLevel = $this->httpStatusCodeLogLevel[$statusCode];
} elseif ($statusCode >= 400 && $statusCode < 500) {
$logLevel = LogLevel::WARNING;
}
}

return $logLevel;
}
}
Loading
0