-
Notifications
You must be signed in to change notification settings - Fork 230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix registration of command subscribers #569
Fix registration of command subscribers #569
Conversation
ea17dc8
to
8386bcd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused by this PR, as I thought ODM 2.0 was not planning to utilize ext-mongodb
's APM functionality for its query logger.
IIRC, ODM 1.x populated Symfony's profiler with logged queries/commands from its own internal logging mechanism. I believe that's what the OP in #563 was referring to. Was that internal logging removed in ODM 2.0?
Logging via a CommandSubscriber would be entirely new functionality, and I expect an instance would need to pipe data to the Symfony service from one of its three listener methods (or collect all events until the end of a request and send it over in one batch).
One issue with doing so is that APM logging is global (beyond the scope of even a single Manager instance), so it will pick up commands from any library using ext-mongodb
. This could be actually prove problematic if profiler or log data ends up being written to MongoDB (see: PHPC-1410).
APM/CommandSubscriberRegistry.php
Outdated
|
||
public function __construct(iterable $commandSubscribers) | ||
{ | ||
$this->commandSubscribers = $commandSubscribers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense for this to validate that each element within $commandSubscribers
is actually a CommandSubscriber instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, I wonder if this is instead supposed to accept only Doctrine\ODM\MongoDB\APM\CommandLogger
instances, as that class is where register()
and unregister()
methods are defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll have to introduce a new interface, as the CommandLogger
class is final
but we also need a command logger that logs to any PSR-compatible logger. I'd introduce a CommandLogger
interface that extends CommandSubscriber
and exposes register
and unregister
methods, then limit possible arguments to this method to that interface.
APM/CommandSubscriberRegistry.php
Outdated
continue; | ||
} | ||
|
||
$subscriber->register(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since CommandSubscriber has no register()
and unregister()
methods, I don't believe we'd ever reach this point. Subscribers are registered with the extension globally via these functions.
The APM tutorial has some examples that tie this all together.
This might be related to my last comment. When I initially reviewed this I was not aware of the CommandLogger class in ODM. Was the CommandSubscriber type hint purposeful? I understand if you don't want to add an interface with |
Looking at the comments, it definitely makes more sense to introduce our interface for loggers, which only declares the However, the fact that command subscriber don't only react to commands sent through the current client but rather collect all commands executed on the server makes me doubt whether we want to add the logging functionality in this form. I believe it is definitely unexpected and potentially dangerous to log all commands executed on the server in the application. Since the events also don't expose any information on who triggered the command, we most likely won't be able to filter out any unwanted commands either. |
Any updates? Thanks!! |
Not yet. |
8386bcd
to
30833ab
Compare
Updated the code with the new |
30833ab
to
a024f9d
Compare
|
||
public function unregister() : void | ||
{ | ||
array_map(static function (CommandLoggerInterface $commandLogger) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Foreach is bad? :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One benefit is that this applies type checking to each element, which would otherwise require an instanceof
check within foreach
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was one of the reasons why I added it. Of course, a type check is already done in the constructor when storing the items, but then I've started using array_map
in place of foreach
to make it more explicit. I can change it to a loop if you prefer that
|
||
public function unregister() : void | ||
{ | ||
array_map(static function (CommandLoggerInterface $commandLogger) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One benefit is that this applies type checking to each element, which would otherwise require an instanceof
check within foreach
.
$commandLoggerRegistry->unregister(); | ||
} | ||
|
||
public function shutdown() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have a return type hint, or is that omitted because we're overriding a method from Symfony's base class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've omitted it because Symfony doesn't have one and I haven't had time to test this against Symfony 5 so far. All Doctrine Bundles will get the Symfony 4.4/5.0 treatment after the Symfony Code Freeze next week (DoctrineBundle has been the guinea pig for this). This will add some return type annotations where applicable. I'll have to see how to treat this since I don't want to hold 4.0 back until November, but I also don't want to release a new major version shortly after releasing 4.0 already.
composer.json
Outdated
@@ -13,7 +13,7 @@ | |||
"require": { | |||
"php": "^7.2", | |||
"doctrine/annotations": "^1.2", | |||
"doctrine/mongodb-odm": "^2.0.0-beta1", | |||
"doctrine/mongodb-odm": "dev-master", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be changed to 2.0.0-RC2 (following its release, of course)?
EDIT: Just saw the "REMOVE:" commit. Makes sense.
@@ -41,7 +41,7 @@ protected function setUp() | |||
|
|||
public function testFixturesLoader() : void | |||
{ | |||
$kernel = new IntegrationTestKernel('dev', true); | |||
$kernel = new IntegrationTestKernel('dev', false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this pertinent to the PR, or just some extra cleanup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was some necessary cleanup as tests started failing.
a024f9d
to
17657d2
Compare
Fixes #563. Command subscribers were not properly registered - just adding a method call to the service definition is not enough.
To work around this, we add a command subscriber registry that is registered and unregistered when the bundle is booted and shut down. The registry proxies all calls to
register
andunregister
to all registered subscribers. Since we don't have an interface for registrable command subscribers, I simply addedmethod_exists
checks to avoid fatal errors. We can still add an interface for such subscribers to the next release candidate for mongodb-odm and change the code to throw exceptions instead of silently skipping incompatible subscribers. Opinions @jmikola @malarzm?