Docs Menu
Docs Home
/ / /
Ruby Driver
/

Monitor Application Events

In this guide, you can learn how to set up and configure monitoring in the MongoDB Ruby Driver.

Monitoring involves collecting information about the activities of a running program, which you can use with an application performance management library.

Monitoring the Ruby driver lets you understand the driver's resource usage and performance. This information can help you make informed decisions when designing and debugging your application.

In this guide, you can learn how to perform the following tasks:

  • Monitor Command Events

  • Monitor Server Discovery and Monitoring (SDAM) Events

  • Monitor Connection Pool Events

This guide shows how to use information about the activity of the driver in code. To learn how to record events in the driver, see the Ruby driver's Logging guide.

A command event is an event related to a MongoDB database command. You can access one or more command monitoring events using the driver by subscribing to them in your application.

To learn more about MongoDB database commands, see the Database Commands guide in the MongoDB Server manual.

You can access details about command events by subscribing to them in your application. You can subscribe to events at a global level, which monitors all clients of a cluster, or at the client level. This example demonstrates the following actions:

  • Instantiates a CommandLogSubscriber

  • Uses the Mongo::Monitoring::Global.subscribe method to subscribe to command events at the global level

  • Uses the Mongo::Client.subscribe method to subscribe to command events at the client level

require 'mongo'
# Creates a subscriber for command monitoring
subscriber = Mongo::Monitoring::CommandLogSubscriber.new
# Globally subscribes to command monitoring events
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::COMMAND, subscriber)
# Replace with your connection string and connect to your client
uri = '<connection string>'
client = Mongo::Client.new(uri)
# Subscribes to command monitoring events at the client level
client.subscribe( Mongo::Monitoring::COMMAND, subscriber)

You can subscribe to any of the following command monitoring events:

Event Name
Description

Created when a command is started.

Created when a command succeeded.

Created when a command failed.

The Ruby driver creates topology events, also known as SDAM events, when there is a change in the state of the instance or cluster that you connected to. For example, the driver creates an event when you establish a new connection or if the cluster elects a new primary node.

To learn more about topology events, see the Replication guide in the Server Manual.

The following sections demonstrate how to record topology changes in your application and explore the information provided in these events.

You can use the Ruby driver'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. You can subscribe to events at a global level, which monitors all clients of a cluster, or at the client level.

This example demonstrates the following actions:

  • Instantiates a ServerOpeningLogSubscriber subscriber

  • Uses the Mongo::Monitoring::Global.subscribe method to subscribe to ServerOpening events at the global level

  • Uses the Mongo::Client.subscribe method to subscribe to ServerOpening events at the client level

require 'mongo'
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)
# Replace with your connection string and connect to your client
uri = '<connection string>'
client = Mongo::Client.new(uri)
# Subscribes to ServerOpening events at the client level by using the SERVER_OPENING monitoring topic
client.subscribe(Mongo::Monitoring::SERVER_OPENING, subscriber)

The following table provides available subscribers and their monitoring topic:

Subscriber Name
Monitoring Topic
Description

SERVER_CLOSED

Subscribes to ServerClosed events and logs them.

SERVER_DESCRIPTION_CHANGED

Subscribes to ServerDescriptionChanged events and logs them.

SERVER_OPENING

Subscribes to ServerOpening events and logs them.

TOPOLOGY_CHANGED

Subscribes to TopologyChanged events and logs them.

TOPOLOGY_CLOSED

Subscribes to TopologyClosed events and logs them.

TOPOLOGY_OPENING

Subscribes to TopologyOpening events and logs them.

You can find a table of SDAM event descriptions in the Event Descriptions section on this page.

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:

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

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:

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)

The following code shows how to subscribe to SDAM events for a single client by using the sdam-proc client option:

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)

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:

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.

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:

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

You can subscribe to heartbeat events globally or for a specific client, as shown in the following example:

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 )

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

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

The following table provides the name and description of each SDAM event:

Event Type
Description

Event created when the server instance is closed.

Event created when a server's description changes.

Event created when a server heartbeat fails.

Event created when a server heartbeat is received by the listener.

Event created when a server heartbeat succeeds.

Event created when the driver connects to the server.

Event created when the topology changes.

Event created when all instance connections in the topology close.

Event created before the driver attempts to connect to an instance.

A connection pool is a set of open TCP connections your driver maintains with a MongoDB instance. Connection pools help reduce the number of network handshakes your application needs to perform and can help your application run faster.

The following sections demonstrate how to record connection pool events in your application and explore the information provided in these events.

You can access details about all connection pool events by subscribing to them in your application. You can subscribe to events at a global level, which monitors all clients of a cluster, or at the client level:

This example demonstrates the following actions:

  • Instantiates a CmapLogSubscriber subscriber

  • Uses the Mongo::Monitoring::Global.subscribe method to subscribe to all connection pool events at the global level

  • Uses the Mongo::Client.subscribe method to subscribe to all connection pool events at the client level

require 'mongo'
# Creates a subscriber for connection pool monitoring
subscriber = Mongo::Monitoring::CmapLogSubscriber.new
# Globally subscribes to connection pool monitoring events
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)
# Replace with your connection string and connect to your client
uri = '<connection string>'
client = Mongo::Client.new(uri)
# Subscribes to connection pool monitoring events at the client level
client.subscribe(Mongo::Monitoring::CONNECTION_POOL, subscriber)

You can subscribe to any of the following connection pool monitoring events:

Event Name
Description

Created when an operation fails to acquire a connection for execution.

Created when an operation attempts to acquire a connection for execution.

Created when a connection is checked back into the pool after an operation is executed.

Created when an operation successfully acquires a connection for execution.

Created when a connection is closed.

Created when a connection is created, but not necessarily when it is used for an operation.

Created after a connection has successfully completed a handshake and is ready to be used for operations.

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

Back

Atlas Vector Search

On this page