Skip to content

Commit 8018a75

Browse files
committed
bug #177 Fix logger that logs to STDERR when no handlers are registered (fabpot)
This PR was submitted for the master branch but it was merged into the 2.x branch instead (closes #177). Discussion ---------- Fix logger that logs to STDERR when no handlers are registered Since Seldaek/monolog@ad37b7b, the `event` logger has no registered handlers in Symfony SE on the CLI. As Monolog 1.x automatically adds a STDERR handler when no handlers are registered, it means that logs (the event ones for instance) are output on STDERR by default with the Symfony CLI, which is exactly what we try to avoid. So, this PR adds a new compiler pass to register a null handler when a logger has no registered handlers to avoid having the default STDERR handler from Monolog. Commits ------- c3fbde4 fixed logger that logs to STDERR when no handlers are registered
2 parents 77618b5 + c3fbde4 commit 8018a75

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bundle\MonologBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
/**
20+
* Fixes loggers with no handlers (by registering a "null" one).
21+
*
22+
* Monolog 1.x adds a default handler logging on STDERR when a logger has
23+
* no registered handlers. This is NOT what what we want in Symfony, so in such
24+
* cases, we add a "null" handler to avoid the issue.
25+
*
26+
* Note that Monolog 2.x does not register a default handler anymore, so this pass can
27+
* be removed when MonologBundle minimum version of Monolog is bumped to 2.0.
28+
*
29+
* @author Fabien Potencier <[email protected]>
30+
*
31+
* @see https://github.com/Seldaek/monolog/commit/ad37b7b2d11f300cbace9f5e84f855d329519e28
32+
*/
33+
class FixEmptyLoggerPass implements CompilerPassInterface
34+
{
35+
private $channelPass;
36+
37+
public function __construct(LoggerChannelPass $channelPass)
38+
{
39+
$this->channelPass = $channelPass;
40+
}
41+
42+
public function process(ContainerBuilder $container)
43+
{
44+
$container->register('monolog.handler.null_internal', 'Monolog\Handler\NullHandler');
45+
foreach ($this->channelPass->getChannels() as $channel) {
46+
$def = $container->getDefinition($channel === 'app' ? 'monolog.logger' : 'monolog.logger.'.$channel);
47+
foreach ($def->getMethodCalls() as $method) {
48+
if ('pushHandler' === $method[0]) {
49+
continue 2;
50+
}
51+
}
52+
53+
$def->addMethodCall('pushHandler', array(new Reference('monolog.handler.null_internal')));
54+
}
55+
}
56+
}

MonologBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
2121
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\DebugHandlerPass;
2222
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\AddProcessorsPass;
23+
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\RemoveEmptyLoggerPass;
2324

2425
/**
2526
* Bundle.
@@ -34,6 +35,7 @@ public function build(ContainerBuilder $container)
3435

3536
$container->addCompilerPass($channelPass = new LoggerChannelPass());
3637
$container->addCompilerPass(new DebugHandlerPass($channelPass));
38+
$container->addCompilerPass(new RemoveEmptyLoggerPass($channelPass));
3739
$container->addCompilerPass(new AddProcessorsPass());
3840
$container->addCompilerPass(new AddSwiftMailerTransportPass());
3941
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Bundle\MonologBundle\Tests\DependencyInjection\Compiler;
13+
14+
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\FixEmptyLoggerPass;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
17+
class FixEmptyLoggerPassTest extends \PHPUnit_Framework_TestCase
18+
{
19+
public function testProcess()
20+
{
21+
$loggerChannelPass = $this->getMockBuilder('Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass')->getMock();
22+
$loggerChannelPass->expects($this->any())->method('getChannels')->will($this->returnValue(array('foo', 'bar')));
23+
24+
$container = new ContainerBuilder();
25+
$container->register('monolog.logger.foo', 'Monolog\Logger');
26+
$container->register('monolog.logger.bar', 'Monolog\Logger')->addMethodCall('pushHandler');
27+
28+
$pass = new FixEmptyLoggerPass($loggerChannelPass);
29+
$pass->process($container);
30+
31+
$calls = $container->getDefinition('monolog.logger.foo')->getMethodCalls();
32+
$this->assertCount(1, $calls);
33+
$this->assertSame('pushHandler', $calls[0][0]);
34+
$this->assertSame('monolog.handler.null_internal', (string) $calls[0][1][0]);
35+
36+
$calls = $container->getDefinition('monolog.logger.bar')->getMethodCalls();
37+
$this->assertCount(1, $calls);
38+
}
39+
}

0 commit comments

Comments
 (0)