From 6bc429bcf97a5821191ba0d410acc8f6285a370c Mon Sep 17 00:00:00 2001 From: David Simon Date: Thu, 22 May 2014 17:18:04 -0400 Subject: [PATCH 1/5] Filter handler --- DependencyInjection/Configuration.php | 25 +++++++++++++++++-- DependencyInjection/MonologExtension.php | 25 +++++++++++++++++-- Resources/config/monolog.xml | 1 + .../MonologExtensionTest.php | 11 ++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index bad48b84..da0ea63a 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 + * - [level_list]: list of levels to accept + * - [min_level]: minimum level to accept (only use if level_list not specified) + * - [max_level]: maximum level to accept (only use if level_list not specified) + * - [bubble]: bool, defaults to true + * * - buffer: * - handler: the wrapped handler's name * - [buffer_size]: defaults to 0 (unlimited) @@ -245,6 +252,12 @@ public function getConfigTreeBuilder() ->canBeUnset() ->prototype('scalar')->end() ->end() + ->arrayNode('level_list') // 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 +488,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'] && !empty($v['min_level']) && !empty($v['level_list']); }) + ->thenInvalid('You can not use min_level together with level_list in a FilterHandler') + ->end() + ->validate() + ->ifTrue(function($v) { return 'filter' === $v['type'] && !empty($v['max_level']) && !empty($v['level_list']); }) + ->thenInvalid('You can not use max_level together with level_list 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..2c232b79 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,21 @@ 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']); + $nestedHandlerId = $this->getHandlerId($handler['handler']); + $this->nestedHandlers[] = $nestedHandlerId; + $minLevelOrList = isset($handler['level_list']) ? $handler['level_list'] : $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/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 */ From e941670c3901cd9f507f10e8a75b964531b26177 Mon Sep 17 00:00:00 2001 From: David Simon Date: Fri, 23 May 2014 10:33:44 -0400 Subject: [PATCH 2/5] Filter handler fixes: raised minimum monolog version requirement, XML schema for config, fixed level list interpretation --- DependencyInjection/Configuration.php | 4 ++-- DependencyInjection/MonologExtension.php | 10 +++++++++- Resources/config/schema/monolog-1.0.xsd | 3 +++ .../FixtureMonologExtensionTest.php | 11 ++++++++--- .../Fixtures/xml/multiple_handlers.xml | 5 +++++ .../Fixtures/yml/multiple_handlers.yml | 6 ++++++ composer.json | 2 +- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index da0ea63a..e4def095 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -256,8 +256,8 @@ public function getConfigTreeBuilder() ->canBeUnset() ->prototype('scalar')->end() ->end() - ->scalarNode('min_level')->defaultValue('DEBUG')->end() // filter - ->scalarNode('max_level')->defaultValue('EMERGENCY')->end() //filter + ->scalarNode('min_level')->defaultNull()->end() // filter + ->scalarNode('max_level')->defaultNull()->end() //filter ->scalarNode('buffer_size')->defaultValue(0)->end() // fingers_crossed and buffer ->scalarNode('handler')->end() // fingers_crossed and buffer ->scalarNode('url')->end() // cube diff --git a/DependencyInjection/MonologExtension.php b/DependencyInjection/MonologExtension.php index 2c232b79..3b401a3f 100644 --- a/DependencyInjection/MonologExtension.php +++ b/DependencyInjection/MonologExtension.php @@ -271,11 +271,19 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler break; case 'filter': + if (is_null($handler['min_level'])) { $handler['min_level'] = 'DEBUG'; } + if (is_null($handler['max_level'])) { $handler['max_level'] = 'EMERGENCY'; } + $handler['min_level'] = $this->levelToMonologConst($handler['min_level']); $handler['max_level'] = $this->levelToMonologConst($handler['max_level']); + $handler['level_list'] = array_map( + function ($level) { return $this->levelToMonologConst($level); }, + $handler['level_list'] + ); + $nestedHandlerId = $this->getHandlerId($handler['handler']); $this->nestedHandlers[] = $nestedHandlerId; - $minLevelOrList = isset($handler['level_list']) ? $handler['level_list'] : $handler['min_level']; + $minLevelOrList = !empty($handler['level_list']) ? $handler['level_list'] : $handler['min_level']; $definition->setArguments(array( new Reference($nestedHandlerId), diff --git a/Resources/config/schema/monolog-1.0.xsd b/Resources/config/schema/monolog-1.0.xsd index 73a47156..21b1c503 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..c5bc0992 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'), [\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..b1e1fd26 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..c93cd1aa 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 + level_list: [WARNING, ERROR] + handler: nested2 + nested2: + type: stream 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", From f296d4bcf336a116d737ce7ec44d3a2396bbf782 Mon Sep 17 00:00:00 2001 From: David Simon Date: Tue, 27 May 2014 10:59:31 -0400 Subject: [PATCH 3/5] Filter handler: various fixes in response to PR comments --- DependencyInjection/Configuration.php | 21 ++++++++++--------- DependencyInjection/MonologExtension.php | 12 ++++------- Resources/config/schema/monolog-1.0.xsd | 2 +- .../Fixtures/xml/multiple_handlers.xml | 4 ++-- .../Fixtures/yml/multiple_handlers.yml | 2 +- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index e4def095..56062882 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -77,9 +77,9 @@ * * - filter: * - handler: the wrapped handler's name - * - [level_list]: list of levels to accept - * - [min_level]: minimum level to accept (only use if level_list not specified) - * - [max_level]: maximum level to accept (only use if level_list not specified) + * - [accepted_levels]: list of levels to accept + * - [min_level]: minimum level to accept (only use if accepted_levels not specified) + * - [max_level]: maximum level to accept (only use if accepted_levels not specified) * - [bubble]: bool, defaults to true * * - buffer: @@ -226,6 +226,7 @@ public function getConfigTreeBuilder() ->fixXmlConfig('member') ->fixXmlConfig('excluded_404') ->fixXmlConfig('tag') + ->fixXmlConfig('accepted_level') ->canBeUnset() ->children() ->scalarNode('type') @@ -252,12 +253,12 @@ public function getConfigTreeBuilder() ->canBeUnset() ->prototype('scalar')->end() ->end() - ->arrayNode('level_list') // filter + ->arrayNode('accepted_levels') // filter ->canBeUnset() ->prototype('scalar')->end() ->end() - ->scalarNode('min_level')->defaultNull()->end() // filter - ->scalarNode('max_level')->defaultNull()->end() //filter + ->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 @@ -496,12 +497,12 @@ public function getConfigTreeBuilder() ->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'] && !empty($v['min_level']) && !empty($v['level_list']); }) - ->thenInvalid('You can not use min_level together with level_list in a FilterHandler') + ->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'] && !empty($v['max_level']) && !empty($v['level_list']); }) - ->thenInvalid('You can not use max_level together with level_list in a FilterHandler') + ->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'])); }) diff --git a/DependencyInjection/MonologExtension.php b/DependencyInjection/MonologExtension.php index 3b401a3f..00762eb5 100644 --- a/DependencyInjection/MonologExtension.php +++ b/DependencyInjection/MonologExtension.php @@ -271,19 +271,15 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler break; case 'filter': - if (is_null($handler['min_level'])) { $handler['min_level'] = 'DEBUG'; } - if (is_null($handler['max_level'])) { $handler['max_level'] = 'EMERGENCY'; } - $handler['min_level'] = $this->levelToMonologConst($handler['min_level']); $handler['max_level'] = $this->levelToMonologConst($handler['max_level']); - $handler['level_list'] = array_map( - function ($level) { return $this->levelToMonologConst($level); }, - $handler['level_list'] - ); + 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['level_list']) ? $handler['level_list'] : $handler['min_level']; + $minLevelOrList = !empty($handler['accepted_levels']) ? $handler['accepted_levels'] : $handler['min_level']; $definition->setArguments(array( new Reference($nestedHandlerId), diff --git a/Resources/config/schema/monolog-1.0.xsd b/Resources/config/schema/monolog-1.0.xsd index 21b1c503..c177919c 100644 --- a/Resources/config/schema/monolog-1.0.xsd +++ b/Resources/config/schema/monolog-1.0.xsd @@ -22,7 +22,7 @@ - + diff --git a/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml b/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml index b1e1fd26..8abe0875 100644 --- a/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml +++ b/Tests/DependencyInjection/Fixtures/xml/multiple_handlers.xml @@ -11,8 +11,8 @@ - WARNING - ERROR + WARNING + ERROR diff --git a/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml b/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml index c93cd1aa..32f69c70 100644 --- a/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml +++ b/Tests/DependencyInjection/Fixtures/yml/multiple_handlers.yml @@ -13,7 +13,7 @@ monolog: type: stream filtered: type: filter - level_list: [WARNING, ERROR] + accepted_levels: [WARNING, ERROR] handler: nested2 nested2: type: stream From 22f845552d7b6fcb1883f8f529b3d844e8a75333 Mon Sep 17 00:00:00 2001 From: David Simon Date: Tue, 27 May 2014 12:02:44 -0400 Subject: [PATCH 4/5] Filter handler: fixed php 5.3 issue in tests --- Tests/DependencyInjection/FixtureMonologExtensionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/DependencyInjection/FixtureMonologExtensionTest.php b/Tests/DependencyInjection/FixtureMonologExtensionTest.php index c5bc0992..9fc1ee5d 100644 --- a/Tests/DependencyInjection/FixtureMonologExtensionTest.php +++ b/Tests/DependencyInjection/FixtureMonologExtensionTest.php @@ -43,7 +43,7 @@ public function testLoadWithSeveralHandlers() $handler = $container->getDefinition('monolog.handler.filtered'); $this->assertDICDefinitionClass($handler, '%monolog.handler.filter.class%'); - $this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested2'), [\Monolog\Logger::WARNING, \Monolog\Logger::ERROR], \Monolog\Logger::EMERGENCY, true)); + $this->assertDICConstructorArguments($handler, array(new Reference('monolog.handler.nested2'), array(\Monolog\Logger::WARNING, \Monolog\Logger::ERROR), \Monolog\Logger::EMERGENCY, true)); } public function testLoadWithOverwriting() From a228219c7894b863d8af7d4c04f411d288de669f Mon Sep 17 00:00:00 2001 From: David Simon Date: Mon, 2 Jun 2014 10:47:42 -0400 Subject: [PATCH 5/5] Filter handler: documentation fix as requested by xabbuh --- DependencyInjection/Configuration.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 56062882..79b902e5 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -78,8 +78,8 @@ * - filter: * - handler: the wrapped handler's name * - [accepted_levels]: list of levels to accept - * - [min_level]: minimum level to accept (only use if accepted_levels not specified) - * - [max_level]: maximum level to accept (only use if accepted_levels not specified) + * - [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: