-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpKernel] Add support for configuring log level, and status code by exception class #42244
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | ||
|
||
$container->loadFromExtension('framework', [ | ||
'exceptions' => [ | ||
BadRequestHttpException::class => [ | ||
'log_level' => 'info', | ||
'status_code' => 422, | ||
], | ||
], | ||
]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" ?> | ||
<container xmlns="http://symfony.com/schema/dic/services" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns:framework="http://symfony.com/schema/dic/symfony" | ||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd | ||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> | ||
|
||
<framework:config> | ||
<framework:exceptions> | ||
<framework:exception name="Symfony\Component\HttpKernel\Exception\BadRequestHttpException" log-level="info" status-code="422" /> | ||
</framework:exceptions> | ||
</framework:config> | ||
</container> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
framework: | ||
exceptions: | ||
Symfony\Component\HttpKernel\Exception\BadRequestHttpException: | ||
log_level: info | ||
status_code: 422 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,19 +32,30 @@ class ErrorListener implements EventSubscriberInterface | |
protected $controller; | ||
protected $logger; | ||
protected $debug; | ||
protected $exceptionsMapping; | ||
|
||
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false) | ||
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = []) | ||
{ | ||
$this->controller = $controller; | ||
$this->logger = $logger; | ||
$this->debug = $debug; | ||
$this->exceptionsMapping = $exceptionsMapping; | ||
} | ||
|
||
public function logKernelException(ExceptionEvent $event) | ||
{ | ||
$e = FlattenException::createFromThrowable($event->getThrowable()); | ||
$throwable = $event->getThrowable(); | ||
$logLevel = null; | ||
foreach ($this->exceptionsMapping as $class => $config) { | ||
if ($throwable instanceof $class && $config['log_level']) { | ||
$logLevel = $config['log_level']; | ||
break; | ||
} | ||
} | ||
|
||
$e = FlattenException::createFromThrowable($throwable); | ||
|
||
$this->logException($event->getThrowable(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine())); | ||
$this->logException($throwable, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()), $logLevel); | ||
} | ||
|
||
public function onKernelException(ExceptionEvent $event) | ||
|
@@ -53,8 +64,8 @@ public function onKernelException(ExceptionEvent $event) | |
return; | ||
} | ||
|
||
$exception = $event->getThrowable(); | ||
$request = $this->duplicateRequest($exception, $event->getRequest()); | ||
$throwable = $event->getThrowable(); | ||
$request = $this->duplicateRequest($throwable, $event->getRequest()); | ||
|
||
try { | ||
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); | ||
|
@@ -65,18 +76,25 @@ public function onKernelException(ExceptionEvent $event) | |
|
||
$prev = $e; | ||
do { | ||
if ($exception === $wrapper = $prev) { | ||
if ($throwable === $wrapper = $prev) { | ||
throw $e; | ||
} | ||
} while ($prev = $wrapper->getPrevious()); | ||
|
||
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); | ||
$prev->setAccessible(true); | ||
$prev->setValue($wrapper, $exception); | ||
$prev->setValue($wrapper, $throwable); | ||
|
||
throw $e; | ||
} | ||
|
||
foreach ($this->exceptionsMapping as $exception => $config) { | ||
if ($throwable instanceof $exception && $config['status_code']) { | ||
$response->setStatusCode($config['status_code']); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this work? The response is rendered L71 before this happens so whilst the response will have the correct status code the page rendered may not be matching. For example the ErrorController will render a page for a 500 although the status code will be altered here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't undestant. The status code you write in the configuration is the one you want. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Of the created response. In the case you are dealing with an API, you probably do not care. However, if you are dealing with an HTML response, then you probably have a different template if it's a 400 or a 500. From what I see here although you override the status code from a 500 to a 400 for example, the rendered page would still look like you had a 500 (and with the default template it shows the status code, i.e. 500). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might need to update |
||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that the order you define the exceptions in your config is important. I don't mind, but this should be documented. |
||
} | ||
} | ||
|
||
$event->setResponse($response); | ||
|
||
if ($this->debug) { | ||
|
@@ -124,10 +142,12 @@ public static function getSubscribedEvents(): array | |
/** | ||
* Logs an exception. | ||
*/ | ||
protected function logException(\Throwable $exception, string $message): void | ||
protected function logException(\Throwable $exception, string $message, string $logLevel = null): void | ||
{ | ||
if (null !== $this->logger) { | ||
if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { | ||
if (null !== $logLevel) { | ||
$this->logger->log($logLevel, $message, ['exception' => $exception]); | ||
} elseif (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { | ||
$this->logger->critical($message, ['exception' => $exception]); | ||
} else { | ||
$this->logger->error($message, ['exception' => $exception]); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the invalid message is inconsistent with the check
range(100, 499)
while invalid message contains text like100 et 599
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please send a PR? Let's also replace this range() by two comparisons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check see: #43399