From b3060931f8796d404ad460f4b1bccb8e72773e69 Mon Sep 17 00:00:00 2001 From: Maxim Smakouz Date: Wed, 13 Sep 2023 15:53:03 +0300 Subject: [PATCH 1/5] Add ability to configure monolog format --- .../src/Bootloader/MonologBootloader.php | 7 +- .../Monolog/src/Config/MonologConfig.php | 11 ++- .../tests/Config/MonologConfigTest.php | 77 +++++++++++++++++++ 3 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 src/Bridge/Monolog/tests/Config/MonologConfigTest.php diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index 76eb30050..b5ad4a131 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -9,6 +9,7 @@ use Monolog\Handler\RotatingFileHandler; use Monolog\Logger; use Monolog\ResettableInterface; +use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Spiral\Boot\Bootloader\Bootloader; use Spiral\Boot\EnvironmentInterface; @@ -32,7 +33,8 @@ final class MonologBootloader extends Bootloader implements Container\SingletonI ]; public function __construct( - private readonly ConfiguratorInterface $config + private readonly ConfiguratorInterface $config, + private readonly ContainerInterface $container ) { } @@ -64,6 +66,7 @@ public function init(Container $container, FinalizerInterface $finalizer, Enviro 'default' => $env->get('MONOLOG_DEFAULT_CHANNEL', MonologConfig::DEFAULT_CHANNEL), 'globalLevel' => Logger::DEBUG, 'handlers' => [], + 'format' => $env->get('MONOLOG_FORMAT', MonologConfig::DEFAULT_FORMAT), ]); $container->bindInjector(Logger::class, LogFactory::class); @@ -101,7 +104,7 @@ public function logRotate( ); return $handler->setFormatter( - new LineFormatter("[%datetime%] %level_name%: %message% %context%\n") + new LineFormatter($this->container->get(MonologConfig::class)->getFormat()) ); } } diff --git a/src/Bridge/Monolog/src/Config/MonologConfig.php b/src/Bridge/Monolog/src/Config/MonologConfig.php index ec87eb792..6ec495651 100644 --- a/src/Bridge/Monolog/src/Config/MonologConfig.php +++ b/src/Bridge/Monolog/src/Config/MonologConfig.php @@ -13,11 +13,13 @@ final class MonologConfig extends InjectableConfig { public const CONFIG = 'monolog'; public const DEFAULT_CHANNEL = 'default'; + public const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; protected array $config = [ - 'default' => self::DEFAULT_CHANNEL, + 'default' => self::DEFAULT_CHANNEL, 'globalLevel' => Logger::DEBUG, - 'handlers' => [], + 'handlers' => [], + 'format' => self::DEFAULT_FORMAT, ]; public function getDefault(): string @@ -75,6 +77,11 @@ public function getProcessors(string $channel): \Generator } } + public function getFormat(): string + { + return $this->config['format'] ?? self::DEFAULT_FORMAT; + } + private function wire(Autowire|string|array $definition): ?Autowire { if ($definition instanceof Autowire) { diff --git a/src/Bridge/Monolog/tests/Config/MonologConfigTest.php b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php new file mode 100644 index 000000000..a3e872e49 --- /dev/null +++ b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php @@ -0,0 +1,77 @@ +assertSame(MonologConfig::DEFAULT_CHANNEL, $config->getDefault()); + + $config = new MonologConfig(['default' => 'foo']); + $this->assertSame('foo', $config->getDefault()); + } + + public function testGetEventLevel(): void + { + $config = new MonologConfig(); + $this->assertSame(Logger::DEBUG, $config->getEventLevel()); + + $config = new MonologConfig(['globalLevel' => 'foo']); + $this->assertSame('foo', $config->getEventLevel()); + } + + public function testGetHandlers(): void + { + $config = new MonologConfig(); + $this->assertEmpty(\iterator_to_array($config->getHandlers('foo'))); + + $config = new MonologConfig([ + 'handlers' => [ + 'foo' => [ + $this->createMock(HandlerInterface::class) + ] + ] + ]); + $this->assertInstanceOf( + HandlerInterface::class, + \iterator_to_array($config->getHandlers('foo')[0]) + ); + } + + public function testGetProcessors(): void + { + $config = new MonologConfig(); + $this->assertEmpty(\iterator_to_array($config->getProcessors('foo'))); + + $config = new MonologConfig([ + 'processors' => [ + 'foo' => [ + $this->createMock(ProcessorInterface::class) + ] + ] + ]); + $this->assertInstanceOf( + ProcessorInterface::class, + \iterator_to_array($config->getProcessors('foo')[0]) + ); + } + + public function testGetFormat(): void + { + $config = new MonologConfig(); + $this->assertSame(MonologConfig::DEFAULT_FORMAT, $config->getFormat()); + + $config = new MonologConfig(['format' => 'foo']); + $this->assertSame('foo', $config->getFormat()); + } +} From f1f06301ca77dde1e1f3feade78385db9ba4a074 Mon Sep 17 00:00:00 2001 From: Maxim Smakouz Date: Thu, 14 Sep 2023 08:05:14 +0300 Subject: [PATCH 2/5] Add test --- .../tests/Config/MonologConfigTest.php | 8 ++-- .../Monolog/tests/RotateHandlerTest.php | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/Bridge/Monolog/tests/Config/MonologConfigTest.php b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php index a3e872e49..2929326f2 100644 --- a/src/Bridge/Monolog/tests/Config/MonologConfigTest.php +++ b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php @@ -26,8 +26,8 @@ public function testGetEventLevel(): void $config = new MonologConfig(); $this->assertSame(Logger::DEBUG, $config->getEventLevel()); - $config = new MonologConfig(['globalLevel' => 'foo']); - $this->assertSame('foo', $config->getEventLevel()); + $config = new MonologConfig(['globalLevel' => Logger::INFO]); + $this->assertSame(Logger::INFO, $config->getEventLevel()); } public function testGetHandlers(): void @@ -44,7 +44,7 @@ public function testGetHandlers(): void ]); $this->assertInstanceOf( HandlerInterface::class, - \iterator_to_array($config->getHandlers('foo')[0]) + \iterator_to_array($config->getHandlers('foo'))[0] ); } @@ -62,7 +62,7 @@ public function testGetProcessors(): void ]); $this->assertInstanceOf( ProcessorInterface::class, - \iterator_to_array($config->getProcessors('foo')[0]) + \iterator_to_array($config->getProcessors('foo'))[0] ); } diff --git a/src/Bridge/Monolog/tests/RotateHandlerTest.php b/src/Bridge/Monolog/tests/RotateHandlerTest.php index 93414111c..e4742833a 100644 --- a/src/Bridge/Monolog/tests/RotateHandlerTest.php +++ b/src/Bridge/Monolog/tests/RotateHandlerTest.php @@ -6,6 +6,10 @@ use Monolog\Handler\RotatingFileHandler; use Monolog\Logger; +use Spiral\Boot\BootloadManager\DefaultInvokerStrategy; +use Spiral\Boot\BootloadManager\Initializer; +use Spiral\Boot\BootloadManager\InitializerInterface; +use Spiral\Boot\BootloadManager\InvokerStrategyInterface; use Spiral\Boot\BootloadManager\StrategyBasedBootloadManager; use Spiral\Boot\FinalizerInterface; use Spiral\Config\ConfigManager; @@ -13,9 +17,18 @@ use Spiral\Config\LoaderInterface; use Spiral\Core\Container; use Spiral\Monolog\Bootloader\MonologBootloader; +use Spiral\Monolog\Config\MonologConfig; class RotateHandlerTest extends BaseTest { + protected function setUp(): void + { + parent::setUp(); + + $this->container->bind(InvokerStrategyInterface::class, DefaultInvokerStrategy::class); + $this->container->bind(InitializerInterface::class, Initializer::class); + } + public function testRotateHandler(): void { $this->container->bind(FinalizerInterface::class, $finalizer = \Mockery::mock(FinalizerInterface::class)); @@ -46,4 +59,29 @@ public function load(string $section): array $this->assertSame(Logger::DEBUG, $handler->getLevel()); } + + public function testChangeFormat(): void + { + $this->container->bind(FinalizerInterface::class, $finalizer = \Mockery::mock(FinalizerInterface::class)); + $finalizer->shouldReceive('addFinalizer')->once(); + + $this->container->bind(MonologConfig::class, new MonologConfig([ + 'format' => 'foo' + ])); + $this->container->bind(ConfiguratorInterface::class, $this->createMock(ConfiguratorInterface::class)); + $this->container->get(StrategyBasedBootloadManager::class)->bootload([MonologBootloader::class]); + + $autowire = new Container\Autowire('log.rotate', [ + 'filename' => 'monolog.log' + ]); + + /** @var RotatingFileHandler $handler */ + $handler = $autowire->resolve($this->container); + $this->assertInstanceOf(RotatingFileHandler::class, $handler); + + $this->assertSame(Logger::DEBUG, $handler->getLevel()); + + $formatter = $handler->getFormatter(); + $this->assertSame('foo', (new \ReflectionProperty($formatter, 'format'))->getValue($formatter)); + } } From 744ccac3bf5d5fec8f31d91ff7beccb3fd28b8f4 Mon Sep 17 00:00:00 2001 From: Maxim Smakouz Date: Thu, 14 Sep 2023 08:22:45 +0300 Subject: [PATCH 3/5] Remove format from config file --- .../Monolog/src/Bootloader/MonologBootloader.php | 12 ++++++------ src/Bridge/Monolog/src/Config/MonologConfig.php | 11 ++--------- .../Monolog/tests/Config/MonologConfigTest.php | 9 --------- src/Bridge/Monolog/tests/RotateHandlerTest.php | 7 +++---- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index b5ad4a131..1967d92d1 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -9,7 +9,6 @@ use Monolog\Handler\RotatingFileHandler; use Monolog\Logger; use Monolog\ResettableInterface; -use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Spiral\Boot\Bootloader\Bootloader; use Spiral\Boot\EnvironmentInterface; @@ -23,6 +22,8 @@ final class MonologBootloader extends Bootloader implements Container\SingletonInterface { + private const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; + protected const SINGLETONS = [ LogsInterface::class => LogFactory::class, LoggerInterface::class => Logger::class, @@ -34,11 +35,11 @@ final class MonologBootloader extends Bootloader implements Container\SingletonI public function __construct( private readonly ConfiguratorInterface $config, - private readonly ContainerInterface $container + private readonly EnvironmentInterface $env, ) { } - public function init(Container $container, FinalizerInterface $finalizer, EnvironmentInterface $env): void + public function init(Container $container, FinalizerInterface $finalizer): void { $finalizer->addFinalizer(static function (bool $terminate) use ($container): void { if ($terminate) { @@ -63,10 +64,9 @@ public function init(Container $container, FinalizerInterface $finalizer, Enviro }); $this->config->setDefaults(MonologConfig::CONFIG, [ - 'default' => $env->get('MONOLOG_DEFAULT_CHANNEL', MonologConfig::DEFAULT_CHANNEL), + 'default' => $this->env->get('MONOLOG_DEFAULT_CHANNEL', MonologConfig::DEFAULT_CHANNEL), 'globalLevel' => Logger::DEBUG, 'handlers' => [], - 'format' => $env->get('MONOLOG_FORMAT', MonologConfig::DEFAULT_FORMAT), ]); $container->bindInjector(Logger::class, LogFactory::class); @@ -104,7 +104,7 @@ public function logRotate( ); return $handler->setFormatter( - new LineFormatter($this->container->get(MonologConfig::class)->getFormat()) + new LineFormatter($this->env->get('MONOLOG_FORMAT', self::DEFAULT_FORMAT)) ); } } diff --git a/src/Bridge/Monolog/src/Config/MonologConfig.php b/src/Bridge/Monolog/src/Config/MonologConfig.php index 6ec495651..ec87eb792 100644 --- a/src/Bridge/Monolog/src/Config/MonologConfig.php +++ b/src/Bridge/Monolog/src/Config/MonologConfig.php @@ -13,13 +13,11 @@ final class MonologConfig extends InjectableConfig { public const CONFIG = 'monolog'; public const DEFAULT_CHANNEL = 'default'; - public const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; protected array $config = [ - 'default' => self::DEFAULT_CHANNEL, + 'default' => self::DEFAULT_CHANNEL, 'globalLevel' => Logger::DEBUG, - 'handlers' => [], - 'format' => self::DEFAULT_FORMAT, + 'handlers' => [], ]; public function getDefault(): string @@ -77,11 +75,6 @@ public function getProcessors(string $channel): \Generator } } - public function getFormat(): string - { - return $this->config['format'] ?? self::DEFAULT_FORMAT; - } - private function wire(Autowire|string|array $definition): ?Autowire { if ($definition instanceof Autowire) { diff --git a/src/Bridge/Monolog/tests/Config/MonologConfigTest.php b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php index 2929326f2..a86f5eeb2 100644 --- a/src/Bridge/Monolog/tests/Config/MonologConfigTest.php +++ b/src/Bridge/Monolog/tests/Config/MonologConfigTest.php @@ -65,13 +65,4 @@ public function testGetProcessors(): void \iterator_to_array($config->getProcessors('foo'))[0] ); } - - public function testGetFormat(): void - { - $config = new MonologConfig(); - $this->assertSame(MonologConfig::DEFAULT_FORMAT, $config->getFormat()); - - $config = new MonologConfig(['format' => 'foo']); - $this->assertSame('foo', $config->getFormat()); - } } diff --git a/src/Bridge/Monolog/tests/RotateHandlerTest.php b/src/Bridge/Monolog/tests/RotateHandlerTest.php index e4742833a..2a5e1d799 100644 --- a/src/Bridge/Monolog/tests/RotateHandlerTest.php +++ b/src/Bridge/Monolog/tests/RotateHandlerTest.php @@ -11,13 +11,14 @@ use Spiral\Boot\BootloadManager\InitializerInterface; use Spiral\Boot\BootloadManager\InvokerStrategyInterface; use Spiral\Boot\BootloadManager\StrategyBasedBootloadManager; +use Spiral\Boot\Environment; +use Spiral\Boot\EnvironmentInterface; use Spiral\Boot\FinalizerInterface; use Spiral\Config\ConfigManager; use Spiral\Config\ConfiguratorInterface; use Spiral\Config\LoaderInterface; use Spiral\Core\Container; use Spiral\Monolog\Bootloader\MonologBootloader; -use Spiral\Monolog\Config\MonologConfig; class RotateHandlerTest extends BaseTest { @@ -65,9 +66,7 @@ public function testChangeFormat(): void $this->container->bind(FinalizerInterface::class, $finalizer = \Mockery::mock(FinalizerInterface::class)); $finalizer->shouldReceive('addFinalizer')->once(); - $this->container->bind(MonologConfig::class, new MonologConfig([ - 'format' => 'foo' - ])); + $this->container->bind(EnvironmentInterface::class, new Environment(['MONOLOG_FORMAT' => 'foo'])); $this->container->bind(ConfiguratorInterface::class, $this->createMock(ConfiguratorInterface::class)); $this->container->get(StrategyBasedBootloadManager::class)->bootload([MonologBootloader::class]); From 40480cc4b278c81d41ac90d4f532fffb255386ad Mon Sep 17 00:00:00 2001 From: Maxim Smakouz Date: Thu, 14 Sep 2023 08:27:21 +0300 Subject: [PATCH 4/5] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c49001678..fe1731f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ - **Other Features** - [spiral/queue] Added `Spiral\Queue\Interceptor\Consume\RetryPolicyInterceptor` to enable automatic job retries with a configurable retry policy. + - [spiral/monolog-bridge] Added the ability to configure the **Monolog** messages format via environment variable + `MONOLOG_FORMAT`. ## 3.8.4 - 2023-09-08 From 0651d8b07933e292663efa3386b46ab1ce0dba22 Mon Sep 17 00:00:00 2001 From: Maxim Smakouz Date: Thu, 14 Sep 2023 08:33:36 +0300 Subject: [PATCH 5/5] Fix CS --- src/Bridge/Monolog/src/Bootloader/MonologBootloader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php index 1967d92d1..6796bc322 100644 --- a/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php +++ b/src/Bridge/Monolog/src/Bootloader/MonologBootloader.php @@ -22,8 +22,6 @@ final class MonologBootloader extends Bootloader implements Container\SingletonInterface { - private const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; - protected const SINGLETONS = [ LogsInterface::class => LogFactory::class, LoggerInterface::class => Logger::class, @@ -33,6 +31,8 @@ final class MonologBootloader extends Bootloader implements Container\SingletonI 'log.rotate' => [self::class, 'logRotate'], ]; + private const DEFAULT_FORMAT = "[%datetime%] %level_name%: %message% %context%\n"; + public function __construct( private readonly ConfiguratorInterface $config, private readonly EnvironmentInterface $env,