Overview
In this guide, you can learn how to use the Scala driver to monitor events that occur during driver operation. Monitoring involves collecting information about the activities of a running program, which you can use with an application or an application performance management library.
You can monitor application events to understand the driver's resource usage and performance, which helps you make informed decisions when designing and debugging your application.
The Scala driver organizes the events you can monitor into the following categories:
Command events: Events related to MongoDB database commands
Server Discovery and Monitoring (SDAM) events: Events related to changes in the state of the MongoDB instance or cluster you are connected to
Connection pool events: Events related to the connection pool the driver maintains with a MongoDB instance
The following sections describe each event category and show how to monitor events. To learn how to record driver events to a log, see the Logging guide.
Monitor Command Events
A command event is an event related to a MongoDB database command. Examples of database commands that produce command events include find, insert, delete, and count.
The Scala driver does not publish events for commands it calls internally. This includes commands the driver uses to monitor your cluster and commands related to connection establishment, such as the initial hello command.
To monitor command events, create a class that implements the CommandListener interface and register an instance of that class with your MongoClient instance.
Important
Redacted Output
As a security measure, the driver redacts the contents of some command events to protect sensitive information. For a full list of redacted command events, see the Security section of the MongoDB Command Logging and Monitoring specification.
To learn more about MongoDB database commands, see Database Commands.
Example
The following example defines the CommandCounter class, which implements the CommandListener interface. The class tracks the number of times the driver successfully executes each database command and prints this information each time a command finishes.
case class CommandCounter() extends CommandListener { private val commands = scala.collection.mutable.Map[String, Int]() override def commandStarted(event: CommandStartedEvent): Unit = {} override def commandSucceeded( event: CommandSucceededEvent ): Unit = { val commandName = event.getCommandName commands(commandName) = commands.getOrElse(commandName, 0) + 1 println(commands.toMap) } override def commandFailed(event: CommandFailedEvent): Unit = {} }
The following code adds an instance of the CommandCounter class to a MongoClientSettings object and configures a MongoClient instance by using the settings:
val settings: MongoClientSettings = MongoClientSettings .builder() .addCommandListener(CommandCounter()) .applyConnectionString(ConnectionString("<connection string>")) .build() val mongoClient: MongoClient = MongoClient(settings)
When you run the application, the output resembles the following:
Map(find -> 1) Map(find -> 2) Map(find -> 2, endSessions -> 1)
Event Descriptions
The following table describes the command events that the Scala driver publishes and the listener interface that handles them:
Event Type | Listener Interface | Description |
|---|---|---|
Published when a database command starts. | ||
Published when a database command succeeds. | ||
Published when a database command fails. |
Monitor SDAM Events
A server discovery and monitoring (SDAM) event is an event related to a change in the state of the MongoDB instance or cluster you are connected to.
The Scala driver defines nine SDAM events and provides the following listener interfaces, which each listen for three SDAM events:
ClusterListener: Listens for events related to topology changes, or changes in the state and structure of the clusterServerListener: Listens for events related to individual server changesServerMonitorListener: Listens for heartbeat events, which report on the status of communication between replica set members
You can use information from SDAM events to understand cluster changes, assess cluster health, or plan capacity.
Example
The following example defines the TestClusterListener class, which implements the ClusterListener interface. The class contains methods that print messages in response to the following topology-related events:
clusterOpening(): Prints a message when the driver first connects to a clusterclusterClosed(): Prints a message when the driver disconnects from a clusterclusterDescriptionChanged(): Prints a message about changes to the read and write availability of the cluster
case class TestClusterListener(readPreference: ReadPreference) extends ClusterListener { var isWritable: Boolean = false var isReadable: Boolean = false override def clusterOpening(event: ClusterOpeningEvent): Unit = println(s"Cluster with ID ${event.getClusterId} opening") override def clusterClosed(event: ClusterClosedEvent): Unit = println(s"Cluster with ID ${event.getClusterId} closed") override def clusterDescriptionChanged(event: ClusterDescriptionChangedEvent): Unit = { if (!isWritable) { if (event.getNewDescription.hasWritableServer) { isWritable = true println("Writable server available") } } else { if (!event.getNewDescription.hasWritableServer) { isWritable = false println("No writable server available") } } if (!isReadable) { if (event.getNewDescription.hasReadableServer(readPreference)) { isReadable = true println("Readable server available") } } else { if (!event.getNewDescription.hasReadableServer(readPreference)) { isReadable = false println("No readable server available") } } } }
The following code adds an instance of the TestClusterListener class to a MongoClientSettings object and configures a MongoClient instance by using the settings:
val uri: ConnectionString = ConnectionString("<connection string>") val settings: MongoClientSettings = MongoClientSettings .builder() .applyToClusterSettings((builder: ClusterSettings.Builder) => builder.addClusterListener(TestClusterListener(ReadPreference.secondary()))) .applyConnectionString(uri) .build() val client: MongoClient = MongoClient(settings)
When you run the application, the output resembles the following:
Cluster with ID ClusterId{value='...', description='...'} opening Writable server available Readable server available Cluster with ID ClusterId{value='...', description='...'} closed
Event Descriptions
The following table describes each SDAM event, the listener interface that handles it, and when the driver publishes it:
Event Type | Listener Interface | Description |
|---|---|---|
Published when the topology description changes, such as when there is an election of a new primary. | ||
Published when the driver first connects to the cluster. | ||
Published when the driver disconnects from the cluster. | ||
Published when the server description changes. | ||
Published when a new server is added to the topology. | ||
Published when an existing server is removed from the topology. | ||
Published when the server monitor sends a | ||
Published when the heartbeat succeeds. | ||
Published when the heartbeat fails. |
Monitor Connection Pool Events
A connection pool event is an event related to the connection pool the driver maintains with a MongoDB instance. A connection pool is a set of open TCP connections your driver maintains with a MongoDB instance. Connection pools reduce the number of network handshakes your application needs to perform and can help your application run faster.
To monitor connection pool events, create a class that implements the ConnectionPoolListener interface and register an instance of that class with your MongoClient instance.
Example
The following example defines the ConnectionPoolLibrarian class, which implements the ConnectionPoolListener interface. The class prints a message each time the driver checks out a connection from the connection pool.
case class ConnectionPoolLibrarian() extends ConnectionPoolListener { override def connectionCheckedOut( event: ConnectionCheckedOutEvent ): Unit = println( s"Let me get you the connection with id " + s"${event.getConnectionId.getLocalValue}..." ) override def connectionCheckOutFailed( event: ConnectionCheckOutFailedEvent ): Unit = {} }
The following code adds an instance of the ConnectionPoolLibrarian class to a MongoClientSettings object and configures a MongoClient instance by using the settings:
val settings: MongoClientSettings = MongoClientSettings .builder() .applyToConnectionPoolSettings( (builder: ConnectionPoolSettings.Builder) => builder.addConnectionPoolListener( ConnectionPoolLibrarian() ) ) .applyConnectionString(ConnectionString("<connection string>")) .build() val mongoClient: MongoClient = MongoClient(settings)
When you run the application, the output resembles the following:
Let me get you the connection with id 1...
Event Descriptions
The following table describes the connection pool events that the Scala driver publishes and the listener interface that handles them:
Event Type | Listener Interface | Description |
|---|---|---|
Published when the connection pool is created. | ||
Published when the connection pool is ready for use. | ||
Published when the connection pool is closed. | ||
Published when a connection is created in the pool. | ||
Published when a connection completes its handshake and is ready for use. | ||
Published when a connection is closed. | ||
Published when the driver starts to check out a connection. | ||
Published when the driver successfully checks out a connection. | ||
Published when the driver fails to check out a connection. | ||
Published when the driver checks a connection back into the pool. | ||
Published when the connection pool is cleared. |
API Documentation
To learn more about the methods and types discussed in this guide, see the following API documentation: