Description
Symfony version(s) affected
6.2.10
Description
First of all, apologies if this isn't a bug but some misconfiguration. I tried my best to isolate it however.
Problem
While using multiple progress bars, as shown in the docs, one has to use sections. This produces an expected result. However, when using logging alongside some logs (ref (b)
in code) will be swallowed:
normal-log-and-bars.mov
19:05:08 WARNING [app] Hello 30
100/1000 [==>-------------------------] 10%
19:05:08 WARNING [app] Hello 50
19:05:08 WARNING [app] Hello 60
19:05:08 WARNING [app] Hello 70
100/1000 [==>-------------------------] 10%
200/1000 [=====>----------------------] 20%
19:05:08 WARNING [app] Hello 100
Fixing the logs breaks sections spacing
The solution I tracked down is to ensure logs (more specifically \Symfony\Bridge\Monolog\Handler\ConsoleHandler
) uses a section above progress bars sections. This entails something I'm not 100% comfortable with - injecting monolog.handler.console
and doing a manual ->setOutput()
on it (ref (a)
in code).
This produces almost correct result with no output being swallowed, but with extra spacing between log lines:
section-log-and-bars.mov
19:09:07 WARNING [app] Hello 270
19:09:07 WARNING [app] Hello 280
19:09:08 WARNING [app] Hello 290
200/1000 [=====>----------------------] 20%
500/1000 [==============>-------------] 50%
Issue with monolog-bridge
+ section?
I ran two more tests: normal logs (no ->setOutput($section)
override) and logs in section but without bars.
section-log-no-bars.mov
19:13:00 WARNING [app] Hello 10
19:13:01 WARNING [app] Hello 20
19:13:01 WARNING [app] Hello 30
normal-log-no-bars.mov
19:13:18 WARNING [app] Hello 10
19:13:18 WARNING [app] Hello 20
19:13:18 WARNING [app] Hello 30
As you can see the issue seems to be caused by a combination of console's ConsoleSectionOutput
& monolog's bridge ConsoleHandler
. I was trying to debug it further but I got stuck.
How to reproduce
<?php
namespace App\Command;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
#[AsCommand(name: 'app:test',)]
class TestCommand extends Command
{
public function __construct(
private LoggerInterface $log,
#[Autowire(service: 'monolog.handler.console')] private ConsoleHandler $consoleHandler
) {
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
//Without this the output of some logs will be swallowed once progress bars start rendering
$this->consoleHandler->setOutput($output->section()); //ref. (a)
//Example adapted from https://symfony.com/doc/current/components/console/helpers/progressbar.html#displaying-multiple-progress-bars
$section1 = $output->section();
$section2 = $output->section();
$progress1 = new ProgressBar($section1);
$progress2 = new ProgressBar($section2);
$progress1->start(1000);
$progress2->start(1000);
$i = 0;
while (++$i < 1000) {
$progress1->advance();
if ($i % 2 === 0) {
$progress2->advance(4);
}
if ($i % 10 === 0) {
$this->log->warning('Hello ' . $i); //ref. (b)
}
usleep(5000);
}
return Command::SUCCESS;
}
}
Possible Solution
No response
Additional Context
No response