event_loggers.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. # Copyright 2020-present MongoDB, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Example event logger classes.
  15. .. versionadded:: 3.11
  16. These loggers can be registered using :func:`register` or
  17. :class:`~pymongo.mongo_client.MongoClient`.
  18. ``monitoring.register(CommandLogger())``
  19. or
  20. ``MongoClient(event_listeners=[CommandLogger()])``
  21. """
  22. import logging
  23. from pymongo import monitoring
  24. class CommandLogger(monitoring.CommandListener):
  25. """A simple listener that logs command events.
  26. Listens for :class:`~pymongo.monitoring.CommandStartedEvent`,
  27. :class:`~pymongo.monitoring.CommandSucceededEvent` and
  28. :class:`~pymongo.monitoring.CommandFailedEvent` events and
  29. logs them at the `INFO` severity level using :mod:`logging`.
  30. .. versionadded:: 3.11
  31. """
  32. def started(self, event):
  33. logging.info("Command {0.command_name} with request id "
  34. "{0.request_id} started on server "
  35. "{0.connection_id}".format(event))
  36. def succeeded(self, event):
  37. logging.info("Command {0.command_name} with request id "
  38. "{0.request_id} on server {0.connection_id} "
  39. "succeeded in {0.duration_micros} "
  40. "microseconds".format(event))
  41. def failed(self, event):
  42. logging.info("Command {0.command_name} with request id "
  43. "{0.request_id} on server {0.connection_id} "
  44. "failed in {0.duration_micros} "
  45. "microseconds".format(event))
  46. class ServerLogger(monitoring.ServerListener):
  47. """A simple listener that logs server discovery events.
  48. Listens for :class:`~pymongo.monitoring.ServerOpeningEvent`,
  49. :class:`~pymongo.monitoring.ServerDescriptionChangedEvent`,
  50. and :class:`~pymongo.monitoring.ServerClosedEvent`
  51. events and logs them at the `INFO` severity level using :mod:`logging`.
  52. .. versionadded:: 3.11
  53. """
  54. def opened(self, event):
  55. logging.info("Server {0.server_address} added to topology "
  56. "{0.topology_id}".format(event))
  57. def description_changed(self, event):
  58. previous_server_type = event.previous_description.server_type
  59. new_server_type = event.new_description.server_type
  60. if new_server_type != previous_server_type:
  61. # server_type_name was added in PyMongo 3.4
  62. logging.info(
  63. "Server {0.server_address} changed type from "
  64. "{0.previous_description.server_type_name} to "
  65. "{0.new_description.server_type_name}".format(event))
  66. def closed(self, event):
  67. logging.warning("Server {0.server_address} removed from topology "
  68. "{0.topology_id}".format(event))
  69. class HeartbeatLogger(monitoring.ServerHeartbeatListener):
  70. """A simple listener that logs server heartbeat events.
  71. Listens for :class:`~pymongo.monitoring.ServerHeartbeatStartedEvent`,
  72. :class:`~pymongo.monitoring.ServerHeartbeatSucceededEvent`,
  73. and :class:`~pymongo.monitoring.ServerHeartbeatFailedEvent`
  74. events and logs them at the `INFO` severity level using :mod:`logging`.
  75. .. versionadded:: 3.11
  76. """
  77. def started(self, event):
  78. logging.info("Heartbeat sent to server "
  79. "{0.connection_id}".format(event))
  80. def succeeded(self, event):
  81. # The reply.document attribute was added in PyMongo 3.4.
  82. logging.info("Heartbeat to server {0.connection_id} "
  83. "succeeded with reply "
  84. "{0.reply.document}".format(event))
  85. def failed(self, event):
  86. logging.warning("Heartbeat to server {0.connection_id} "
  87. "failed with error {0.reply}".format(event))
  88. class TopologyLogger(monitoring.TopologyListener):
  89. """A simple listener that logs server topology events.
  90. Listens for :class:`~pymongo.monitoring.TopologyOpenedEvent`,
  91. :class:`~pymongo.monitoring.TopologyDescriptionChangedEvent`,
  92. and :class:`~pymongo.monitoring.TopologyClosedEvent`
  93. events and logs them at the `INFO` severity level using :mod:`logging`.
  94. .. versionadded:: 3.11
  95. """
  96. def opened(self, event):
  97. logging.info("Topology with id {0.topology_id} "
  98. "opened".format(event))
  99. def description_changed(self, event):
  100. logging.info("Topology description updated for "
  101. "topology id {0.topology_id}".format(event))
  102. previous_topology_type = event.previous_description.topology_type
  103. new_topology_type = event.new_description.topology_type
  104. if new_topology_type != previous_topology_type:
  105. # topology_type_name was added in PyMongo 3.4
  106. logging.info(
  107. "Topology {0.topology_id} changed type from "
  108. "{0.previous_description.topology_type_name} to "
  109. "{0.new_description.topology_type_name}".format(event))
  110. # The has_writable_server and has_readable_server methods
  111. # were added in PyMongo 3.4.
  112. if not event.new_description.has_writable_server():
  113. logging.warning("No writable servers available.")
  114. if not event.new_description.has_readable_server():
  115. logging.warning("No readable servers available.")
  116. def closed(self, event):
  117. logging.info("Topology with id {0.topology_id} "
  118. "closed".format(event))
  119. class ConnectionPoolLogger(monitoring.ConnectionPoolListener):
  120. """A simple listener that logs server connection pool events.
  121. Listens for :class:`~pymongo.monitoring.PoolCreatedEvent`,
  122. :class:`~pymongo.monitoring.PoolClearedEvent`,
  123. :class:`~pymongo.monitoring.PoolClosedEvent`,
  124. :~pymongo.monitoring.class:`ConnectionCreatedEvent`,
  125. :class:`~pymongo.monitoring.ConnectionReadyEvent`,
  126. :class:`~pymongo.monitoring.ConnectionClosedEvent`,
  127. :class:`~pymongo.monitoring.ConnectionCheckOutStartedEvent`,
  128. :class:`~pymongo.monitoring.ConnectionCheckOutFailedEvent`,
  129. :class:`~pymongo.monitoring.ConnectionCheckedOutEvent`,
  130. and :class:`~pymongo.monitoring.ConnectionCheckedInEvent`
  131. events and logs them at the `INFO` severity level using :mod:`logging`.
  132. .. versionadded:: 3.11
  133. """
  134. def pool_created(self, event):
  135. logging.info("[pool {0.address}] pool created".format(event))
  136. def pool_cleared(self, event):
  137. logging.info("[pool {0.address}] pool cleared".format(event))
  138. def pool_closed(self, event):
  139. logging.info("[pool {0.address}] pool closed".format(event))
  140. def connection_created(self, event):
  141. logging.info("[pool {0.address}][conn #{0.connection_id}] "
  142. "connection created".format(event))
  143. def connection_ready(self, event):
  144. logging.info("[pool {0.address}][conn #{0.connection_id}] "
  145. "connection setup succeeded".format(event))
  146. def connection_closed(self, event):
  147. logging.info("[pool {0.address}][conn #{0.connection_id}] "
  148. "connection closed, reason: "
  149. "{0.reason}".format(event))
  150. def connection_check_out_started(self, event):
  151. logging.info("[pool {0.address}] connection check out "
  152. "started".format(event))
  153. def connection_check_out_failed(self, event):
  154. logging.info("[pool {0.address}] connection check out "
  155. "failed, reason: {0.reason}".format(event))
  156. def connection_checked_out(self, event):
  157. logging.info("[pool {0.address}][conn #{0.connection_id}] "
  158. "connection checked out of pool".format(event))
  159. def connection_checked_in(self, event):
  160. logging.info("[pool {0.address}][conn #{0.connection_id}] "
  161. "connection checked into pool".format(event))