Skip to content

DOCSP-41982: cluster monitoring #144

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

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions source/includes/monitoring/sdam.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

require __DIR__ . '/vendor/autoload.php';

// start-mysubscriber
class MySubscriber implements MongoDB\Driver\Monitoring\SDAMSubscriber
{
private $stream;
public function __construct($stream)
{
$this->stream = $stream;
}
public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void
public function serverOpening(MongoDB\Driver\Monitoring\ServerOpeningEvent $event): void

Also, between any methods with bodies.

{
fwrite($this->stream, sprintf(
'Server opening on %s:%s%s',
$event->getHost(),
$event->getPort(),
PHP_EOL,
));
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fwrite($this->stream, sprintf(
'Server opening on %s:%s%s',
$event->getHost(),
$event->getPort(),
PHP_EOL,
));
fprintf(
$this->stream,
"Server opening on %s:%s\n",
$event->getHost(),
$event->getPort(),
);

See: https://www.php.net/fprintf

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Looks like @GromNaN originally wrote that in mongodb/mongo-php-library@b455ab7 😄

}
public function serverClosed(MongoDB\Driver\Monitoring\ServerClosedEvent $event): void {}
public function serverChanged(MongoDB\Driver\Monitoring\ServerChangedEvent $event): void {}
public function serverHeartbeatFailed(MongoDB\Driver\Monitoring\ServerHeartbeatFailedEvent $event): void {}
public function serverHeartbeatStarted(MongoDB\Driver\Monitoring\ServerHeartbeatStartedEvent $event): void {}
public function serverHeartbeatSucceeded(MongoDB\Driver\Monitoring\ServerHeartbeatSucceededEvent $event): void {}
public function topologyChanged(MongoDB\Driver\Monitoring\TopologyChangedEvent $event): void {}
public function topologyClosed(MongoDB\Driver\Monitoring\TopologyClosedEvent $event): void {}
public function topologyOpening(MongoDB\Driver\Monitoring\TopologyOpeningEvent $event): void {}
Copy link
Member

Choose a reason for hiding this comment

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

I believe contravariance would allow us to remove the type hints from these methods and make the code more concise. See: https://3v4l.org/H34oT#v8.3.11

That said, it'd make the example code less useful for copying if users want to implement these methods themselves. I'm fine to leave these as-is.

/cc @alcaeus

Copy link
Member

Choose a reason for hiding this comment

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

Omitting the types would make the example more concise, but I'd like to avoid suggesting to do this in documentation, as I consider it bad practice. We could leverage use statements to shorten the types, but that may be difficult if only small snippets of this code are included in the documentation.

We face a similar issue with the other documentation examples used in the server docs, and we decided to just deal with the long types in favour of having copy-pastable code.

}
// end-mysubscriber

$uri = getenv('MONGODB_URI') ?: throw new RuntimeException('Set the MONGODB_URI variable to your Atlas URI that connects to the sample dataset');
$client = new MongoDB\Client($uri);

$database = $client->db;
$collection = $database->my_coll;

// start-add-sub
$subscriber = new MySubscriber(STDERR);
$client->addSubscriber($subscriber);
// end-add-sub

$collection->insertOne(['x' => 100]);
1 change: 1 addition & 0 deletions source/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ MongoDB PHP Library
/write
/aggregation
/indexes
/monitoring
/security
/tutorial
/upgrade
Expand Down
21 changes: 21 additions & 0 deletions source/monitoring.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.. _php-monitoring:

========================
Monitor Your Application
========================

.. toctree::
:caption: Monitoring categories

/monitoring/cluster-monitoring

.. /monitoring/command-monitoring
.. /monitoring/connection-monitoring

- :ref:`Cluster Monitoring <php-cluster-monitoring>`: Monitor changes
in your cluster configuration

.. TODO - :ref:`Command Monitoring <php-command-monitoring>`: monitor command
.. execution
.. - :ref:`Connection Pool Monitoring <php-connection-monitoring>`:
.. monitor changes in the connection pool
136 changes: 136 additions & 0 deletions source/monitoring/cluster-monitoring.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
.. _php-cluster-monitoring:

==================
Cluster Monitoring
==================

.. facet::
:name: genre
:values: reference

.. meta::
:keywords: code example, server, topology

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecols

Overview
--------

This guide shows you how to use the {+php-library+} to monitor topology
events in a MongoDB instance, replica set, or sharded cluster. The
driver creates topology events, also known as Server Discovery and
Copy link
Member

Choose a reason for hiding this comment

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

Technically, topology events are those related to the entire cluster, while server events are those pertaining to a single server within the topology. SDAM monitoring includes both types of events.

I would personally just refer to them as SDAM events, as you seem to do in a subsequent section. If you need a short name, "cluster events" might also work but there's no prior art for that in any driver spec.

Disregard if this name was intentionally chosen for consistency with existing driver docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good to know, in general it is ok if this page differs from the same page in other docs. Each docs standardization is meant to improve on previous ones!

Monitoring (SDAM) events, when there are any changes in the state of the
MongoDB instance or cluster that you are connected to.

You might use information about topology events in your
application to understand cluster changes, assess cluster health, or
perform capacity planning.

Subscribe to Events
-------------------

You can access details about SDAM events by subscribing to them
in your application. To subscribe to an event, create a class that
implements the ``MongoDB\Driver\Monitoring\SDAMSubscriber`` interface,
then use the ``MongoDB\Client::addSubscriber()`` method to register the
event subscriber with your ``MongoDB\Client`` instance.

The following code creates the ``MySubscriber`` class, which implements
the ``SDAMSubscriber`` interface. The class is defined with a method to
output a message when a ``ServerOpeningEvent`` is generated by the
server:

.. literalinclude:: /includes/monitoring/sdam.php
:start-after: start-mysubscriber
:end-before: end-mysubscriber
:language: php
:copyable:
:dedent:

.. note::

As shown in the preceding code, you must implement all of the methods

Check failure on line 56 in source/monitoring/cluster-monitoring.txt

View workflow job for this annotation

GitHub Actions / TDBX Vale rules

[vale] reported by reviewdog 🐶 [MongoDB.Wordiness] Consider using 'all' instead of 'all of'. Raw Output: {"message": "[MongoDB.Wordiness] Consider using 'all' instead of 'all of'.", "location": {"path": "source/monitoring/cluster-monitoring.txt", "range": {"start": {"line": 56, "column": 55}}}, "severity": "ERROR"}
of the ``SDAMSubscriber`` interface, even for events you are not subscribing to.
You can implement these methods with empty bodies so that the library
does not generate any messages for these events.

Then, use the ``addSubscriber()`` method to register ``MySubscriber``
with the client, as shown in the following code:

.. literalinclude:: /includes/monitoring/sdam.php
:start-after: start-add-sub
:end-before: end-add-sub
:language: php
:copyable:
:dedent:

When you run the application, your subscriber records the SDAM event and
outputs messages such as the following:

.. code-block:: none
:copyable: false

Server opening on ac-rmuag0v-shard-00-00.gh0qg50.mongodb.net:27017
Server opening on ac-rmuag0v-shard-00-01.gh0qg50.mongodb.net:27017
Server opening on ac-rmuag0v-shard-00-02.gh0qg50.mongodb.net:27017

Event Descriptions
------------------

You can subscribe to the following SDAM events by implementing the
corresponding method from the ``SDAMSubscriber`` interface:

.. list-table::
:widths: 35 65
:header-rows: 1

* - Event Name
- Description

* - ``ServerChangedEvent``
- Created when an instance state changes, such as from secondary to
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional: Could remove "Created when" from the start of every event (probably along with a new column header name)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can't think of a good way to adjust the column header, as renaming it "Situation that Triggers Event" seems worse than keeping the "Created when"s in

Copy link
Member

Choose a reason for hiding this comment

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

In the docs for ServerChangedEvent we say the event class "encapsulates information about a changed server description".

Here, the table is presenting the event as the thing that happened instead of just an object containing some information about a thing that happened.

The "Condition" column in Events API from the driver spec might be helpful. Note that the spec includes "Description" in the name of these events, where PHP just calls it ServerChangedEvent. I think that was due to us copying the shorter name from our libmongoc dependency.

I might suggest:

When the server description changes, such as the server's type changing from secondary to primary.

primary.

* - ``ServerOpeningEvent``
- Created when the server is initialized.

* - ``ServerClosedEvent``
- Created when the server is closed.

* - ``TopologyChangedEvent``
- Created when the topology changes, such as an election of a new
primary or disconnection of a ``mongos`` proxy.

* - ``TopologyOpeningEvent``
- Created when the topology is initialized.

* - ``TopologyClosedEvent``
- Created when the topology is closed.
Copy link
Member

Choose a reason for hiding this comment

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

I'd reword this as "the driver disconnects from the cluster". Given the event name, I don't think we need to repeat "topology is closed" in the description, although you can still include both if you like. In that case, maybe note the disconnect behavior with "i.e." or something.

Per the SDAM Monitoring spec, this would always be the last event to be dispatched. In the PHP driver, it's not actually possible to observe this event when using default behavior, as we persist the libmongoc client object (and thus the connections) beyond the lifetime of the PHP script. So by the time a client is actually closed, there'd be no subscriber in memory to receive the event.

This event can only be observed when specifying disableClientPersistence: true in the Manager or Client driver options array. There's more context to be found in PHPC-2023 and mongodb/mongo-php-driver@c2410ab.

Having said that, I think it's sufficient to just refer to disconnecting from the cluster here. And admittedly, we (the PHP team) should improve the docs for these event classes. I created PHPC-2449 to track that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

thanks for providing this background!


* - ``ServerHeartbeatStartedEvent``
- Created when the heartbeat is started.

* - ``ServerHeartbeatSucceededEvent``
- Created when the heartbeat succeeds.

* - ``ServerHeartbeatFailedEvent``
- Created when the heartbeat fails.

API Documentation
-----------------

To learn more about any of the classes or methods discussed in this guide, see the
following API documentation:

- :phpmethod:`MongoDB\Client::addSubscriber()`
- :phpclass:`MongoDB\Client`

To learn more about subscriber classes and methods, see the following
pages in the PHP manual:

- :php:`MongoDB\Driver\Monitoring\SDAMSubscriber <mongodb-driver-monitoring-sdamsubscriber>`
- :php:`MongoDB\Driver\Monitoring\ServerOpeningEvent <mongodb-driver-monitoring-serveropeningevent>`
Loading