Monitoring
On this page
Overview
In this guide, you can learn how to set up and configure monitoring in the MongoDB Kotlin driver.
Monitoring is the process of getting information about the activities a running program performs for use in an application or an application performance management library.
Monitoring the MongoDB Kotlin driver lets you understand the driver's resource usage and performance, and can help you make informed decisions when designing and debugging your application.
In this guide you will learn how to perform these tasks:
Monitor different types of events in the MongoDB Kotlin driver
Monitor connection pool events with Java Management Extensions (JMX) and JConsole
This guide shows how to use information about the activity of the driver in code. If you would like to learn how to record events in the driver, consider reading our guide on logging.
Monitor Events
To monitor an event, you must register a listener on your MongoClient
instance.
An event is any action that happens in a running program. The driver includes functionality for listening to a subset of the events that occur when the driver is running.
A listener is a class that performs some action when certain events occur. A listener's API defines the events it can respond to.
Each method of a listener class represents a response to a certain event. Each method receives one argument: an object representing the event the method responds to.
The MongoDB Kotlin driver organizes the events it defines into three categories:
Command Events
Server Discovery and Monitoring Events
Connection Pool Events
The following sections show how to monitor each event category.
For a full list of the events you can monitor, see the event package of the MongoDB Kotlin driver.
Command Events
A command event is an event related to a MongoDB database command. Some
examples of database commands that produce command events are find
,
insert
, delete
, and count
.
To monitor command events, write a class that implements the
CommandListener
interface and register an instance of that class with your
MongoClient
instance.
For more information on MongoDB database commands, see the MongoDB manual entry on database commands.
Note
Internal Commands
The driver does not publish events for commands it calls internally. This
includes database commands the driver uses to monitor your cluster and
commands related to connection establishment (such as the initial hello
command).
Important
Redacted Output
As a security measure, the driver redacts the contents of some command events. This protects the sensitive information contained in these command events. For a full list of redacted command events, see the MongoDB command logging and monitoring specification.
Example
This example shows how to make a counter for database commands. The counter keeps track of the number of times the driver successfully executes each database command, and prints this information every time a database command finishes.
To make a counter, do the following:
Make a class with counter functionality that implements the
CommandListener
interface.Add an instance of the new class that implements
CommandListener
to aMongoClientSettings
object.Configure a
MongoClient
instance with theMongoClientSettings
object.
The following code defines the CommandCounter
class which implements the
CommandListener
interface:
class CommandCounter : CommandListener { private val commands = mutableMapOf<String, Int>() override fun commandSucceeded(event: CommandSucceededEvent) { val commandName = event.commandName val count = commands[commandName] ?: 0 commands[commandName] = count + 1 println(commands.toString()) } override fun commandFailed(event: CommandFailedEvent) { println("Failed execution of command '${event.commandName}' with id ${event.requestId}") } }
The following code adds an instance of the CommandCounter
class to a
MongoClientSettings
object, and configures a MongoClient
instance with the
MongoClientSettings
object. The code then runs some database commands to test the
counter.
val commandCounter = CommandCounter() val settings = MongoClientSettings.builder() .applyConnectionString(URI) .addCommandListener(commandCounter) .build() val mongoClient = MongoClient.create(settings) val database = mongoClient.getDatabase(DATABASE) val collection = database.getCollection<Document>(COLLECTION) // Run some commands to test the counter collection.find().firstOrNull() collection.find().firstOrNull()
{find=1} {find=2} {find=2, endSessions=1}
For more information on the classes and methods mentioned in this section, see the following API Documentation:
Server Discovery and Monitoring 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 have connected the driver to.
The driver defines nine SDAM events. The driver divides these nine events between three separate listener interfaces which each listen for three of the nine events. Here are the three interfaces and the events they listen for:
ClusterListener
: topology-related eventsServerListener
: events related tomongod
ormongos
processesServerMonitorListener
: heartbeat related events
To monitor a type of SDAM event, write a class that
implements one of the three preceding interfaces and register an instance of that
class with your MongoClient
instance.
For a detailed description of each SDAM event, see the MongoDB SDAM monitoring events specification.
Example
This example shows how to make a listener class that prints a message that lets you know if the driver can write to your MongoDB instance.
The following code defines the IsWritable
class which implements the
ClusterListener
interface.
class IsWriteable : ClusterListener { private var isWritable = false override fun clusterDescriptionChanged(event: ClusterDescriptionChangedEvent) { if (!isWritable) { if (event.newDescription.hasWritableServer()) { isWritable = true println("Able to write to cluster") } } else { if (!event.newDescription.hasWritableServer()) { isWritable = false println("Unable to write to cluster") } } } }
The following code adds an instance of the IsWritable
class to a
MongoClient
object. The code then runs a find operation to test the
IsWritable
class.
val clusterListener = IsWriteable() val settings = MongoClientSettings.builder() .applyConnectionString(URI) .applyToClusterSettings { builder -> builder.addClusterListener(clusterListener) } .build() val mongoClient = MongoClient.create(settings) val database = mongoClient.getDatabase(DATABASE) val collection = database.getCollection<Document>(COLLECTION) // Run a command to trigger a ClusterDescriptionChangedEvent event collection.find().firstOrNull()
Able to write to server
For more information on the classes and methods mentioned in this section, see the following API Documentation:
Connection Pool Events
A connection pool event is an event related to a connection pool held by the driver. 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 with a MongoDB instance, and can help your application run faster.
To monitor connection pool events, write a class that implements the
ConnectionPoolListener
interface and register an instance of that class with your
MongoClient
instance.
Example
This example shows how to make a listener class that prints a message each time you check out a connection from your connection pool.
The following code defines the ConnectionPoolLibrarian
class which implements the
ConnectionPoolListener
interface.
class ConnectionPoolLibrarian : ConnectionPoolListener { override fun connectionCheckedOut(event: ConnectionCheckedOutEvent) { println("Let me get you the connection with id ${event.connectionId.localValue}...") } override fun connectionCheckOutFailed(event: ConnectionCheckOutFailedEvent) { println("Something went wrong! Failed to checkout connection.") } }
The following code adds an instance of the ConnectionPoolLibrarian
class to a
MongoClient
object. The code then runs a database command to test the
librarian.
val cpListener = ConnectionPoolLibrarian() val settings = MongoClientSettings.builder() .applyConnectionString(URI) .applyToConnectionPoolSettings { builder -> builder.addConnectionPoolListener(cpListener) } .build() val mongoClient = MongoClient.create(settings) val database = mongoClient.getDatabase(DATABASE) val collection = database.getCollection<Document>(COLLECTION) // Run a command to trigger connection pool events collection.find().firstOrNull()
Let me get you the connection with id 21...
For more information on the classes and methods mentioned in this section, see the following API Documentation:
Monitor Connection Pool Events with JMX
You can monitor connection pool events using Java Management Extensions (JMX). JMX provides tools to monitor applications and devices.
For more information on JMX, see the official Oracle JMX documentation.
JMX Support
To enable JMX connection pool monitoring, add an instance of the
JMXConnectionPoolListener
class to your MongoClient
object.
The JMXConnectionPoolListener
class performs the following actions:
Creates MXBean instances for each
mongod
ormongos
process the driver maintains a connection pool with.Registers these MXBean instances with the platform MBean server.
MXBeans registered on the platform MBean server have the following properties:
Property | Description |
---|---|
clusterId | A client-generated unique identifier. This identifier ensures that
each MXBean the driver makes has a unique name when an application has
multiple MongoClient instances connected to the same MongoDB deployment. |
host | The hostname of the machine running the mongod or mongos process. |
port | The port on which the mongod or mongos process is listening. |
minSize | The minimum size of the connection pool, including idle and in-use connections. |
maxSize | The maximum size of the connection pool, including idle and in-use connections. |
size | The current size of the connection pool, including idle and in-use connections. |
checkedOutCount | The current count of connections that are in use. |
All MXBean instances created by the driver are under the domain
"org.mongodb.driver"
.
For more information on the topics discussed in this subsection, see the following resources from Oracle:
JMX and JConsole Example
This example shows how you can monitor the driver's connection pools using JMX and JConsole. JConsole is a JMX compliant GUI monitoring tool that comes with the Java Platform.
Tip
Consult the Official JMX and JConsole Documentation
The descriptions of JMX and JConsole in this example are illustrative rather than a source of truth. For guaranteed up to date information, consult the following official Oracle resources:
The following code snippet adds a JMXConnectionPoolListener
to a
MongoClient
instance. The code then pauses execution so you can
navigate to JConsole and inspect your connection pools.
val connectionPoolListener = JMXConnectionPoolListener() val settings = MongoClientSettings.builder() .applyConnectionString(uri) .applyToConnectionPoolSettings { it.addConnectionPoolListener(connectionPoolListener) } .build() val mongoClient: MongoClient = MongoClient.create(settings) try { println("Navigate to JConsole to see your connection pools...") Thread.sleep(Long.MAX_VALUE) } catch (e: Exception) { e.printStackTrace() }
Navigate to JConsole to see your connection pools...
Once you have started your server, open JConsole in your terminal using the following command:
jconsole
Once JConsole is open, perform the following actions in the GUI:
Select the process running the preceding example code.
Press Insecure Connection in the warning dialog box.
Click on the MBeans tab.
Inspect your connection pool events under the
"org.mongodb.driver"
domain.
When you no longer want to inspect your connection pools in JConsole, do the following:
Exit JConsole by closing the JConsole window
Stop the program running the preceding code snippet
For more information on JMX and JConsole, see the following resources from Oracle:
For more information on the JMXConnectionPoolListener
class, see
the API Documentation for
JMXConnectionPoolListener.
Include the Driver in Your Distributed Tracing System
If you use a distributed tracing system, you can include event data from the driver. A distributed tracing system is an application that tracks requests as they propagate throughout different services in a service-oriented architecture.
If you use the driver in a Spring Cloud application, use Spring Cloud Sleuth to include MongoDB event data in the Zipkin distributed tracing system.
If you do not use Spring Cloud or need to include driver event data in a distributed tracing system other than Zipkin, you must write a command event listener that manages spans for your desired distributed tracing system. To see an implementation of such a listener, see the Java source code for the TraceMongoCommandListener class in the Spring Cloud Sleuth source code.
To learn more about Spring Cloud Sleuth, see Getting Started in the Spring Cloud Sleuth documentation.
To view a detailed description of a distributed tracing system, see Dapper from Google Research.