diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index bad48b84..79b902e5 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -75,6 +75,13 @@ * - [stop_buffering]: bool to disable buffering once the handler has been activated, defaults to true * - [bubble]: bool, defaults to true * + * - filter: + * - handler: the wrapped handler's name + * - [accepted_levels]: list of levels to accept + * - [min_level]: minimum level to accept (only used if accepted_levels not specified) + * - [max_level]: maximum level to accept (only used if accepted_levels not specified) + * - [bubble]: bool, defaults to true + * * - buffer: * - handler: the wrapped handler's name * - [buffer_size]: defaults to 0 (unlimited) @@ -219,6 +226,7 @@ public function getConfigTreeBuilder() ->fixXmlConfig('member') ->fixXmlConfig('excluded_404') ->fixXmlConfig('tag') + ->fixXmlConfig('accepted_level') ->canBeUnset() ->children() ->scalarNode('type') @@ -245,6 +253,12 @@ public function getConfigTreeBuilder() ->canBeUnset() ->prototype('scalar')->end() ->end() + ->arrayNode('accepted_levels') // filter + ->canBeUnset() + ->prototype('scalar')->end() + ->end() + ->scalarNode('min_level')->defaultValue('DEBUG')->end() // filter + ->scalarNode('max_level')->defaultValue('EMERGENCY')->end() //filter ->scalarNode('buffer_size')->defaultValue(0)->end() // fingers_crossed and buffer ->scalarNode('handler')->end() // fingers_crossed and buffer ->scalarNode('url')->end() // cube @@ -475,13 +489,21 @@ public function getConfigTreeBuilder() ->thenInvalid('Service handlers can not have a formatter configured in the bundle, you must reconfigure the service itself instead') ->end() ->validate() - ->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') + ->ifTrue(function($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type'] || 'filter' === $v['type']) && 1 !== count($v['handler']); }) + ->thenInvalid('The handler has to be specified to use a FingersCrossedHandler or BufferHandler or FilterHandler') ->end() ->validate() ->ifTrue(function($v) { return 'fingers_crossed' === $v['type'] && !empty($v['excluded_404s']) && !empty($v['activation_strategy']); }) ->thenInvalid('You can not use excluded_404s together with a custom activation_strategy in a FingersCrossedHandler') ->end() + ->validate() + ->ifTrue(function($v) { return 'filter' === $v['type'] && "DEBUG" !== $v['min_level'] && !empty($v['accepted_levels']); }) + ->thenInvalid('You can not use min_level together with accepted_levels in a FilterHandler') + ->end() + ->validate() + ->ifTrue(function($v) { return 'filter' === $v['type'] && "EMERGENCY" !== $v['max_level'] && !empty($v['accepted_levels']); }) + ->thenInvalid('You can not use max_level together with accepted_levels in a FilterHandler') + ->end() ->validate() ->ifTrue(function($v) { return 'swift_mailer' === $v['type'] && empty($v['email_prototype']) && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject'])); }) ->thenInvalid('The sender, recipient and subject or an email prototype have to be specified to use a SwiftMailerHandler') diff --git a/DependencyInjection/MonologExtension.php b/DependencyInjection/MonologExtension.php index 31251380..00762eb5 100644 --- a/DependencyInjection/MonologExtension.php +++ b/DependencyInjection/MonologExtension.php @@ -31,6 +31,11 @@ class MonologExtension extends Extension private $swiftMailerHandlers = array(); + private function levelToMonologConst($level) + { + return is_int($level) ? $level : constant('Monolog\Logger::'.strtoupper($level)); + } + /** * Loads the Monolog configuration. * @@ -85,6 +90,7 @@ public function load(array $configs, ContainerBuilder $container) 'Monolog\\Handler\\AbstractProcessingHandler', 'Monolog\\Handler\\StreamHandler', 'Monolog\\Handler\\FingersCrossedHandler', + 'Monolog\\Handler\\FilterHandler', 'Monolog\\Handler\\TestHandler', 'Monolog\\Logger', 'Symfony\\Bridge\\Monolog\\Logger', @@ -116,7 +122,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler { $handlerId = $this->getHandlerId($name); $definition = new Definition(sprintf('%%monolog.handler.%s.class%%', $handler['type'])); - $handler['level'] = is_int($handler['level']) ? $handler['level'] : constant('Monolog\Logger::'.strtoupper($handler['level'])); + $handler['level'] = $this->levelToMonologConst($handler['level']); switch ($handler['type']) { case 'service': @@ -240,7 +246,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler break; case 'fingers_crossed': - $handler['action_level'] = is_int($handler['action_level']) ? $handler['action_level'] : constant('Monolog\Logger::'.strtoupper($handler['action_level'])); + $handler['action_level'] = $this->levelToMonologConst($handler['action_level']); $nestedHandlerId = $this->getHandlerId($handler['handler']); $this->nestedHandlers[] = $nestedHandlerId; @@ -264,6 +270,25 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler )); break; + case 'filter': + $handler['min_level'] = $this->levelToMonologConst($handler['min_level']); + $handler['max_level'] = $this->levelToMonologConst($handler['max_level']); + foreach (array_keys($handler['accepted_levels']) as $k) { + $handler['accepted_levels'][$k] = $this->levelToMonologConst($handler['accepted_levels'][$k]); + } + + $nestedHandlerId = $this->getHandlerId($handler['handler']); + $this->nestedHandlers[] = $nestedHandlerId; + $minLevelOrList = !empty($handler['accepted_levels']) ? $handler['accepted_levels'] : $handler['min_level']; + + $definition->setArguments(array( + new Reference($nestedHandlerId), + $minLevelOrList, + $handler['max_level'], + $handler['bubble'] + )); + break; + case 'buffer': $nestedHandlerId = $this->getHandlerId($handler['handler']); $this->nestedHandlers[] = $nestedHandlerId; diff --git a/Resources/config/monolog.xml b/Resources/config/monolog.xml index a672cbb0..7f213821 100644 --- a/Resources/config/monolog.xml +++ b/Resources/config/monolog.xml @@ -37,6 +37,7 @@ Monolog\Handler\FingersCrossedHandler Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy + Monolog\Handler\FilterHandler Monolog\Handler\MongoDBHandler MongoClient diff --git a/Resources/config/schema/monolog-1.0.xsd b/Resources/config/schema/monolog-1.0.xsd index 73a47156..c177919c 100644 --- a/Resources/config/schema/monolog-1.0.xsd +++ b/Resources/config/schema/monolog-1.0.xsd @@ -22,6 +22,7 @@ + @@ -35,6 +36,8 @@ + + diff --git a/Tests/DependencyInjection/FixtureMonologExtensionTest.php b/Tests/DependencyInjection/FixtureMonologExtensionTest.php index 96c24218..9fc1ee5d 100644 --- a/Tests/DependencyInjection/FixtureMonologExtensionTest.php +++ b/Tests/DependencyInjection/FixtureMonologExtensionTest.php @@ -28,9 +28,10 @@ public function testLoadWithSeveralHandlers() $this->assertTrue($container->hasDefinition('monolog.handler.nested')); $logger = $container->getDefinition('monolog.logger'); - $this->assertCount(2, $logger->getMethodCalls()); - $this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', array(new Reference('monolog.handler.custom'))); - $this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', array(new Reference('monolog.handler.main'))); + $this->assertCount(3, $logger->getMethodCalls()); + $this->assertDICDefinitionMethodCallAt(2, $logger, 'pushHandler', array(new Reference('monolog.handler.custom'))); + $this->assertDICDefinitionMethodCallAt(1, $logger, 'pushHandler', array(new Reference('monolog.handler.main'))); + $this->assertDICDefinitionMethodCallAt(0, $logger, 'pushHandler', array(new Reference('monolog.handler.filtered'))); $handler = $container->getDefinition('monolog.handler.custom'); $this->assertDICDefinitionClass($handler, '%monolog.handler.stream.class%'); @@ -39,6 +40,10 @@ public function testLoadWithSeveralHandlers() $handler = $container->getDefinition('monolog.handler.main'); $this->assertDICDefinitionClass($handler, '%monolog.handler.fingers_crossed.class%'); $this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested'), \Monolog\Logger::ERROR, 0, true, true)); + + $handler = $container->getDefinition('monolog.handler.filtered'); + $this->assertDICDefinitionClass($handler, '%monolog.handler.filter.class%'); + $this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested2'), array(\Monolog\Logger::WARNING, \Monolog\Logger::ERROR), \Monolog\Logger::EMERGENCY, true)); } public function testLoadWithOverwriting() diff --git a/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml b/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml index fe98c55c..8abe0875 100644 --- a/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml +++ b/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml @@ -10,5 +10,10 @@ + + WARNING + ERROR + + diff --git a/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml b/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml index 14af13e3..32f69c70 100644 --- a/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml +++ b/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml @@ -11,3 +11,9 @@ monolog: handler: nested nested: type: stream + filtered: + type: filter + accepted_levels: [WARNING, ERROR] + handler: nested2 + nested2: + type: stream diff --git a/Tests/DependencyInjection/MonologExtensionTest.php b/Tests/DependencyInjection/MonologExtensionTest.php index 2e8fe052..9dac6d69 100644 --- a/Tests/DependencyInjection/MonologExtensionTest.php +++ b/Tests/DependencyInjection/MonologExtensionTest.php @@ -70,6 +70,17 @@ public function testExceptionWhenUsingFingerscrossedWithoutHandler() $loader->load(array(array('handlers' => array('main' => array('type' => 'fingers_crossed')))), $container); } + /** + * @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + */ + public function testExceptionWhenUsingFilterWithoutHandler() + { + $container = new ContainerBuilder(); + $loader = new MonologExtension(); + + $loader->load(array(array('handlers' => array('main' => array('type' => 'filter')))), $container); + } + /** * @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException */ diff --git a/composer.json b/composer.json index 23ce3fde..b647232a 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "symfony/dependency-injection": "~2.3", "symfony/config": "~2.3", "symfony/http-kernel": "~2.3", - "monolog/monolog": "~1.6" + "monolog/monolog": "~1.8" }, "require-dev": { "symfony/yaml": "~2.3",