8000 Add basic support for automatic console exception logging · symfony/symfony@87eee63 · GitHub
[go: up one dir, main page]

Skip to content

Commit 87eee63

Browse files
jameshalsallchalasr
authored andcommitted
Add basic support for automatic console exception logging
1 parent 63b8d31 commit 87eee63

File tree

4 files changed

+202
-0
lines changed

4 files changed

+202
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public function load(array $configs, ContainerBuilder $container)
8282
}
8383

8484
$loader->load('fragment_renderer.xml');
85+
$loader->load('conso 10000 le.xml');
8586

8687
// Property access is used by both the Form and the Validator component
8788
$loader->load('property_access.xml');
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<services>
8+
<service id="console.exception_listener" class="Symfony\Component\Console\EventListener\ExceptionListener">
9+
<tag name="kernel.event_subscriber" />
10+
<argument type="service" id="logger" on-invalid="null" />
11+
</service>
12+
</services>
13+
</container>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\EventListener;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Console\ConsoleEvents;
16+
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
17+
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
18+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
19+
20+
/**
21+
* Console exception listener.
22+
*
23+
* Attempts to log exceptions or abnormal terminations of console commands.
24+
*
25+
* @author James Halsall <james.t.halsall@googlemail.com>
26+
*/
27+
class ExceptionListener implements EventSubscriberInterface
28+
{
29+
/**
30+
* @var LoggerInterface
31+
*/
32+
protected $logger;
33+
34+
/**
35+
* Constructor.
36+
*
37+
* @param LoggerInterface $logger A logger
38+
*/
39+
public function __construct(LoggerInterface $logger = null)
40+
{
41+
$this->logger = $logger;
42+
}
43+
44+
/**
45+
* Handles console command exception.
46+
*
47+
* @param ConsoleExceptionEvent $event Console event
48+
*/
49+
public function onKernelException(ConsoleExceptionEvent $event)
50+
{
51+
if (null === $this->logger) {
52+
return;
53+
}
54+
55+
$exception = $event->getException();
56+
$input = (string) $event->getInput();
57+
58+
$this->logger->error('Exception thrown while running command: "{command}". Message: "{message}"', array('exception' => $exception, 'command' => $input, 'message' => $exception->getMessage()));
59+
}
60+
61+
/**
62+
* Handles termination of console command.
63+
*
64+
* @param ConsoleTerminateEvent $event Console event
65+
*/
66+
public function onKernelTerminate(ConsoleTerminateEvent $event)
67+
{
68+
if (null === $this->logger) {
69+
return;
70+
}
71+
72+
$exitCode = $event->getExitCode();
73+
74+
if ($exitCode === 0) {
75+
return;
76+
}
77+
78+
$input = (string) $event->getInput();
79+
80+
$this->logger->error('Command "{command}" exited with status code "{code}"', array('command' => (string) $input, 'code' => $exitCode));
81+
}
82+
83+
public static function getSubscribedEvents()
84+
{
85+
return array(
86+
ConsoleEvents::EXCEPTION => array('onKernelException', -128),
87+
ConsoleEvents::TERMINATE => array('onKernelTerminate', -128),
88+
);
89+
}
90+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\Tests\EventListener;
13+
14+
use Psr\Log\LoggerInterface;
15+
use Symfony\Component\Console\Command\Command;
16+
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
17+
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
18+
use Symfony\Component\Console\EventListener\ExceptionListener;
19+
use Symfony\Component\Console\Input\ArrayInput;
20+
use Symfony\Component\Console\Tests\Output\TestOutput;
21+
22+
class ExceptionListenerTest extends \PHPUnit_Framework_TestCase
23+
{
24+
public function testOnKernelException()
25+
{
26+
$logger = $this->getLogger();
27+
$listener = new ExceptionListener($logger);
28+
29+
$exception = new \RuntimeException('An error occurred');
30+
31+
$logger
32+
->expects($this->once())
33+
->method('error')
34+
->with('Exception thrown while running command: "{command}". Message: "{message}"', array('exception' => $exception, 'command' => '\'test:run\' --foo=baz buzz', 'message' => 'An error occurred'))
35+
;
36+
37+
$input = array(
38+
'name' => 'test:run',
39+
'--foo' => 'baz',
40+
'bar' => 'buzz'
41+
);
42+
43+
$listener->onKernelException($this->getConsoleExceptionEvent($exception, $input, 1));
44+
}
45+
46+
public function testOnKernelTerminateForNonZeroExitCodeWritesToLog()
47+
{
48+
$logger = $this->getLogger();
49+
$listener = new ExceptionListener($logger);
50+
51+
$logger
52+
->expects($this->once())
53+
->method('error')
54+
->with('Command "{command}" exited with status code "{code}"', array('command' => '\'test:run\'', 'code' => 255))
55+
;
56+
57+
$listener->onKernelTerminate($this->getConsoleTerminateEvent(array('name' => 'test:run'), 255));
58+
}
59+
60+
public function testOnKernelTerminateForZeroExitCodeDoesNotWriteToLog()
61+
{
62+
$logger = $this->getLogger();
63+
$listener = new ExceptionListener($logger);
64+
65+
$logger
66+
->expects($this->never())
67+
->method('error')
68+
;
69+
70+
$listener->onKernelTerminate($this->getConsoleTerminateEvent(array('name' => 'test:run'), 0));
71+
}
72+
73+
public function testGetSubscribedEvents()
74+
{
75+
$this->assertEquals(
76+
array(
77+
'console.exception' => array('onKernelException', -128),
78+
'console.terminate' => array('onKernelTerminate' B41A , -128),
79+
),
80+
ExceptionListener::getSubscribedEvents()
81+
);
82+
}
83+
84+
private function getLogger()
85+
{
86+
return $this->getMockForAbstractClass(LoggerInterface::class);
87+
}
88+
89+
private function getConsoleExceptionEvent(\Exception $exception, $input, $exitCode)
90+
{
91+
return new ConsoleExceptionEvent(new Command('test:run'), new ArrayInput($input), new TestOutput(), $exception, $exitCode);
92+
}
93+
94+
private function getConsoleTerminateEvent($input, $exitCode)
95+
{
96+
return new ConsoleTerminateEvent(new Command('test:run'), new ArrayInput($input), new TestOutput(), $exitCode);
97+
}
98+
}

0 commit comments

Comments
 (0)
0