diff --git a/README.md b/README.md index 5af3e00..0799c12 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,15 @@ handler. enable_annotations: false # Configuration option used by both handlers. - process_psr_3_messages: true + process_psr_3_messages: + + # Examples: + - false + - { enabled: false } + - { date_format: Y-m-d, remove_used_context_fields: true } + enabled: true + date_format: ~ + remove_used_context_fields: ~ ``` 1. Enable the bundle in `config/bundles.php` by adding it to the array: diff --git a/src/DependencyInjection/BizkitLoggableCommandExtension.php b/src/DependencyInjection/BizkitLoggableCommandExtension.php index 7884b39..65908b9 100644 --- a/src/DependencyInjection/BizkitLoggableCommandExtension.php +++ b/src/DependencyInjection/BizkitLoggableCommandExtension.php @@ -29,7 +29,7 @@ final class BizkitLoggableCommandExtension extends ConfigurableExtension implements PrependExtensionInterface, CompilerPassInterface { /** - * @var bool + * @var array{enabled: bool, date_format?: ?string, remove_used_context_fields?: bool} */ private $processPsr3Messages; @@ -149,13 +149,36 @@ private function setLoggableOutputConfigurator(ContainerBuilder $container): voi */ private function registerPsrLogMessageProcessor(ContainerBuilder $container): void { - if (!$this->processPsr3Messages) { + if (!$this->processPsr3Messages['enabled']) { return; } + static $hasConstructorArguments; + + if (!isset($hasConstructorArguments)) { + $r = (new \ReflectionClass(PsrLogMessageProcessor::class))->getConstructor(); + $hasConstructorArguments = null !== $r && $r->getNumberOfParameters() > 0; + unset($r); + } + $monologProcessorId = 'monolog.processor.psr_log_message'; + $monologProcessorArguments = []; $processorId = 'bizkit_loggable_command.processor.psr_log_message'; + $processorOptions = $this->processPsr3Messages; + unset($processorOptions['enabled']); + + if ($processorOptions) { + if (!$hasConstructorArguments) { + throw new RuntimeException('Monolog 1.26 or higher is required for the "date_format" and "remove_used_context_fields" options to be used.'); + } + $monologProcessorArguments = [ + $processorOptions['date_format'] ?? null, + $processorOptions['remove_used_context_fields'] ?? false, + ]; + $monologProcessorId .= '.'.ContainerBuilder::hash($monologProcessorArguments); + } + if ($container->hasDefinition($monologProcessorId)) { $container->setAlias($processorId, $monologProcessorId) ->setPublic(false) @@ -163,6 +186,7 @@ private function registerPsrLogMessageProcessor(ContainerBuilder $container): vo } else { $processor = new Definition(PsrLogMessageProcessor::class); $processor->setPublic(false); + $processor->setArguments($monologProcessorArguments); $container->setDefinition($processorId, $processor); } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index d455e99..91be4d2 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -95,11 +95,28 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() - ->append( - $monologHandlersConfig->find('process_psr_3_messages') - ->info('Configuration option used by both handlers.') - ->defaultTrue() - ) + ->arrayNode('process_psr_3_messages') + ->info('Configuration option used by both handlers.') + ->example([ + false, + ['enabled' => false], + ['date_format' => 'Y-m-d', 'remove_used_context_fields' => true], + ]) + ->addDefaultsIfNotSet() + ->beforeNormalization() + ->ifTrue(static function ($v): bool { + return !\is_array($v); + }) + ->then(static function ($v): array { + return ['enabled' => $v]; + }) + ->end() + ->children() + ->booleanNode('enabled')->defaultTrue()->end() + ->scalarNode('date_format')->end() + ->booleanNode('remove_used_context_fields')->end() + ->end() + ->end() ->end() ->validate() diff --git a/tests/DependencyInjection/BizkitLoggableCommandExtensionTest.php b/tests/DependencyInjection/BizkitLoggableCommandExtensionTest.php index 2cc468e..8d6ef27 100644 --- a/tests/DependencyInjection/BizkitLoggableCommandExtensionTest.php +++ b/tests/DependencyInjection/BizkitLoggableCommandExtensionTest.php @@ -23,6 +23,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; /** @@ -324,4 +325,92 @@ public function testPsrLogMessageProcessorIsAliasedWhenTrueAndMonologServiceExis $this->assertFalse($container->hasDefinition('bizkit_loggable_command.processor.psr_log_message')); $this->assertTrue($container->hasAlias('bizkit_loggable_command.processor.psr_log_message')); } + + public function testExceptionIsThrownWhenPsrLogMessageProcessorDoesNotHaveConstructorArguments(): void + { + if ($this->psrLogMessageProcessorHasConstructorArguments()) { + $this->markTestSkipped('Monolog < 1.26 is needed.'); + } + + $container = new ContainerBuilder(); + $container->registerExtension($loggableCommandExtension = new BizkitLoggableCommandExtension()); + + $loggableCommandExtension->load([[ + 'process_psr_3_messages' => [ + 'date_format' => 'Y-m-d', + ], + ]], $container); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + 'Monolog 1.26 or higher is required for the "date_format" and "remove_used_context_fields" options to be used.' + ); + + $loggableCommandExtension->process($container); + } + + public function testPsrLogMessageProcessorIsRegisteredWhenTrueWithArgumentsAndMonologServiceDoesNotExist(): void + { + if (!$this->psrLogMessageProcessorHasConstructorArguments()) { + $this->markTestSkipped('Monolog >= 1.26 is needed.'); + } + + $container = new ContainerBuilder(); + $container->registerExtension($loggableCommandExtension = new BizkitLoggableCommandExtension()); + + $container->register( + 'monolog.processor.psr_log_message.'.ContainerBuilder::hash([null, true]), + PsrLogMessageProcessor::class + ); + + $loggableCommandExtension->load([[ + 'process_psr_3_messages' => [ + 'enabled' => true, + 'date_format' => 'Y-m-d', + ], + ]], $container); + $loggableCommandExtension->process($container); + + $this->assertTrue($container->hasDefinition('bizkit_loggable_command.processor.psr_log_message')); + $this->assertFalse($container->hasAlias('bizkit_loggable_command.processor.psr_log_message')); + } + + public function testPsrLogMessageProcessorIsAliasedWhenTrueWithArgumentsAndMonologServiceExists(): void + { + if (!$this->psrLogMessageProcessorHasConstructorArguments()) { + $this->markTestSkipped('Monolog >= 1.26 is needed.'); + } + + $container = new ContainerBuilder(); + $container->registerExtension($loggableCommandExtension = new BizkitLoggableCommandExtension()); + + $container->register( + 'monolog.processor.psr_log_message.'.ContainerBuilder::hash([null, true]), + PsrLogMessageProcessor::class + ); + + $loggableCommandExtension->load([[ + 'process_psr_3_messages' => [ + 'enabled' => true, + 'remove_used_context_fields' => true, + ], + ]], $container); + $loggableCommandExtension->process($container); + + $this->assertFalse($container->hasDefinition('bizkit_loggable_command.processor.psr_log_message')); + $this->assertTrue($container->hasAlias('bizkit_loggable_command.processor.psr_log_message')); + } + + private function psrLogMessageProcessorHasConstructorArguments(): bool + { + static $hasConstructorArguments; + + if (!isset($hasConstructorArguments)) { + $r = (new \ReflectionClass(PsrLogMessageProcessor::class))->getConstructor(); + $hasConstructorArguments = null !== $r && $r->getNumberOfParameters() > 0; + unset($r); + } + + return $hasConstructorArguments; + } } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index 5174d9c..369a588 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -43,7 +43,54 @@ public function testDefaultConfig(): void 'extra_options' => [], 'enable_annotations' => false, ], - 'process_psr_3_messages' => true, + 'process_psr_3_messages' => [ + 'enabled' => true, + ], ], $config); } + + public function testConfigWhenProcessPsr3MessageIsTrue(): void + { + $config = (new Processor())->processConfiguration(new Configuration(), [ + 'bizkit_loggable_command' => [ + 'process_psr_3_messages' => true, + ], + ]); + + $this->assertArrayHasKey('process_psr_3_messages', $config); + $this->assertSame([ + 'enabled' => true, + ], $config['process_psr_3_messages']); + } + + public function testConfigWhenProcessPsr3MessageIsFalse(): void + { + $config = (new Processor())->processConfiguration(new Configuration(), [ + 'bizkit_loggable_command' => [ + 'process_psr_3_messages' => false, + ], + ]); + + $this->assertArrayHasKey('process_psr_3_messages', $config); + $this->assertSame([ + 'enabled' => false, + ], $config['process_psr_3_messages']); + } + + public function testConfigWhenProcessPsr3MessageIsArray(): void + { + $config = (new Processor())->processConfiguration(new Configuration(), [ + 'bizkit_loggable_command' => [ + 'process_psr_3_messages' => [ + 'date_format' => 'Y-m-d', + ], + ], + ]); + + $this->assertArrayHasKey('process_psr_3_messages', $config); + $this->assertSame([ + 'date_format' => 'Y-m-d', + 'enabled' => true, + ], $config['process_psr_3_messages']); + } }