Skip to content

Commit eb7f2e6

Browse files
committed
PYTHON-1138 - Improve SDAM monitoring documentation
1 parent 1d8f12f commit eb7f2e6

File tree

6 files changed

+180
-29
lines changed

6 files changed

+180
-29
lines changed

doc/api/pymongo/ismaster.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
:orphan:
2+
3+
:mod:`ismaster` -- A wrapper for ismaster command responses.
4+
============================================================
5+
6+
.. automodule:: pymongo.ismaster
7+
8+
.. autoclass:: pymongo.ismaster.IsMaster(doc)
9+
10+
.. autoattribute:: document
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
:orphan:
2+
3+
:mod:`server_description` -- An object representation of a server the driver is connected to.
4+
=============================================================================================
5+
6+
.. automodule:: pymongo.server_description
7+
8+
.. autoclass:: pymongo.server_description.ServerDescription()
9+
10+
.. autoattribute:: address
11+
.. autoattribute:: all_hosts
12+
.. autoattribute:: server_type
13+
.. autoattribute:: server_type_name
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
:orphan:
2+
3+
:mod:`topology_description` -- An object representation of a deployment of MongoDB servers.
4+
===========================================================================================
5+
6+
.. automodule:: pymongo.topology_description
7+
8+
.. autoclass:: pymongo.topology_description.TopologyDescription()
9+
10+
.. automethod:: has_readable_server(read_preference=ReadPreference.PRIMARY)
11+
.. automethod:: has_writable_server
12+
.. automethod:: server_descriptions
13+
.. autoattribute:: topology_type
14+
.. autoattribute:: topology_type_name

pymongo/monitoring.py

Lines changed: 134 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
"""Tools to monitor driver events.
1616
17+
.. versionadded:: 3.1
18+
1719
Use :func:`register` to register global listeners for specific events.
1820
Listeners must inherit from one of the abstract classes below and implement
1921
the correct functions for that class.
@@ -45,6 +47,74 @@ def failed(self, event):
4547
4648
monitoring.register(CommandLogger())
4749
50+
Server discovery and monitoring events are also available. For example::
51+
52+
class ServerLogger(monitoring.ServerListener):
53+
54+
def opened(self, event):
55+
logging.info("Server {0.server_address} added to topology "
56+
"{0.topology_id}".format(event))
57+
58+
def description_changed(self, event):
59+
previous_server_type = event.previous_description.server_type
60+
new_server_type = event.new_description.server_type
61+
if new_server_type != previous_server_type:
62+
# server_type_name was added in PyMongo 3.4
63+
logging.info(
64+
"Server {0.server_address} changed type from "
65+
"{0.previous_description.server_type_name} to "
66+
"{0.new_description.server_type_name}".format(event))
67+
68+
def closed(self, event):
69+
logging.warning("Server {0.server_address} removed from topology "
70+
"{0.topology_id}".format(event))
71+
72+
73+
class HeartbeatLogger(monitoring.ServerHeartbeatListener):
74+
75+
def started(self, event):
76+
logging.info("Heartbeat sent to server "
77+
"{0.connection_id}".format(event))
78+
79+
def succeeded(self, event):
80+
# The reply.document attribute was added in PyMongo 3.4.
81+
logging.info("Heartbeat to server {0.connection_id} "
82+
"succeeded with reply "
83+
"{0.reply.document}".format(event))
84+
85+
def failed(self, event):
86+
logging.warning("Heartbeat to server {0.connection_id} "
87+
"failed with error {0.reply}".format(event))
88+
89+
class TopologyLogger(monitoring.TopologyListener):
90+
91+
def opened(self, event):
92+
logging.info("Topology with id {0.topology_id} "
93+
"opened".format(event))
94+
95+
def description_changed(self, event):
96+
logging.info("Topology description updated for "
97+
"topology id {0.topology_id}".format(event))
98+
previous_topology_type = event.previous_description.topology_type
99+
new_topology_type = event.new_description.topology_type
100+
if new_topology_type != previous_topology_type:
101+
# topology_type_name was added in PyMongo 3.4
102+
logging.info(
103+
"Topology {0.topology_id} changed type from "
104+
"{0.previous_description.topology_type_name} to "
105+
"{0.new_description.topology_type_name}".format(event))
106+
# The has_writable_server and has_readable_server methods
107+
# were added in PyMongo 3.4.
108+
if not event.new_description.has_writable_server():
109+
logging.warning("No writable servers available.")
110+
if not event.new_description.has_readable_server():
111+
logging.warning("No readable servers available.")
112+
113+
def closed(self, event):
114+
logging.info("Topology with id {0.topology_id} "
115+
"closed".format(event))
116+
117+
48118
Event listeners can also be registered per instance of
49119
:class:`~pymongo.mongo_client.MongoClient`::
50120
@@ -78,13 +148,13 @@ def failed(self, event):
78148

79149

80150
class _EventListener(object):
81-
"""Abstract base class for all event listeners. """
151+
"""Abstract base class for all event listeners."""
82152

83153

84154
class CommandListener(_EventListener):
85155
"""Abstract base class for command listeners.
86156
Handles `CommandStartedEvent`, `CommandSucceededEvent`,
87-
and `CommandFailedEvent`"""
157+
and `CommandFailedEvent`."""
88158

89159
def started(self, event):
90160
"""Abstract method to handle a `CommandStartedEvent`.
@@ -114,7 +184,10 @@ def failed(self, event):
114184
class ServerHeartbeatListener(_EventListener):
115185
"""Abstract base class for server heartbeat listeners.
116186
Handles `ServerHeartbeatStartedEvent`, `ServerHeartbeatSucceededEvent`,
117-
and `ServerHeartbeatFailedEvent`."""
187+
and `ServerHeartbeatFailedEvent`.
188+
189+
.. versionadded:: 3.3
190+
"""
118191

119192
def started(self, event):
120193
"""Abstract method to handle a `ServerHeartbeatStartedEvent`.
@@ -144,7 +217,10 @@ def failed(self, event):
144217
class TopologyListener(_EventListener):
145218
"""Abstract base class for topology monitoring listeners.
146219
Handles `TopologyOpenedEvent`, `TopologyDescriptionChangedEvent`, and
147-
`TopologyClosedEvent`."""
220+
`TopologyClosedEvent`.
221+
222+
.. versionadded:: 3.3
223+
"""
148224

149225
def opened(self, event):
150226
"""Abstract method to handle a `TopologyOpenedEvent`.
@@ -174,7 +250,10 @@ def closed(self, event):
174250
class ServerListener(_EventListener):
175251
"""Abstract base class for server listeners.
176252
Handles `ServerOpeningEvent`, `ServerDescriptionChangedEvent`, and
177-
`ServerClosedEvent`."""
253+
`ServerClosedEvent`.
254+
255+
.. versionadded:: 3.3
256+
"""
178257

179258
def opened(self, event):
180259
"""Abstract method to handle a `ServerOpeningEvent`.
@@ -405,7 +484,10 @@ def topology_id(self):
405484

406485

407486
class ServerDescriptionChangedEvent(_ServerEvent):
408-
"""Published when server description changes."""
487+
"""Published when server description changes.
488+
489+
.. versionadded:: 3.3
490+
"""
409491

410492
__slots__ = ('__previous_description', '__new_description')
411493

@@ -416,25 +498,33 @@ def __init__(self, previous_description, new_description, *args):
416498

417499
@property
418500
def previous_description(self):
419-
"""The previous server description."""
501+
"""The previous
502+
:class:`~pymongo.server_description.ServerDescription`."""
420503
return self.__previous_description
421504

422505
@property
423506
def new_description(self):
424-
"""The new server description."""
507+
"""The new
508+
:class:`~pymongo.server_description.ServerDescription`."""
425509
return self.__new_description
426510

427511

428512
class ServerOpeningEvent(_ServerEvent):
429-
"""Published when server is initialized."""
513+
"""Published when server is initialized.
514+
515+
.. versionadded:: 3.3
516+
"""
430517

431518

432519
class ServerClosedEvent(_ServerEvent):
433-
"""Published when server is closed."""
520+
"""Published when server is closed.
521+
522+
.. versionadded:: 3.3
523+
"""
434524

435525

436526
class TopologyEvent(object):
437-
"""Base class for topology description events"""
527+
"""Base class for topology description events."""
438528

439529
__slots__ = ('__topology_id')
440530

@@ -448,7 +538,10 @@ def topology_id(self):
448538

449539

450540
class TopologyDescriptionChangedEvent(TopologyEvent):
451-
"""Published when the topology description changes."""
541+
"""Published when the topology description changes.
542+
543+
.. versionadded:: 3.3
544+
"""
452545

453546
__slots__ = ('__previous_description', '__new_description')
454547

@@ -459,25 +552,33 @@ def __init__(self, previous_description, new_description, *args):
459552

460553
@property
461554
def previous_description(self):
462-
"""The old topology description."""
555+
"""The previous
556+
:class:`~pymongo.topology_description.TopologyDescription`."""
463557
return self.__previous_description
464558

465559
@property
466560
def new_description(self):
467-
"""The new topology description."""
561+
"""The new
562+
:class:`~pymongo.topology_description.TopologyDescription`."""
468563
return self.__new_description
469564

470565

471566
class TopologyOpenedEvent(TopologyEvent):
472-
"""Published when the topology is initialized."""
567+
"""Published when the topology is initialized.
568+
569+
.. versionadded:: 3.3
570+
"""
473571

474572

475573
class TopologyClosedEvent(TopologyEvent):
476-
"""Published when the topology is closed."""
574+
"""Published when the topology is closed.
575+
576+
.. versionadded:: 3.3
577+
"""
477578

478579

479580
class _ServerHeartbeatEvent(object):
480-
"""Base class for server heartbeat events"""
581+
"""Base class for server heartbeat events."""
481582

482583
__slots__ = ('__connection_id')
483584

@@ -486,17 +587,23 @@ def __init__(self, connection_id):
486587

487588
@property
488589
def connection_id(self):
489-
""""The address (host, port) of the server this heartbeat was sent
490-
to."""
590+
"""The address (host, port) of the server this heartbeat was sent
591+
to."""
491592
return self.__connection_id
492593

493594

494595
class ServerHeartbeatStartedEvent(_ServerHeartbeatEvent):
495-
""""Published when a heartbeat is started."""
596+
"""Published when a heartbeat is started.
597+
598+
.. versionadded:: 3.3
599+
"""
496600

497601

498602
class ServerHeartbeatSucceededEvent(_ServerHeartbeatEvent):
499-
"""Fired when the server heartbeat succeeds."""
603+
"""Fired when the server heartbeat succeeds.
604+
605+
.. versionadded:: 3.3
606+
"""
500607

501608
__slots__ = ('__duration', '__reply')
502609

@@ -512,13 +619,16 @@ def duration(self):
512619

513620
@property
514621
def reply(self):
515-
"""The command reply."""
622+
"""An instance of :class:`~pymongo.ismaster.IsMaster`."""
516623
return self.__reply
517624

518625

519626
class ServerHeartbeatFailedEvent(_ServerHeartbeatEvent):
520627
"""Fired when the server heartbeat fails, either with an "ok: 0"
521-
or a socket exception."""
628+
or a socket exception.
629+
630+
.. versionadded:: 3.3
631+
"""
522632

523633
__slots__ = ('__duration', '__reply')
524634

@@ -534,7 +644,7 @@ def duration(self):
534644

535645
@property
536646
def reply(self):
537-
"""The command reply."""
647+
"""A subclass of :exc:`Exception`."""
538648
return self.__reply
539649

540650

pymongo/server_description.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""Represent one server in the topology."""
15+
"""Represent one server the driver is connected to."""
1616

1717
from bson import EPOCH_NAIVE
1818
from pymongo.server_type import SERVER_TYPE
@@ -85,10 +85,12 @@ def __init__(
8585

8686
@property
8787
def address(self):
88+
"""The address (host, port) of this server."""
8889
return self._address
8990

9091
@property
9192
def server_type(self):
93+
"""The type of this server."""
9294
return self._server_type
9395

9496
@property

pymongo/topology_description.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# implied. See the License for the specific language governing
1313
# permissions and limitations under the License.
1414

15-
"""Represent the topology of servers."""
15+
"""Represent a deployment of MongoDB servers."""
1616

1717
from collections import namedtuple
1818

@@ -37,7 +37,7 @@ def __init__(self,
3737
max_set_version,
3838
max_election_id,
3939
topology_settings):
40-
"""Represent a topology of servers.
40+
"""Representation of a deployment of MongoDB servers.
4141
4242
:Parameters:
4343
- `topology_type`: initial type
@@ -121,11 +121,13 @@ def reset(self):
121121
self._topology_settings)
122122

123123
def server_descriptions(self):
124-
"""Dict of (address, ServerDescription)."""
124+
"""Dict of (address,
125+
:class:`~pymongo.server_description.ServerDescription`)."""
125126
return self._server_descriptions.copy()
126127

127128
@property
128129
def topology_type(self):
130+
"""The type of this topology."""
129131
return self._topology_type
130132

131133
@property
@@ -215,7 +217,7 @@ def has_readable_server(self, read_preference=ReadPreference.PRIMARY):
215217
:Parameters:
216218
- `read_preference`: an instance of a read preference from
217219
:mod:`~pymongo.read_preferences`. Defaults to
218-
:attr:`~pymongo.ReadPreference.PRIMARY`.
220+
:attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.
219221
220222
.. note:: When connected directly to a single server this method
221223
always returns ``True``.

0 commit comments

Comments
 (0)