Skip to content

Commit 0e28c20

Browse files
lyrixxfabpot
authored andcommitted
[HttpKernel] Add support for configuring log level, and status code by exception class
1 parent 5306f8a commit 0e28c20

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* Deprecate `AbstractTestSessionListener::getSession` inject a session in the request instead
88
* Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener`
9+
* Add support for configuring log level, and status code by exception class
910

1011
5.3
1112
---

EventListener/ErrorListener.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,30 @@ class ErrorListener implements EventSubscriberInterface
3232
protected $controller;
3333
protected $logger;
3434
protected $debug;
35+
protected $exceptionsMapping;
3536

36-
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false)
37+
public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = [])
3738
{
3839
$this->controller = $controller;
3940
$this->logger = $logger;
4041
$this->debug = $debug;
42+
$this->exceptionsMapping = $exceptionsMapping;
4143
}
4244

4345
public function logKernelException(ExceptionEvent $event)
4446
{
45-
$e = FlattenException::createFromThrowable($event->getThrowable());
47+
$throwable = $event->getThrowable();
48+
$logLevel = null;
49+
foreach ($this->exceptionsMapping as $class => $config) {
50+
if ($throwable instanceof $class && $config['log_level']) {
51+
$logLevel = $config['log_level'];
52+
break;
53+
}
54+
}
55+
56+
$e = FlattenException::createFromThrowable($throwable);
4657

47-
$this->logException($event->getThrowable(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()));
58+
$this->logException($throwable, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()), $logLevel);
4859
}
4960

5061
public function onKernelException(ExceptionEvent $event)
@@ -53,8 +64,8 @@ public function onKernelException(ExceptionEvent $event)
5364
return;
5465
}
5566

56-
$exception = $event->getThrowable();
57-
$request = $this->duplicateRequest($exception, $event->getRequest());
67+
$throwable = $event->getThrowable();
68+
$request = $this->duplicateRequest($throwable, $event->getRequest());
5869

5970
try {
6071
$response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false);
@@ -65,18 +76,25 @@ public function onKernelException(ExceptionEvent $event)
6576

6677
$prev = $e;
6778
do {
68-
if ($exception === $wrapper = $prev) {
79+
if ($throwable === $wrapper = $prev) {
6980
throw $e;
7081
}
7182
} while ($prev = $wrapper->getPrevious());
7283

7384
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
7485
$prev->setAccessible(true);
75-
$prev->setValue($wrapper, $exception);
86+
$prev->setValue($wrapper, $throwable);
7687

7788
throw $e;
7889
}
7990

91+
foreach ($this->exceptionsMapping as $exception => $config) {
92+
if ($throwable instanceof $exception && $config['status_code']) {
93+
$response->setStatusCode($config['status_code']);
94+
break;
95+
}
96+
}
97+
8098
$event->setResponse($response);
8199

82100
if ($this->debug) {
@@ -124,10 +142,12 @@ public static function getSubscribedEvents(): array
124142
/**
125143
* Logs an exception.
126144
*/
127-
protected function logException(\Throwable $exception, string $message): void
145+
protected function logException(\Throwable $exception, string $message, string $logLevel = null): void
128146
{
129147
if (null !== $this->logger) {
130-
if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
148+
if (null !== $logLevel) {
149+
$this->logger->log($logLevel, $message, ['exception' => $exception]);
150+
} elseif (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
131151
$this->logger->critical($message, ['exception' => $exception]);
132152
} else {
133153
$this->logger->error($message, ['exception' => $exception]);

Tests/EventListener/ErrorListenerTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,27 @@ public function testHandleWithLogger($event, $event2)
9797
$this->assertCount(3, $logger->getLogs('critical'));
9898
}
9999

100+
public function testHandleWithLoggerAndCustomConfiguration()
101+
{
102+
$request = new Request();
103+
$event = new ExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MAIN_REQUEST, new \RuntimeException('bar'));
104+
$logger = new TestLogger();
105+
$l = new ErrorListener('not used', $logger, false, [
106+
\RuntimeException::class => [
107+
'log_level' => 'warning',
108+
'status_code' => 401,
109+
],
110+
]);
111+
$l->logKernelException($event);
112+
$l->onKernelException($event);
113+
114+
$this->assertEquals(new Response('foo', 401), $event->getResponse());
115+
116+
$this->assertEquals(0, $logger->countErrors());
117+
$this->assertCount(0, $logger->getLogs('critical'));
118+
$this->assertCount(1, $logger->getLogs('warning'));
119+
}
120+
100121
public function provider()
101122
{
102123
if (!class_exists(Request::class)) {

0 commit comments

Comments
 (0)