PYTHON-1138 - Improve SDAM monitoring documentation

This commit is contained in:
Bernie Hackett 2016-09-01 14:33:01 -07:00
parent 1d8f12fa60
commit eb7f2e625a
6 changed files with 180 additions and 29 deletions

View File

@ -0,0 +1,10 @@
:orphan:
:mod:`ismaster` -- A wrapper for ismaster command responses.
============================================================
.. automodule:: pymongo.ismaster
.. autoclass:: pymongo.ismaster.IsMaster(doc)
.. autoattribute:: document

View File

@ -0,0 +1,13 @@
:orphan:
:mod:`server_description` -- An object representation of a server the driver is connected to.
=============================================================================================
.. automodule:: pymongo.server_description
.. autoclass:: pymongo.server_description.ServerDescription()
.. autoattribute:: address
.. autoattribute:: all_hosts
.. autoattribute:: server_type
.. autoattribute:: server_type_name

View File

@ -0,0 +1,14 @@
:orphan:
:mod:`topology_description` -- An object representation of a deployment of MongoDB servers.
===========================================================================================
.. automodule:: pymongo.topology_description
.. autoclass:: pymongo.topology_description.TopologyDescription()
.. automethod:: has_readable_server(read_preference=ReadPreference.PRIMARY)
.. automethod:: has_writable_server
.. automethod:: server_descriptions
.. autoattribute:: topology_type
.. autoattribute:: topology_type_name

View File

@ -14,6 +14,8 @@
"""Tools to monitor driver events.
.. versionadded:: 3.1
Use :func:`register` to register global listeners for specific events.
Listeners must inherit from one of the abstract classes below and implement
the correct functions for that class.
@ -45,6 +47,74 @@ For example, a simple command logger might be implemented like this::
monitoring.register(CommandLogger())
Server discovery and monitoring events are also available. For example::
class ServerLogger(monitoring.ServerListener):
def opened(self, event):
logging.info("Server {0.server_address} added to topology "
"{0.topology_id}".format(event))
def description_changed(self, event):
previous_server_type = event.previous_description.server_type
new_server_type = event.new_description.server_type
if new_server_type != previous_server_type:
# server_type_name was added in PyMongo 3.4
logging.info(
"Server {0.server_address} changed type from "
"{0.previous_description.server_type_name} to "
"{0.new_description.server_type_name}".format(event))
def closed(self, event):
logging.warning("Server {0.server_address} removed from topology "
"{0.topology_id}".format(event))
class HeartbeatLogger(monitoring.ServerHeartbeatListener):
def started(self, event):
logging.info("Heartbeat sent to server "
"{0.connection_id}".format(event))
def succeeded(self, event):
# The reply.document attribute was added in PyMongo 3.4.
logging.info("Heartbeat to server {0.connection_id} "
"succeeded with reply "
"{0.reply.document}".format(event))
def failed(self, event):
logging.warning("Heartbeat to server {0.connection_id} "
"failed with error {0.reply}".format(event))
class TopologyLogger(monitoring.TopologyListener):
def opened(self, event):
logging.info("Topology with id {0.topology_id} "
"opened".format(event))
def description_changed(self, event):
logging.info("Topology description updated for "
"topology id {0.topology_id}".format(event))
previous_topology_type = event.previous_description.topology_type
new_topology_type = event.new_description.topology_type
if new_topology_type != previous_topology_type:
# topology_type_name was added in PyMongo 3.4
logging.info(
"Topology {0.topology_id} changed type from "
"{0.previous_description.topology_type_name} to "
"{0.new_description.topology_type_name}".format(event))
# The has_writable_server and has_readable_server methods
# were added in PyMongo 3.4.
if not event.new_description.has_writable_server():
logging.warning("No writable servers available.")
if not event.new_description.has_readable_server():
logging.warning("No readable servers available.")
def closed(self, event):
logging.info("Topology with id {0.topology_id} "
"closed".format(event))
Event listeners can also be registered per instance of
:class:`~pymongo.mongo_client.MongoClient`::
@ -78,13 +148,13 @@ _LISTENERS = _Listeners([], [], [], [])
class _EventListener(object):
"""Abstract base class for all event listeners. """
"""Abstract base class for all event listeners."""
class CommandListener(_EventListener):
"""Abstract base class for command listeners.
Handles `CommandStartedEvent`, `CommandSucceededEvent`,
and `CommandFailedEvent`"""
and `CommandFailedEvent`."""
def started(self, event):
"""Abstract method to handle a `CommandStartedEvent`.
@ -114,7 +184,10 @@ class CommandListener(_EventListener):
class ServerHeartbeatListener(_EventListener):
"""Abstract base class for server heartbeat listeners.
Handles `ServerHeartbeatStartedEvent`, `ServerHeartbeatSucceededEvent`,
and `ServerHeartbeatFailedEvent`."""
and `ServerHeartbeatFailedEvent`.
.. versionadded:: 3.3
"""
def started(self, event):
"""Abstract method to handle a `ServerHeartbeatStartedEvent`.
@ -144,7 +217,10 @@ class ServerHeartbeatListener(_EventListener):
class TopologyListener(_EventListener):
"""Abstract base class for topology monitoring listeners.
Handles `TopologyOpenedEvent`, `TopologyDescriptionChangedEvent`, and
`TopologyClosedEvent`."""
`TopologyClosedEvent`.
.. versionadded:: 3.3
"""
def opened(self, event):
"""Abstract method to handle a `TopologyOpenedEvent`.
@ -174,7 +250,10 @@ class TopologyListener(_EventListener):
class ServerListener(_EventListener):
"""Abstract base class for server listeners.
Handles `ServerOpeningEvent`, `ServerDescriptionChangedEvent`, and
`ServerClosedEvent`."""
`ServerClosedEvent`.
.. versionadded:: 3.3
"""
def opened(self, event):
"""Abstract method to handle a `ServerOpeningEvent`.
@ -405,7 +484,10 @@ class _ServerEvent(object):
class ServerDescriptionChangedEvent(_ServerEvent):
"""Published when server description changes."""
"""Published when server description changes.
.. versionadded:: 3.3
"""
__slots__ = ('__previous_description', '__new_description')
@ -416,25 +498,33 @@ class ServerDescriptionChangedEvent(_ServerEvent):
@property
def previous_description(self):
"""The previous server description."""
"""The previous
:class:`~pymongo.server_description.ServerDescription`."""
return self.__previous_description
@property
def new_description(self):
"""The new server description."""
"""The new
:class:`~pymongo.server_description.ServerDescription`."""
return self.__new_description
class ServerOpeningEvent(_ServerEvent):
"""Published when server is initialized."""
"""Published when server is initialized.
.. versionadded:: 3.3
"""
class ServerClosedEvent(_ServerEvent):
"""Published when server is closed."""
"""Published when server is closed.
.. versionadded:: 3.3
"""
class TopologyEvent(object):
"""Base class for topology description events"""
"""Base class for topology description events."""
__slots__ = ('__topology_id')
@ -448,7 +538,10 @@ class TopologyEvent(object):
class TopologyDescriptionChangedEvent(TopologyEvent):
"""Published when the topology description changes."""
"""Published when the topology description changes.
.. versionadded:: 3.3
"""
__slots__ = ('__previous_description', '__new_description')
@ -459,25 +552,33 @@ class TopologyDescriptionChangedEvent(TopologyEvent):
@property
def previous_description(self):
"""The old topology description."""
"""The previous
:class:`~pymongo.topology_description.TopologyDescription`."""
return self.__previous_description
@property
def new_description(self):
"""The new topology description."""
"""The new
:class:`~pymongo.topology_description.TopologyDescription`."""
return self.__new_description
class TopologyOpenedEvent(TopologyEvent):
"""Published when the topology is initialized."""
"""Published when the topology is initialized.
.. versionadded:: 3.3
"""
class TopologyClosedEvent(TopologyEvent):
"""Published when the topology is closed."""
"""Published when the topology is closed.
.. versionadded:: 3.3
"""
class _ServerHeartbeatEvent(object):
"""Base class for server heartbeat events"""
"""Base class for server heartbeat events."""
__slots__ = ('__connection_id')
@ -486,17 +587,23 @@ class _ServerHeartbeatEvent(object):
@property
def connection_id(self):
""""The address (host, port) of the server this heartbeat was sent
to."""
"""The address (host, port) of the server this heartbeat was sent
to."""
return self.__connection_id
class ServerHeartbeatStartedEvent(_ServerHeartbeatEvent):
""""Published when a heartbeat is started."""
"""Published when a heartbeat is started.
.. versionadded:: 3.3
"""
class ServerHeartbeatSucceededEvent(_ServerHeartbeatEvent):
"""Fired when the server heartbeat succeeds."""
"""Fired when the server heartbeat succeeds.
.. versionadded:: 3.3
"""
__slots__ = ('__duration', '__reply')
@ -512,13 +619,16 @@ class ServerHeartbeatSucceededEvent(_ServerHeartbeatEvent):
@property
def reply(self):
"""The command reply."""
"""An instance of :class:`~pymongo.ismaster.IsMaster`."""
return self.__reply
class ServerHeartbeatFailedEvent(_ServerHeartbeatEvent):
"""Fired when the server heartbeat fails, either with an "ok: 0"
or a socket exception."""
or a socket exception.
.. versionadded:: 3.3
"""
__slots__ = ('__duration', '__reply')
@ -534,7 +644,7 @@ class ServerHeartbeatFailedEvent(_ServerHeartbeatEvent):
@property
def reply(self):
"""The command reply."""
"""A subclass of :exc:`Exception`."""
return self.__reply

View File

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Represent one server in the topology."""
"""Represent one server the driver is connected to."""
from bson import EPOCH_NAIVE
from pymongo.server_type import SERVER_TYPE
@ -85,10 +85,12 @@ class ServerDescription(object):
@property
def address(self):
"""The address (host, port) of this server."""
return self._address
@property
def server_type(self):
"""The type of this server."""
return self._server_type
@property

View File

@ -12,7 +12,7 @@
# implied. See the License for the specific language governing
# permissions and limitations under the License.
"""Represent the topology of servers."""
"""Represent a deployment of MongoDB servers."""
from collections import namedtuple
@ -37,7 +37,7 @@ class TopologyDescription(object):
max_set_version,
max_election_id,
topology_settings):
"""Represent a topology of servers.
"""Representation of a deployment of MongoDB servers.
:Parameters:
- `topology_type`: initial type
@ -121,11 +121,13 @@ class TopologyDescription(object):
self._topology_settings)
def server_descriptions(self):
"""Dict of (address, ServerDescription)."""
"""Dict of (address,
:class:`~pymongo.server_description.ServerDescription`)."""
return self._server_descriptions.copy()
@property
def topology_type(self):
"""The type of this topology."""
return self._topology_type
@property
@ -215,7 +217,7 @@ class TopologyDescription(object):
:Parameters:
- `read_preference`: an instance of a read preference from
:mod:`~pymongo.read_preferences`. Defaults to
:attr:`~pymongo.ReadPreference.PRIMARY`.
:attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.
.. note:: When connected directly to a single server this method
always returns ``True``.