Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[MonologBridge] Fix interactive_only not preventing propagation#64207

Open
philbates35 wants to merge 4 commits into
symfony:7.4from
philbates35:fix/monolog-bridge-interactive-only-propagation
Open

[MonologBridge] Fix interactive_only not preventing propagation#64207
philbates35 wants to merge 4 commits into
symfony:7.4from
philbates35:fix/monolog-bridge-interactive-only-propagation

Conversation

@philbates35
Copy link
Copy Markdown

@philbates35 philbates35 commented May 14, 2026

Q A
Branch? 7.4
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #...
License MIT

The interactive_only flag on ConsoleHandler is documented to prevent propagation to sibling handlers when the input is interactive, but it only overrides getBubble(). Monolog 3's AbstractProcessingHandler::handle() reads the $bubble property directly inside the propagation decision (return false === $this->bubble), so the dynamic value computed by the override never reaches Logger::addRecord's loop. As a result, when configured alongside a stream handler (e.g. JSON to stderr for log aggregation), interactive runs produced duplicate records.

Mirror the dynamic getBubble() value into $this->bubble for the duration of the handle() call so the property-based check used by Monolog honours interactive_only as documented. The previous value is restored via finally so subsequent records and external readers of getBubble() see the original configuration.

The existing testInteractiveOnly unit asserts the method-level contract but never wires the handler into a Logger with a sibling, which is why this slipped through. Add two regression tests at the propagation level: one that asserts a sibling TestHandler does NOT receive the record when input is interactive, and one that asserts it still DOES when input is non-interactive.

@philbates35 philbates35 force-pushed the fix/monolog-bridge-interactive-only-propagation branch 2 times, most recently from 4cc7646 to 004f21a Compare May 14, 2026 13:13
The interactive_only flag on ConsoleHandler is documented to prevent
propagation to sibling handlers when the input is interactive, but it
only overrides getBubble(). Monolog 3's AbstractProcessingHandler::handle()
reads the $bubble property directly inside the propagation decision
(`return false === $this->bubble`), so the dynamic value computed by
the override never reaches Logger::addRecord's loop. As a result, when
configured alongside a stream handler (e.g. JSON to stderr for log
aggregation), interactive runs produced duplicate records.

Mirror the dynamic getBubble() value into $this->bubble for the duration
of the handle() call so the property-based check used by Monolog honours
interactive_only as documented. The previous value is restored via
finally so subsequent records and external readers of getBubble() see
the original configuration.

The existing testInteractiveOnly unit asserts the method-level contract
but never wires the handler into a Logger with a sibling, which is why
this slipped through. Add two regression tests at the propagation level:
one that asserts a sibling TestHandler does NOT receive the record when
input is interactive, and one that asserts it still DOES when input is
non-interactive.
@philbates35 philbates35 force-pushed the fix/monolog-bridge-interactive-only-propagation branch from 004f21a to be7bd8b Compare May 14, 2026 13:28
self::assertTrue($handler->getBubble(), '->getBubble returns true when input is not interactive and interactiveOnly is true');
}

public function testInteractiveOnlyPreventsPropagationWhenInteractive()
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails without the fix, proving that propogation isn't stopped, which contradicts the docs and I believe the intended behaviour.

Runtime:       PHP 8.2.31
Configuration: /home/runner/work/symfony/symfony/phpunit.xml

............................F.................................... 65 / 88 ( 73%)
.......................                                           88 / 88 (100%)

Time: 00:00.928, Memory: 24.00 MB

There was 1 failure:

1) Symfony\Bridge\Monolog\Tests\Handler\ConsoleHandlerTest::testInteractiveOnlyPreventsPropagationWhenInteractive
sibling handler must not receive records when interactive_only is true and input is interactive
Failed asserting that true is false.

/home/runner/work/symfony/symfony/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php:280
/home/runner/work/symfony/symfony/.phpunit/phpunit-11.5-0/phpunit:104
/home/runner/work/symfony/symfony/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php:458
/home/runner/work/symfony/symfony/vendor/symfony/phpunit-bridge/bin/simple-phpunit:13

FAILURES!
Tests: 88, Assertions: 238, Failures: 1.

@philbates35 philbates35 marked this pull request as ready for review May 14, 2026 13:29
@carsonbot carsonbot added this to the 7.4 milestone May 14, 2026
return parent::handle($record);
} finally {
$this->bubble = $previousBubble;
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to update the fix to be an alternative "more correct" fix if there's a better way, but this solution gets the test passing.

Copy link
Copy Markdown
Member

@HypeMC HypeMC May 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like something that should be fixed on Monolog's side instead.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix submitted here: Seldaek/monolog#2031

Copy link
Copy Markdown
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for investigating this issue and providing a regression test.

As noted by @HypeMC, this should be fixed in Monolog's AbstractProcessingHandler

- return false === $this->bubble;
+ return !$this->getBubble();

Once monolog is updated, the ConsoleHandler::handle() method override can be removed.

$interactiveInput = $this->createStub(InputInterface::class);
$interactiveInput->method('isInteractive')->willReturn(true);

$consoleHandler = new ConsoleHandler(interactiveOnly: true);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use named arguments in test, because they are not supported by our BC policy.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 👍

Comment thread src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php Outdated
@GromNaN GromNaN changed the title [MonologBridge] Fix interactive_only not preventing propagation [MonologBridge] Fix interactive_only not preventing propagation May 14, 2026
@symfony symfony deleted a comment from carsonbot May 15, 2026
@symfony symfony deleted a comment from carsonbot May 15, 2026
@philbates35
Copy link
Copy Markdown
Author

Thanks for investigating this issue and providing a regression test.

As noted by @HypeMC, this should be fixed in Monolog's AbstractProcessingHandler

- return false === $this->bubble;
+ return !$this->getBubble();

Once monolog is updated, the ConsoleHandler::handle() method override can be removed.

Fix submitted here: Seldaek/monolog#2031

@philbates35
Copy link
Copy Markdown
Author

Thanks for the review @GromNaN @HypeMC, I've updated the PR with the requested changes. Do I understand correctly that you'd be happy to get this fix in now, and we later remove the override in a follow up PR if/when the fix becomes available on the monolog side?

Copy link
Copy Markdown
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. We will be able to merge this PR into 7.4 to fix the bug. Later, once Seldaek/monolog#2031 get released, we can increase the minimum required version of monolog/monolog and remove ConsoleHandler::handler in the next minor release of symfony/monolog-bridge.

There's just one small correction left to make to the comment, which no longer matches the code.

Comment on lines 100 to 101
// we have to update the logging level each time because the verbosity of the
// console output might have changed in the meantime (it is not immutable)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this outdated comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants