From 97d222b3b5a98688a76bc202d157254ffee20933 Mon Sep 17 00:00:00 2001 From: Guicherd Date: Tue, 9 Jan 2024 15:23:06 +0100 Subject: [PATCH] feature #90 add global logger service that logs in job --- .../docs/getting-started.md | 14 +++++ .../src/Resources/services/global/logger.xml | 16 ++++++ src/batch/src/Logger/BatchLogger.php | 54 +++++++++++++++++++ src/batch/tests/Logger/BatchLoggerTest.php | 39 ++++++++++++++ tests/symfony/src/Job/Country/CountryJob.php | 12 ++++- tests/symfony/src/Kernel.php | 14 +++++ tests/symfony/tests/CountryJobSet.php | 1 + 7 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/batch-symfony-framework/src/Resources/services/global/logger.xml create mode 100644 src/batch/src/Logger/BatchLogger.php create mode 100644 src/batch/tests/Logger/BatchLoggerTest.php diff --git a/src/batch-symfony-framework/docs/getting-started.md b/src/batch-symfony-framework/docs/getting-started.md index 593fc723..630d0a8c 100644 --- a/src/batch-symfony-framework/docs/getting-started.md +++ b/src/batch-symfony-framework/docs/getting-started.md @@ -104,6 +104,20 @@ The job launcher that will be injected depends on the packages you have installe - if `yokai/batch-symfony-console` is installed, you will receive a `Yokai\Batch\Bridge\Symfony\Console\RunCommandJobLauncher` - otherwise you will receive a `Yokai\Batch\Launcher\SimpleJobLauncher` + +## Define a custom BatchLogger +In a symfony project, a monolog handler could be declared as of: +```yaml +# config/packages/monolog.yaml +monolog: + handlers: + batch: + type: service + service: + id: service.to.be.defined +``` + + ## On the same subject - [What is a job execution storage ?](https://github.com/yokai-php/batch/blob/0.x/docs/domain/job-execution-storage.md) diff --git a/src/batch-symfony-framework/src/Resources/services/global/logger.xml b/src/batch-symfony-framework/src/Resources/services/global/logger.xml new file mode 100644 index 00000000..c15d5235 --- /dev/null +++ b/src/batch-symfony-framework/src/Resources/services/global/logger.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/batch/src/Logger/BatchLogger.php b/src/batch/src/Logger/BatchLogger.php new file mode 100644 index 00000000..00415b5b --- /dev/null +++ b/src/batch/src/Logger/BatchLogger.php @@ -0,0 +1,54 @@ +batchLogger = $event->getExecution()->getLogger(); + } + + /** + * Forget the logger + */ + public function onPostExecute(PostExecuteEvent $event): void + { + $this->batchLogger = null; + } + + /** + * Log with the batchLogger defined in the PreExecuteEvent or with nullLogger if nothing remembered + * + * @param array $context + * @throws InvalidArgumentException + */ + public function log($level, Stringable|string $message, array $context = []): void + { + ($this->batchLogger ?? new NullLogger())->log($level, $message, $context); + } +} diff --git a/src/batch/tests/Logger/BatchLoggerTest.php b/src/batch/tests/Logger/BatchLoggerTest.php new file mode 100644 index 00000000..d4ba7330 --- /dev/null +++ b/src/batch/tests/Logger/BatchLoggerTest.php @@ -0,0 +1,39 @@ +addListener(PreExecuteEvent::class, [$logger, 'onPreExecute']); + $dispatcher->addListener(PostExecuteEvent::class, [$logger, 'onPostExecute']); + + $execution = JobExecution::createRoot('123', 'test.job_executor'); + + $logger->log('info', 'before'); + $preExecuteEvent = new PreExecuteEvent($execution); + $dispatcher->dispatch($preExecuteEvent); + + $logger->log('info', 'between'); + + $postExecuteEvent = new PostExecuteEvent($execution); + $dispatcher->dispatch($postExecuteEvent); + $logger->log('info', 'after'); + + self::assertStringNotContainsString('before', $execution->getLogs()->__toString()); + self::assertStringContainsString('between', $execution->getLogs()->__toString()); + self::assertStringNotContainsString('after', $execution->getLogs()->__toString()); + } +} diff --git a/tests/symfony/src/Job/Country/CountryJob.php b/tests/symfony/src/Job/Country/CountryJob.php index 71870b65..6be49d9a 100644 --- a/tests/symfony/src/Job/Country/CountryJob.php +++ b/tests/symfony/src/Job/Country/CountryJob.php @@ -4,6 +4,7 @@ namespace Yokai\Batch\Sources\Tests\Symfony\App\Job\Country; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\KernelInterface; use Yokai\Batch\Bridge\OpenSpout\Writer\FlatFileWriter; use Yokai\Batch\Bridge\Symfony\Framework\JobWithStaticNameInterface; @@ -56,14 +57,18 @@ final class CountryJob extends AbstractDecoratedJob implements private ItemWriterInterface $writer; private array $countries = []; private bool $flushed = false; + private LoggerInterface $batchLogger; public static function getJobName(): string { return 'country'; } - public function __construct(JobExecutionStorageInterface $executionStorage, KernelInterface $kernel) - { + public function __construct( + JobExecutionStorageInterface $executionStorage, + KernelInterface $kernel, + LoggerInterface $batchLogger + ) { $writePath = fn(string $format) => new StaticValueParameterAccessor( ARTIFACT_DIR . '/symfony/country/countries.' . $format ); @@ -91,10 +96,13 @@ public function __construct(JobExecutionStorageInterface $executionStorage, Kern $executionStorage ), ); + $this->batchLogger = $batchLogger; } public function process(mixed $item): array { + $this->batchLogger->log('info', 'log process'); + return ['iso2' => $item['code'], $item['_key'] => $item['value']]; } diff --git a/tests/symfony/src/Kernel.php b/tests/symfony/src/Kernel.php index f795324c..ad12c7f3 100644 --- a/tests/symfony/src/Kernel.php +++ b/tests/symfony/src/Kernel.php @@ -7,6 +7,7 @@ use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Bundle\MonologBundle\MonologBundle; use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Bundle\TwigBundle\TwigBundle; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -19,6 +20,7 @@ use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Yokai\Batch\Bridge\Symfony\Framework\YokaiBatchBundle; use Yokai\Batch\Job\JobInterface; +use Yokai\Batch\Logger\BatchLogger; final class Kernel extends BaseKernel implements CompilerPassInterface { @@ -31,6 +33,7 @@ public function registerBundles(): iterable yield new TwigBundle(); yield new SecurityBundle(); yield new YokaiBatchBundle(); + yield new MonologBundle(); } public function getProjectDir(): string @@ -108,6 +111,17 @@ protected function configureContainer(ContainerConfigurator $container): void ], ]); + $container->extension('monolog', [ + 'handlers' => [ + 'batch' => [ + 'type' => 'service', + 'service' => [ + 'id' => 'Yokai\Batch\Logger\BatchLogger' + ] + ] + ] + ]); + $container->services() ->set('logger', Logger::class) ->args([null, '%kernel.logs_dir%/test.log', null, new Reference(RequestStack::class)]) diff --git a/tests/symfony/tests/CountryJobSet.php b/tests/symfony/tests/CountryJobSet.php index 52eb49c7..3bfee185 100644 --- a/tests/symfony/tests/CountryJobSet.php +++ b/tests/symfony/tests/CountryJobSet.php @@ -74,6 +74,7 @@ static function (JobExecution $execution) { '{"iso2":"GB","iso3":"GBR","name":"United Kingdom","continent":"EU","currency":"GBP","phone":"44"}', $jsonl ); + Assert::assertStringContainsString('log process', $execution->getLogs()->__toString()); }, ]; }