Skip to content

Commit b455ab7

Browse files
GromNaNjmikola
andauthored
PHPLIB-1309 Add addSubscriber/removeSubscriber to Client class to ease configuration (#1195)
Co-authored-by: Jeremy Mikola <[email protected]>
1 parent 9f8eac1 commit b455ab7

9 files changed

+245
-1
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# CHANGELOG
2+
3+
4+
## 1.18.0 (unreleased)
5+
6+
* Add `addSubscriber` and `removeSubscriber` methods to the `Client` class to ease dependency injection configuration
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
arg_name: param
2+
name: $subscriber
3+
type: :php:`MongoDB\\Driver\\Monitoring\\Subscriber <class.mongodb-driver-monitoring-subscriber>`
4+
description: |
5+
A monitoring event subscriber to register with this Client.
6+
interface: phpmethod
7+
operation: ~
8+
optional: false
9+
...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
arg_name: param
2+
name: $subscriber
3+
type: :php:`MongoDB\\Driver\\Monitoring\\Subscriber <class.mongodb-driver-monitoring-subscriber>`
4+
description: |
5+
A monitoring event subscriber to unregister with this Client.
6+
interface: phpmethod
7+
operation: ~
8+
optional: false
9+
...

docs/reference/class/MongoDBClient.txt

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Methods
3030

3131
/reference/method/MongoDBClient__construct
3232
/reference/method/MongoDBClient__get
33+
/reference/method/MongoDBClient-addSubscriber
3334
/reference/method/MongoDBClient-createClientEncryption
3435
/reference/method/MongoDBClient-dropDatabase
3536
/reference/method/MongoDBClient-getManager
@@ -39,6 +40,7 @@ Methods
3940
/reference/method/MongoDBClient-getWriteConcern
4041
/reference/method/MongoDBClient-listDatabaseNames
4142
/reference/method/MongoDBClient-listDatabases
43+
/reference/method/MongoDBClient-removeSubscriber
4244
/reference/method/MongoDBClient-selectCollection
4345
/reference/method/MongoDBClient-selectDatabase
4446
/reference/method/MongoDBClient-startSession
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
================================
2+
MongoDB\\Client::addSubscriber()
3+
================================
4+
5+
.. versionadded:: 1.18
6+
7+
.. default-domain:: mongodb
8+
9+
.. contents:: On this page
10+
:local:
11+
:backlinks: none
12+
:depth: 1
13+
:class: singlecol
14+
15+
Definition
16+
----------
17+
18+
.. phpmethod:: MongoDB\\Client::addSubscriber()
19+
20+
Registers a monitoring event subscriber with this Client. The subscriber
21+
will be notified of all events for this Client.
22+
23+
.. code-block:: php
24+
25+
function addSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void
26+
27+
This method has the following parameters:
28+
29+
.. include:: /includes/apiargs/MongoDBClient-method-addSubscriber-param.rst
30+
31+
.. note::
32+
33+
If ``$subscriber`` is already registered with this Client, this function
34+
is a no-op. If ``$subscriber`` is also registered globally, it will still
35+
only be notified once of each event for this Client.
36+
37+
Errors/Exceptions
38+
-----------------
39+
40+
.. include:: /includes/extracts/error-invalidargumentexception.rst
41+
42+
:php:`MongoDB\\Driver\\Exception\\InvalidArgumentException <mongodb-driver-exception-invalidargumentexception>`
43+
if subscriber is a :php:`MongoDB\\Driver\\Monitoring\\LogSubscriber <class.mongodb-driver-monitoring-logsubscriber>`,
44+
since loggers can only be registered globally with
45+
:php:`MongoDB\\Driver\\Monitoring\\addSubscriber <function.mongodb.driver.monitoring.addsubscriber>`.
46+
47+
Example
48+
-------
49+
50+
Create a :phpclass:`MongoDB\\Driver\\Monitoring\\CommandSubscriber` that
51+
logs all events:
52+
53+
.. code-block:: php
54+
55+
<?php
56+
57+
use MongoDB\Driver\Monitoring\CommandSubscriber;
58+
use MongoDB\Driver\Monitoring\CommandStartedEvent;
59+
use MongoDB\Driver\Monitoring\CommandSucceededEvent;
60+
use MongoDB\Driver\Monitoring\CommandFailedEvent;
61+
62+
class LogCommandSubscriber implements CommandSubscriber
63+
{
64+
private $stream;
65+
public function __construct($stream)
66+
{
67+
$this->stream = $stream;
68+
}
69+
70+
public function commandStarted(CommandStartedEvent $event): void
71+
{
72+
fwrite($this->stream, sprintf(
73+
'Started command #%d "%s": %s%s',
74+
$event->getRequestId(),
75+
$event->getCommandName(),
76+
Document::fromPHP($event->getCommand())->toCanonicalExtendedJSON(),
77+
PHP_EOL,
78+
));
79+
}
80+
81+
public function commandSucceeded(CommandSucceededEvent $event): void
82+
{
83+
fwrite($this->stream, sprintf(
84+
'Succeeded command #%d "%s" in %d microseconds: %s%s',
85+
$event->getRequestId(),
86+
$event->getCommandName(),
87+
$event->getDurationMicros(),
88+
json_encode($event->getReply()),
89+
PHP_EOL,
90+
));
91+
}
92+
93+
public function commandFailed(CommandFailedEvent $event): void
94+
{
95+
fwrite($this->stream, sprintf(
96+
'Failed command #%d "%s" in %d microseconds: %s%s',
97+
$event->getRequestId(),
98+
$event->getCommandName(),
99+
$event->getDurationMicros(),
100+
$event->getError()->getMessage(),
101+
PHP_EOL,
102+
));
103+
}
104+
}
105+
106+
The subscriber can then be registered with a Client:
107+
108+
.. code-block:: php
109+
110+
<?php
111+
112+
$client = new MongoDB\Client();
113+
$subscriber = new LogCommandSubscriber(STDERR);
114+
115+
$client->addSubscriber($subscriber);
116+
117+
$client->test->users->insertOne(['username' => 'alice']);
118+
119+
The above code will write the following to stderr output:
120+
121+
.. code-block:: text
122+
123+
Started command #1 "insert": { "insert" : "users", "ordered" : true, "$db" : "test", "lsid" : { "id" : { "$binary" : { "base64" : "dKTBhZD7Qvi0vUhvR58mCA==", "subType" : "04" } } }, "documents" : [ { "username" : "alice", "_id" : { "$oid" : "655d1fca12e81018340a4fc2" } } ] }
124+
Succeeded command #1 "insert" in 876 microseconds: {"n":1,"ok":1}
125+
126+
See Also
127+
--------
128+
129+
- :phpmethod:`MongoDB\\Client::removeSubscriber()`
130+
- :php:`Application Performance Monitoring (APM) <manual/en/mongodb.tutorial.apm>`
131+
- :php:`MongoDB\\Driver\\Manager::addSubscriber() <manual/en/mongodb-driver-manager.addsubscriber>`
132+
- :php:`MongoDB\Driver\Monitoring\CommandSubscriber <manual/en/class.mongodb-driver-monitoring-commandsubscriber>`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
================================
2+
MongoDB\\Client::removeSubscriber()
3+
================================
4+
5+
.. versionadded:: 1.18
6+
7+
.. default-domain:: mongodb
8+
9+
.. contents:: On this page
10+
:local:
11+
:backlinks: none
12+
:depth: 1
13+
:class: singlecol
14+
15+
Definition
16+
----------
17+
18+
.. phpmethod:: MongoDB\\Client::removeSubscriber()
19+
20+
Unregisters a monitoring event subscriber with this Client.
21+
22+
.. code-block:: php
23+
24+
function removeSubscriber(MongoDB\Driver\Monitoring\Subscriber $subscriber): void
25+
26+
This method has the following parameters:
27+
28+
.. include:: /includes/apiargs/MongoDBClient-method-removeSubscriber-param.rst
29+
30+
.. note::
31+
32+
If ``$subscriber`` is not registered with this Client, this function
33+
is a no-op.
34+
35+
Errors/Exceptions
36+
-----------------
37+
38+
.. include:: /includes/extracts/error-invalidargumentexception.rst
39+
40+
See Also
41+
--------
42+
43+
- :phpmethod:`MongoDB\\Client::addSubscriber()`
44+
- :php:`Application Performance Monitoring (APM) <manual/en/mongodb.tutorial.apm>`
45+
- :php:`MongoDB\\Driver\\Manager::removeSubscriber() <manual/en/mongodb-driver-manager.addsubscriber>`
46+
- :php:`MongoDB\Driver\Monitoring\CommandSubscriber <manual/en/class.mongodb-driver-monitoring-commandsubscriber>`

examples/command_logger.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function commandFailed(CommandFailedEvent $event): void
5656

5757
$client = new Client(getenv('MONGODB_URI') ?: 'mongodb://127.0.0.1/');
5858

59-
$client->getManager()->addSubscriber(new CommandLogger());
59+
$client->addSubscriber(new CommandLogger());
6060

6161
$collection = $client->test->command_logger;
6262
$collection->drop();

src/Client.php

+21
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException;
2424
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
2525
use MongoDB\Driver\Manager;
26+
use MongoDB\Driver\Monitoring\Subscriber;
2627
use MongoDB\Driver\ReadConcern;
2728
use MongoDB\Driver\ReadPreference;
2829
use MongoDB\Driver\Session;
@@ -163,6 +164,16 @@ public function __toString()
163164
return $this->uri;
164165
}
165166

167+
/**
168+
* Registers a monitoring event subscriber with this Client's Manager
169+
*
170+
* @see Manager::addSubscriber()
171+
*/
172+
final public function addSubscriber(Subscriber $subscriber): void
173+
{
174+
$this->manager->addSubscriber($subscriber);
175+
}
176+
166177
/**
167178
* Returns a ClientEncryption instance for explicit encryption and decryption
168179
*
@@ -296,6 +307,16 @@ public function listDatabases(array $options = [])
296307
return $operation->execute($server);
297308
}
298309

310+
/**
311+
* Unregisters a monitoring event subscriber with this Client's Manager
312+
*
313+
* @see Manager::removeSubscriber()
314+
*/
315+
final public function removeSubscriber(Subscriber $subscriber): void
316+
{
317+
$this->manager->removeSubscriber($subscriber);
318+
}
319+
299320
/**
300321
* Select a collection.
301322
*

tests/ClientFunctionalTest.php

+18
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
use MongoDB\Client;
66
use MongoDB\Driver\BulkWrite;
7+
use MongoDB\Driver\Command;
78
use MongoDB\Driver\Manager;
9+
use MongoDB\Driver\Monitoring\CommandSubscriber;
810
use MongoDB\Driver\Session;
911
use MongoDB\Model\DatabaseInfo;
1012
use MongoDB\Model\DatabaseInfoIterator;
@@ -119,4 +121,20 @@ public function testStartSession(): void
119121
{
120122
$this->assertInstanceOf(Session::class, $this->client->startSession());
121123
}
124+
125+
public function testAddAndRemoveSubscriber(): void
126+
{
127+
$client = new Client(static::getUri());
128+
129+
$addedSubscriber = $this->createMock(CommandSubscriber::class);
130+
$addedSubscriber->expects($this->once())->method('commandStarted');
131+
$client->addSubscriber($addedSubscriber);
132+
133+
$removedSubscriber = $this->createMock(CommandSubscriber::class);
134+
$removedSubscriber->expects($this->never())->method('commandStarted');
135+
$client->addSubscriber($removedSubscriber);
136+
$client->removeSubscriber($removedSubscriber);
137+
138+
$client->getManager()->executeCommand('admin', new Command(['ping' => 1]));
139+
}
122140
}

0 commit comments

Comments
 (0)