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..14743972
--- /dev/null
+++ b/src/batch/tests/Logger/BatchLoggerTest.php
@@ -0,0 +1,40 @@
+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..d7ef2459 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;
@@ -31,6 +32,7 @@ public function registerBundles(): iterable
yield new TwigBundle();
yield new SecurityBundle();
yield new YokaiBatchBundle();
+ yield new MonologBundle();
}
public function getProjectDir(): string
@@ -108,6 +110,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());
},
];
}