[MonologBundle] Refactored the configuration of processors

This commit is contained in:
Christophe Coevoet 2011-07-06 15:50:39 +02:00
parent 082473659e
commit 874fb9540a
7 changed files with 71 additions and 55 deletions

View File

@ -9,6 +9,15 @@ timeline closely anyway.
RC4 to RC5 RC4 to RC5
---------- ----------
* The configuration of MonologBundle has been refactored.
* Only services are supported for the processors. They are now registered
using the `monolog.processor` tag which accept three optionnal attributes:
* `handler`: the name of an handler to register it only for a specific handler
* `channel`: to register it only for one logging channel (exclusive with `handler`)
* `method`: The method used to process the record (`__invoke` is used if not set)
* To avoid security issues, HTTP headers coming from proxies are not trusted * To avoid security issues, HTTP headers coming from proxies are not trusted
anymore by default (like `HTTP_X_FORWARDED_FOR`, `X_FORWARDED_PROTO`, and anymore by default (like `HTTP_X_FORWARDED_FOR`, `X_FORWARDED_PROTO`, and
`X_FORWARDED_HOST`). If your application is behind a reverse proxy, add the `X_FORWARDED_HOST`). If your application is behind a reverse proxy, add the
@ -20,7 +29,7 @@ RC4 to RC5
RC3 to RC4 RC3 to RC4
---------- ----------
* Annotation classes must be annotated with @Annotation * Annotation classes must be annotated with @Annotation
(see the validator constraints for examples) (see the validator constraints for examples)
* Annotations are not using the PHP autoloading but their own mechanism. This * Annotations are not using the PHP autoloading but their own mechanism. This

View File

@ -0,0 +1,59 @@
<?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\Bundle\MonologBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers processors in Monolg loggers or handlers.
*
* @author Christophe Coevoet <stof@notk.org>
*/
class AddProcessorsPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('monolog.logger')) {
return;
}
foreach ($container->findTaggedServiceIds('monolog.processor') as $id => $tags) {
foreach ($tags as $tag) {
if (!empty($tag['channel']) && !empty($tag['handler'])) {
throw new \InvalidArgumentException(sprintf('you cannot specify both the "handler" and "channel" attributes for the "monolog.processor" tag on service "%s"', $id));
}
if (!empty($tag['handler'])) {
$definition = $container->getDefinition(sprintf('monolog.handler.%s', $tag['handler']));
} elseif (!empty($tag['channel'])) {
if ('app' === $tag['channel']) {
$definition = $container->getDefinition('monolog.logger');
} else {
$definition = $container->getDefinition(sprintf('monolog.logger.%s', $tag['channel']));
}
} else {
$definition = $container->getDefinition('monolog.logger_prototype');
}
if (!empty($tag['method'])) {
$processor = array(new Reference($id), $tag['method']);
} else {
// If no method is defined, fallback to use __invoke
$processor = new Reference($id);
}
$definition->addMethodCall('pushProcessor', array($processor));
}
}
}
}

View File

@ -37,7 +37,6 @@ class Configuration implements ConfigurationInterface
$rootNode $rootNode
->fixXmlConfig('handler') ->fixXmlConfig('handler')
->fixXmlConfig('processor')
->children() ->children()
->arrayNode('handlers') ->arrayNode('handlers')
->canBeUnset() ->canBeUnset()
@ -77,7 +76,6 @@ class Configuration implements ConfigurationInterface
->scalarNode('email_prototype')->end() // swift_mailer ->scalarNode('email_prototype')->end() // swift_mailer
->scalarNode('formatter')->end() ->scalarNode('formatter')->end()
->end() ->end()
->append($this->getProcessorsNode())
->validate() ->validate()
->ifTrue(function($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type']) && 1 !== count($v['handler']); }) ->ifTrue(function($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type']) && 1 !== count($v['handler']); })
->thenInvalid('The handler has to be specified to use a FingersCrossedHandler or BufferHandler') ->thenInvalid('The handler has to be specified to use a FingersCrossedHandler or BufferHandler')
@ -101,23 +99,8 @@ class Configuration implements ConfigurationInterface
->end() ->end()
->end() ->end()
->end() ->end()
->append($this->getProcessorsNode())
; ;
return $treeBuilder; return $treeBuilder;
} }
private function getProcessorsNode()
{
$treeBuilder = new TreeBuilder();
$node = $treeBuilder->root('processors');
$node
->canBeUnset()
->performNoDeepMerging()
->prototype('scalar')->end()
;
return $node;
}
} }

View File

@ -49,10 +49,6 @@ class MonologExtension extends Extension
$logger = $container->getDefinition('monolog.logger_prototype'); $logger = $container->getDefinition('monolog.logger_prototype');
if (!empty($config['processors'])) {
$this->addProcessors($container, $logger, $config['processors']);
}
$handlers = array(); $handlers = array();
foreach ($config['handlers'] as $name => $handler) { foreach ($config['handlers'] as $name => $handler) {
$handlers[] = array('id' => $this->buildHandler($container, $name, $handler), 'priority' => $handler['priority'] ); $handlers[] = array('id' => $this->buildHandler($container, $name, $handler), 'priority' => $handler['priority'] );
@ -238,9 +234,6 @@ class MonologExtension extends Extension
if (!empty($handler['formatter'])) { if (!empty($handler['formatter'])) {
$definition->addMethodCall('setFormatter', array(new Reference($handler['formatter']))); $definition->addMethodCall('setFormatter', array(new Reference($handler['formatter'])));
} }
if (!empty($handler['processors'])) {
$this->addProcessors($container, $definition, $handler['processors']);
}
$container->setDefinition($handlerId, $definition); $container->setDefinition($handlerId, $definition);
return $handlerId; return $handlerId;
@ -251,13 +244,6 @@ class MonologExtension extends Extension
return sprintf('monolog.handler.%s', $name); return sprintf('monolog.handler.%s', $name);
} }
private function addProcessors(ContainerBuilder $container, Definition $definition, array $processors)
{
foreach (array_reverse($processors) as $processor) {
$definition->addMethodCall('pushProcessor', array($this->parseDefinition($processor, $container)));
}
}
private function parseDefinition($definition, ContainerBuilder $container = null) private function parseDefinition($definition, ContainerBuilder $container = null)
{ {
if (0 === strpos($definition, '@')) { if (0 === strpos($definition, '@')) {

View File

@ -15,6 +15,7 @@ use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass; use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\DebugHandlerPass; use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\DebugHandlerPass;
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\AddProcessorsPass;
/** /**
* Bundle. * Bundle.
@ -29,5 +30,6 @@ class MonologBundle extends Bundle
$container->addCompilerPass(new LoggerChannelPass()); $container->addCompilerPass(new LoggerChannelPass());
$container->addCompilerPass(new DebugHandlerPass()); $container->addCompilerPass(new DebugHandlerPass());
$container->addCompilerPass(new AddProcessorsPass());
} }
} }

View File

@ -18,8 +18,6 @@
<parameter key="monolog.handler.debug.class">Symfony\Bridge\Monolog\Handler\DebugHandler</parameter> <parameter key="monolog.handler.debug.class">Symfony\Bridge\Monolog\Handler\DebugHandler</parameter>
<parameter key="monolog.handler.swift_mailer.class">Monolog\Handler\SwiftMailerHandler</parameter> <parameter key="monolog.handler.swift_mailer.class">Monolog\Handler\SwiftMailerHandler</parameter>
<parameter key="monolog.handler.native_mailer.class">Monolog\Handler\NativeMailerHandler</parameter> <parameter key="monolog.handler.native_mailer.class">Monolog\Handler\NativeMailerHandler</parameter>
<parameter key="monolog.processor.web.class">Symfony\Bridge\Monolog\Processor\WebProcessor</parameter>
<parameter key="monolog.processor.introspection.class">Monolog\Processor\IntrospectionProcessor</parameter>
</parameters> </parameters>
<services> <services>
@ -32,11 +30,5 @@
<service id="monolog.logger_prototype" class="%monolog.logger.class%" abstract="true"> <service id="monolog.logger_prototype" class="%monolog.logger.class%" abstract="true">
<argument /><!-- Channel --> <argument /><!-- Channel -->
</service> </service>
<service id="monolog.processor.web" class="%monolog.processor.web.class%" scope="request" public="false">
<argument type="service" id="request" />
</service>
<service id="monolog.processor.introspection" class="%monolog.processor.introspection.class%" public="false" />
</services> </services>
</container> </container>

View File

@ -35,21 +35,6 @@ class MonologExtensionTest extends TestCase
$this->assertDICConstructorArguments($handler, array('%kernel.logs_dir%/%kernel.environment%.log', \Monolog\Logger::DEBUG, true)); $this->assertDICConstructorArguments($handler, array('%kernel.logs_dir%/%kernel.environment%.log', \Monolog\Logger::DEBUG, true));
} }
public function testLoadWithProcessor()
{
$container = new ContainerBuilder();
$loader = new MonologExtension();
$loader->load(array(array('handlers' => array('main' => array('type' => 'stream', 'processors' => array('@monolog.processor.web'))))), $container);
$this->assertTrue($container->hasDefinition('monolog.handler.main'));
$handler = $container->getDefinition('monolog.handler.main');
$this->assertDICDefinitionMethodCallAt(0, $handler, 'pushProcessor', array(new Reference('monolog.processor.web')));
$this->assertTrue($container->getDefinition('monolog.processor.web')->isPublic());
$this->assertFalse($container->getDefinition('monolog.processor.introspection')->isPublic());
}
public function testLoadWithCustomValues() public function testLoadWithCustomValues()
{ {
$container = new ContainerBuilder(); $container = new ContainerBuilder();