diff --git a/source/includes/monitoring/monitoring.rb b/source/includes/monitoring/monitoring.rb new file mode 100644 index 00000000..444b11e0 --- /dev/null +++ b/source/includes/monitoring/monitoring.rb @@ -0,0 +1,173 @@ +# start-available-subscriber +subscriber = Mongo::Monitoring::ServerOpeningLogSubscriber.new + +# Globally subscribes to ServerOpening events by using the SERVER_OPENING monitoring topic +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_OPENING, subscriber) +client = Mongo::Client.new(['127.0.0.1:27017']) + +# Subscribes to ServerOpening events at the client level by using the SERVER_OPENING monitoring topic +client.subscribe( Mongo::Monitoring::SERVER_OPENING, subscriber ) +# end-available-subscriber + +# start-sdam +class SDAMLogSubscriber + include Mongo::Loggable + + def succeeded(event) + log_debug(format_event(event)) + end + + private + + def logger + Mongo::Logger.logger + end + + def format_message(message) + format("SDAM | %s", message) + end +end + +class TopologyOpeningLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + "Topology type '#{event.topology.display_name}' initializing." + end +end + +class ServerOpeningLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + "Server #{event.address} initializing." + end +end + +class ServerDescriptionChangedLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + "Server description for #{event.address} changed from " + + "'#{event.previous_description.server_type}' to '#{event.new_description.server_type}'." + end +end + +class TopologyChangedLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + if event.previous_topology != event.new_topology + "Topology type '#{event.previous_topology.display_name}' changed to " + + "type '#{event.new_topology.display_name}'." + else + "There was a change in the members of the '#{event.new_topology.display_name}' " + + "topology." + end + end +end + +class ServerClosedLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + "Server #{event.address} connection closed." + end +end + +class TopologyClosedLogSubscriber < SDAMLogSubscriber + private + + def format_event(event) + "Topology type '#{event.topology.display_name}' closed." + end +end +#end-sdam + +# start-sdam-subscriber-global +topology_opening_subscriber = TopologyOpeningLogSubscriber.new +server_opening_subscriber = ServerOpeningLogSubscriber.new +server_description_changed_subscriber = ServerDescriptionChangedLogSubscriber.new +topology_changed_subscriber = TopologyChangedLogSubscriber.new +server_closed_subscriber = ServerClosedLogSubscriber.new +topology_closed_subscriber = TopologyClosedLogSubscriber.new + +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING, + topology_opening_subscriber) +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_OPENING, + server_opening_subscriber) +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_DESCRIPTION_CHANGED, + server_description_changed_subscriber) +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_CHANGED, + topology_changed_subscriber) +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_CLOSED, + server_closed_subscriber) +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_CLOSED, + topology_closed_subscriber) +# end-sdam-subscriber-global + +# start-sdam-subscriber-client +topology_opening_subscriber = TopologyOpeningLogSubscriber.new +server_opening_subscriber = ServerOpeningLogSubscriber.new +server_description_changed_subscriber = ServerDescriptionChangedLogSubscriber.new +topology_changed_subscriber = TopologyChangedLogSubscriber.new +server_closed_subscriber = ServerClosedLogSubscriber.new +topology_closed_subscriber = TopologyClosedLogSubscriber.new + +sdam_proc = Proc.new do |client| + client.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING, + topology_opening_subscriber) + client.subscribe(Mongo::Monitoring::SERVER_OPENING, + server_opening_subscriber) + client.subscribe(Mongo::Monitoring::SERVER_DESCRIPTION_CHANGED, + server_description_changed_subscriber) + client.subscribe(Mongo::Monitoring::TOPOLOGY_CHANGED, + topology_changed_subscriber) + client.subscribe(Mongo::Monitoring::SERVER_CLOSED, + server_closed_subscriber) + client.subscribe(Mongo::Monitoring::TOPOLOGY_CLOSED, + topology_closed_subscriber) +end + +client = Mongo::Client.new(['127.0.0.1:27017'], database: 'test', + sdam_proc: sdam_proc) +# end-sdam-subscriber-client + +# start-heartbeat +class HeartbeatLogSubscriber + include Mongo::Loggable + + def started(event) + log_debug("#{event.address} | STARTED") + end + + def succeeded(event) + log_debug("#{event.address} | SUCCEEDED | #{event.duration}s") + end + + def failed(event) + log_debug("#{event.address} | FAILED | #{event.error.class}: #{event.error.message} | #{event.duration}s") + end + + private + + def logger + Mongo::Logger.logger + end + + def format_message(message) + format("HEARTBEAT | %s", message) + end +end +# end-heartbeat + +# start-heartbeat-subscribe +subscriber = HeartbeatLogSubscriber.new + +# Globally subscribes to Server Opening events +Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber) + +# Subscribes to Server Opening events at the client level +client = Mongo::Client.new([ '127.0.0.1:27017' ], database: 'test' ) +client.subscribe( Mongo::Monitoring::SERVER_HEARTBEAT, subscriber ) +# end-heartbeat-subscribe diff --git a/source/index.txt b/source/index.txt index 4953b1a7..42770f30 100644 --- a/source/index.txt +++ b/source/index.txt @@ -18,6 +18,7 @@ Read Data Operations on Replica Sets Indexes + Monitor Your Application Data Aggregation Security Data Formats diff --git a/source/monitoring.txt b/source/monitoring.txt new file mode 100644 index 00000000..d13920e9 --- /dev/null +++ b/source/monitoring.txt @@ -0,0 +1,11 @@ +.. _ruby-monitoring: + +======================== +Monitor Your Application +======================== + +.. toctree:: + :caption: Monitoring categories + + Cluster Monitoring + \ No newline at end of file diff --git a/source/monitoring/cluster-monitoring.txt b/source/monitoring/cluster-monitoring.txt new file mode 100644 index 00000000..41b16d7a --- /dev/null +++ b/source/monitoring/cluster-monitoring.txt @@ -0,0 +1,250 @@ +.. _ruby-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 {+driver-short+} to monitor server discovery +and monitoring (SDAM) events in a MongoDB instance, replica set, or sharded +cluster by using custom subscribers or available subscriber methods. These events +occur when there are changes in the state of the MongoDB instance or cluster +that you are connected to. + +You can use information about SDAM events in your application to understand +cluster changes, assess cluster health, or perform capacity planning. + +SDAM Subscribers +---------------- + +You can use the {+driver-short+}'s ``subscribe`` method to subscribe to events. +Pass a monitoring topic, which defines the monitoring event type, and a subscriber +object as arguments to the ``subscribe`` method. + +The following code uses the ``ServerOpeningLogSubscriber`` subscriber to monitor a connection +to a server instance. You can subscribe to events at a global level, which monitors +all clients of a cluster, or at the client level: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-available-subscriber + :end-before: end-available-subscriber + :language: ruby + :copyable: + :dedent: + +The following table provides available subscribers and their monitoring topic: + +.. list-table:: + :header-rows: 1 + :widths: 35 20 45 + + * - Subscriber Name + - Monitoring Topic + - Description + + * - `ServerClosedLogSubscriber <{+api-root+}/Mongo/Monitoring/ServerClosedLogSubscriber.html>`__ + - ``SERVER_CLOSED`` + - Subscribes to ``ServerClosed`` events and logs them. + + * - `ServerDescriptionChangedLogSubscriber <{+api-root+}/Mongo/Monitoring/ServerDescriptionChangedLogSubscriber.html>`__ + - ``SERVER_DESCRIPTION_CHANGED`` + - Subscribes to ``ServerDescriptionChanged`` events and logs them. + + * - `ServerOpeningLogSubscriber <{+api-root+}/Mongo/Monitoring/ServerOpeningLogSubscriber.html>`__ + - ``SERVER_OPENING`` + - Subscribes to ``ServerOpening`` events and logs them. + + * - `TopologyChangedLogSubscriber <{+api-root+}/Mongo/Monitoring/TopologyChangedLogSubscriber.html>`__ + - ``TOPOLOGY_CHANGED`` + - Subscribes to ``TopologyChanged`` events and logs them. + + * - `TopologyClosedLogSubscriber <{+api-root+}/Mongo/Monitoring/TopologyClosedLogSubscriber.html>`__ + - ``TOPOLOGY_CLOSED`` + - Subscribes to ``TopologyClosed`` events and logs them. + + * - `TopologyOpeningLogSubscriber <{+api-root+}/Mongo/Monitoring/TopologyOpeningLogSubscriber.html>`__ + - ``TOPOLOGY_OPENING`` + - Subscribes to ``TopologyOpening`` events and logs them. + +You can find a table of SDAM event descriptions in the :ref:`Event Descriptions ` +section on this page. + +Custom SDAM Monitoring +---------------------- + +You can create a custom SDAM subscriber to access details about server +and topology events. Create a separate class for each event type, as available +data for each event varies. + +For all events, the subscriber calls the ``succeeded`` method and passes the event +as an argument. A simple SDAM logging subscriber can look +like the following code: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-sdam + :end-before: end-sdam + :language: ruby + :copyable: + :dedent: + +To subscribe to events, create the appropriate subscriber and +subscribe to the correct monitoring topic. The following code shows how +to subscribe to SDAM events globally: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-sdam-subscriber-global + :end-before: end-sdam-subscriber-global + :language: ruby + :copyable: + :dedent: + +The following code shows how to subscribe to SDAM events for a single client +by using the ``sdam-proc`` client option: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-sdam-subscriber-client + :end-before: end-sdam-subscriber-client + :language: ruby + :copyable: + :dedent: + +.. note:: + + The ``:sdam_proc`` client option applies only to the given client. + When certain client options are changed by using the + ``Client#with`` call, the driver may create a new cluster with + a default set of event subscribers. If this happens, the provided + ``:sdam_proc`` is not called, and the application may miss events. + +When you run the application, your subscriber records the SDAM event and +outputs messages such as the following: + +.. code-block:: none + :copyable: false + + D, [2018-10-09T13:58:03.489461 #22079] DEBUG -- : SDAM | Topology type 'Unknown' initializing. + D, [2018-10-09T13:58:03.489699 #22079] DEBUG -- : SDAM | Server 127.0.0.1:27100 initializing. + D, [2018-10-09T13:58:03.491384 #22079] DEBUG -- : SDAM | Server description for 127.0.0.1:27100 changed from 'unknown' to 'unknown'. + D, [2018-10-09T13:58:03.491642 #22079] DEBUG -- : SDAM | Server localhost:27100 initializing. + D, [2018-10-09T13:58:03.493199 #22079] DEBUG -- : SDAM | Server description for localhost:27100 changed from 'unknown' to 'primary'. + D, [2018-10-09T13:58:03.493473 #22079] DEBUG -- : SDAM | Server localhost:27101 initializing. + D, [2018-10-09T13:58:03.494874 #22079] DEBUG -- : SDAM | Server description for localhost:27101 changed from 'unknown' to 'secondary'. + D, [2018-10-09T13:58:03.495139 #22079] DEBUG -- : SDAM | Server localhost:27102 initializing. + D, [2018-10-09T13:58:03.496504 #22079] DEBUG -- : SDAM | Server description for localhost:27102 changed from 'unknown' to 'secondary'. + D, [2018-10-09T13:58:03.496777 #22079] DEBUG -- : SDAM | Topology type 'Unknown' changed to type 'ReplicaSetNoPrimary'. + D, [2018-10-09T13:58:03.497306 #22079] DEBUG -- : SDAM | Server 127.0.0.1:27100 connection closed. + D, [2018-10-09T13:58:03.497606 #22079] DEBUG -- : SDAM | Topology type 'ReplicaSetNoPrimary' changed to type 'ReplicaSetWithPrimary'. + + # client.close + + D, [2018-10-09T13:58:05.342057 #22079] DEBUG -- : SDAM | Server localhost:27100 connection closed. + D, [2018-10-09T13:58:05.342299 #22079] DEBUG -- : SDAM | Server localhost:27101 connection closed. + D, [2018-10-09T13:58:05.342565 #22079] DEBUG -- : SDAM | Server localhost:27102 connection closed. + D, [2018-10-09T13:58:05.342693 #22079] DEBUG -- : SDAM | Topology type 'ReplicaSetWithPrimary' closed. + +Server Heartbeats +~~~~~~~~~~~~~~~~~ + +You can also create a custom subscriber to monitor server heartbeats, which occur +when the server monitor sends a ``hello`` command to the server. + +Custom server heartbeat subscribers differ from other SDAM subscribers, +as they must implement the following three methods: + +- ``started``: Invoked when the listener receives the heartbeat +- ``succeeded``: Response for a successful heartbeat outcome +- ``failed``: Response for a failed heartbeat outcome + +The following example shows a heartbeat event subscriber: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-heartbeat + :end-before: end-heartbeat + :language: ruby + :copyable: + :dedent: + +You can subscribe to heartbeat events globally or for a specific client, +as shown in the following example: + +.. literalinclude:: /includes/monitoring/monitoring.rb + :start-after: start-heartbeat-subscribe + :end-before: end-heartbeat-subscribe + :language: ruby + :copyable: + :dedent: + +When you run the application, your subscriber records the heartbeat event and +outputs messages such as the following: + +.. code-block:: none + :copyable: false + + D, [2018-09-23T13:44:10.707018 #1739] DEBUG -- : HEARTBEAT | 127.0.0.1:27027 | STARTED + D, [2018-09-23T13:44:10.707778 #1739] DEBUG -- : HEARTBEAT | 127.0.0.1:27027 | SUCCEEDED | 0.000772381s + +.. _SDAM-event-descriptions: + +Event Descriptions +------------------ + +The following table provides the name and description of each SDAM event: + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Event Type + - Description + + * - `ServerClosed <{+api-root+}/Mongo/Monitoring/Event/ServerClosed.html>`__ + - Event created when the server instance is closed. + + * - `ServerDescriptionChanged <{+api-root+}/Mongo/Monitoring/Event/ServerDescriptionChanged.html>`__ + - Event created when a server's description changes. + + * - `ServerHeartbeatFailed <{+api-root+}/Mongo/Monitoring/Event/ServerHeartbeatFailed.html>`__ + - Event created when a server heartbeat fails. + + * - `ServerHeartbeatStarted <{+api-root+}/Mongo/Monitoring/Event/ServerHeartbeatStarted.html>`__ + - Event created when a server heartbeat is received by the listener. + + * - `ServerHeartbeatSucceeded <{+api-root+}/Mongo/Monitoring/Event/ServerHeartbeatSucceeded.html>`__ + - Event created when a server heartbeat succeeds. + + * - `ServerOpening <{+api-root+}/Mongo/Monitoring/Event/ServerOpening.html>`__ + - Event created when the driver connects to the server. + + * - `TopologyChanged <{+api-root+}/Mongo/Monitoring/Event/TopologyChanged.html>`__ + - Event created when the topology changes. + + * - `TopologyClosed <{+api-root+}/Mongo/Monitoring/Event/TopologyClosed.html>`__ + - Event created when all instance connections in the topology close. + + * - `TopologyOpening <{+api-root+}/Mongo/Monitoring/Event/TopologyOpening.html>`__ + - Event created before the driver attempts to connect to an instance. + +API Documentation +----------------- + +To learn more about any of the classes or methods discussed in this guide, see the +following API documentation: + +- `Mongo::Monitoring <{+api-root+}/Mongo/Monitoring.html>`__ +- `Mongo::Monitoring::Event <{+api-root+}/Mongo/Monitoring/Event.html>`__ +- `subscribe <{+api-root+}/Mongo/Monitoring/Subscribable.html#subscribe-instance_method>`__