Docs Menu
Docs Home
/ / /
Go Driver
/

Logging

On this page

  • Overview
  • Enable Logging
  • Configure a Logger
  • Log Components and Severity Levels
  • Example
  • Use a Custom Logger
  • Example
  • Integrate Third-Party Loggers
  • Example
  • Additional Information
  • API Documentation

In this guide, you can learn how to use the driver to configure logging for your application. The purpose of logging is to record driver events.

A logger logs messages at a severity, or verbosity, level that you can specify. By enabling a logger in your application, you can receive information about your application's activities at a high level, a detailed level, or somewhere in between.

Tip

To learn more about logging severity levels, see the Wikipedia entry on the Syslog standard for message logging.

To configure a logger on your Client instance, call the SetLoggerOptions() method when creating your ClientOptions object. The SetLoggerOptions() method takes a LoggerOptions type as a parameter. Set this LoggerOptions type to configure the logger for your application.

The following code shows how to create a client with logging enabled:

loggerOptions := options.
Logger().
SetComponentLevel(options.LogComponentCommand, options.LogLevelDebug)
clientOptions := options.
Client().
ApplyURI(uri).
SetLoggerOptions(loggerOptions)
client, err := mongo.Connect(context.TODO(), clientOptions)

To create a LoggerOptions object, call the options.Logger() method. The following table describes how to set properties on a LoggerOptions type to configure your logger. The first column lists the LoggerOptions properties, the second column describes the properties, and the third column lists the corresponding setter method and parameters for each property:

Property
Description
Setter Method
ComponentLevels

Type: map[LogComponent]LogLevel
A mapping of components to log severity levels. The driver uses the LogLevel for each LogComponent to determine if the log message is generated.

To learn more about the LogComponent and LogLevel types, see the Log Components and Severity Levels section of this guide.
SetComponentLevel()

Parameters: LogComponent, LogLevel
Sink

Type: LogSink
The logging interface that the driver uses to log messages. The LogSink type is an interface that you can implement to provide a custom sink or integrate a third-party logger for the driver's logs. If you don't set this property, the driver uses the standard logging library.

To learn more, see the Use a Custom Logger and Integrate Third-Party Loggers sections of this guide.
SetSink()

Parameter: LogSink
MaxDocumentLength

Type: uint
Default: 1000
The maximum length in bytes of each log message that the driver emits. If the message is larger than this value, the driver truncates it and appends ellipses to the partial log message.
SetMaxDocumentLength()

Parameter: uint

Tip

Write Logs to a Specific File

By default, the standard logger logs messages to your console (stderr). You can specify a logging destination by setting the MONGODB_LOG_PATH environment variable to stdout or a filepath.

To specify the components that the driver logs against, set the LogComponent type. The following table describes built-in specifications for LogComponent:

Setting
Description
Enumeration Value
LogComponentAll
Enables logging for all components
0
LogComponentCommand
Enables command monitor logging
1
LogComponentTopology
Enables topology logging
2
LogComponentServerSelection
Enables server selection logging
3
LogComponentConnection
Enables connection services logging
4

You can specify the log component by using either the setting name or its enumeration value. The following code shows equivalent ways of enabling command monitoring:

// Using named value
comp := options.LogComponentCommand
// Using enumeration
comp := options.LogComponent(1)

To specify the log severity level, set the LogLevel type. The following code shows how to enable logging at the LevelDebug level:

lvl := options.LogLevelDebug

Important

The Go driver currently emits only LevelDebug level messages, but it supports other specifications for LogLevel. To learn more, see the LogLevel API documentation.

This example shows how to configure the standard logger with the following specifications:

  • The maximum document length is 25 bytes.

  • The log component is LogComponentCommand.

  • The logging severity level is LevelDebug.

loggerOptions := options.
Logger().
SetMaxDocumentLength(25).
SetComponentLevel(options.LogComponentCommand, options.LogLevelDebug)
// Creates options that include the logger specification
clientOptions := options.
Client().
ApplyURI(uri).
SetLoggerOptions(loggerOptions)

The following code performs an insert operation, which generates log messages:

type Item struct {
Name string
}
coll := client.Database("db").Collection("testColl")
_, err = coll.InsertOne(context.TODO(), Item{Name: "grapefruit"})
{"command":"{\"insert\": \"testColl\",\"or...","commandName":"insert","databaseName":"db","driverConnectionId":1,"message":"Command started","operationId":0,"requestId":13,"serverConnectionId":97377,"serverHost":"...","serverPort":27017,"timestamp":...}
{"commandName":"insert","driverConnectionId":1,"durationMS":19,"message":"Command succeeded","operationId":0,"reply":"{\"n\": {\"$numberInt\":\"1\"},...","requestId":13,"serverConnectionId":97377,"serverHost":"...","serverPort":27017,"timestamp":...}

If the standard logging library does not meet your needs, you can implement a custom logger. By customizing your logging configuration, you have more control over the content, format, and frequency of log messages.

To use a custom logger, define a logger struct and implement the Info() and Error() methods for the struct. Next, set the logger as the LogSink for your Client by calling the SetSink() method on your LoggerOptions instance.

This example demonstrates how to define and implement a custom logger.

1
type CustomLogger struct {
io.Writer
mu sync.Mutex
}

Note

The preceding code example uses a Mutex type in the CustomLogger struct to ensure atomic writes and prevent race conditions. Setting a Mutex makes your logger safe for concurrent use by multiple goroutines.

2
func (logger *CustomLogger) Info(level int, msg string, _ ...interface{}) {
logger.mu.Lock()
defer logger.mu.Unlock()
if options.LogLevel(level+1) == options.LogLevelDebug {
fmt.Fprintf(logger, "level: %d DEBUG, message: %s\n", level, msg)
} else {
fmt.Fprintf(logger, "level: %d INFO, message: %s\n", level, msg)
}
}
func (logger *CustomLogger) Error(err error, msg string, _ ...interface{}) {
logger.mu.Lock()
defer logger.mu.Unlock()
fmt.Fprintf(logger, "error: %v, message: %s\n", err, msg)
}
3

In this example, the logger logs commands and connection events at the LevelDebug level:

buf := bytes.NewBuffer(nil)
sink := &CustomLogger{Writer: buf}
loggerOptions := options.
Logger().
SetSink(sink).
SetComponentLevel(options.LogComponentCommand, options.LogLevelDebug).
SetComponentLevel(options.LogComponentConnection, options.LogLevelDebug)
// Creates options that include the logger specification
clientOptions := options.
Client().
ApplyURI(uri).
SetLoggerOptions(loggerOptions)
4

The following code performs an insert operation, which generates log messages:

type Item struct {
Name string
}
coll := client.Database("db").Collection("testColl")
_, err = coll.InsertOne(context.TODO(), Item{Name: "grapefruit"})
level: 1 DEBUG, message: Connection pool created
level: 1 DEBUG, message: Connection pool ready
level: 1 DEBUG, message: Connection pool created
level: 1 DEBUG, message: Connection pool ready
level: 1 DEBUG, message: Connection pool created
level: 1 DEBUG, message: Connection pool ready
level: 1 DEBUG, message: Connection checkout started
level: 1 DEBUG, message: Connection created
level: 1 DEBUG, message: Connection ready
level: 1 DEBUG, message: Connection checked out
level: 1 DEBUG, message: Command started
level: 1 DEBUG, message: Command succeeded
level: 1 DEBUG, message: Connection checked in

There are many third-party logging packages available in Go. To use a third-party logger in your application, create a logger and assign it as the sink in your LoggerOptions instance.

This example demonstrates how to integrate logrus, a third-party logging package, into your application.

1

Run the following go get commands in your terminal to download the logrus packages required for this example:

go get github.com/bombsimon/logrusr/v4
go get github.com/sirupsen/logrus
2

The following code creates a logrus logger with these specifications:

  • The logger logs messages to the console.

  • The logger logs messages at the DebugLevel level.

  • The logger formats messages using the JSONFormatter formatter.

myLogger := &logrus.Logger{
Out: os.Stderr,
Level: logrus.DebugLevel,
Formatter: &logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
PrettyPrint: true,
},
}
3

In the following code example, the logger is configured to log commands at the LevelDebug level.

sink := logrusr.New(myLogger).GetSink()
// Sets options when configuring the logrus logger
loggerOptions := options.
Logger().
SetSink(sink).
SetComponentLevel(options.LogComponentCommand, options.LogLevelDebug)
// Creates options that include the logger specification
clientOptions := options.
Client().
ApplyURI(uri).
SetLoggerOptions(loggerOptions)
4

The following code performs some CRUD operations, which generate log messages:

type Item struct {
Name string
}
coll := client.Database("db").Collection("testColl")
docs := []interface{}{
Item{Name: "starfruit"},
Item{Name: "kiwi"},
Item{Name: "cantaloupe"},
}
_, err = coll.InsertMany(context.TODO(), docs)
if err != nil {
panic(err)
}
_, err = coll.DeleteOne(context.TODO(), Item{Name: "kiwi"})
if err != nil {
panic(err)
}
{
"command": "{\"insert\": \"testColl\", ...}",
"commandName": "insert",
"databaseName": "db",
...
"level": "debug",
"message": "Command started",
"msg": "Command started",
...
"time": "2023-07-06 10:23:42"
}
{
"commandName": "insert",
...
"level": "debug",
"message": "Command succeeded",
"msg": "Command succeeded",
...
"time": "2023-07-06 10:23:42"
}
{
"command": "{\"delete\": \"testColl\", ...}",
"commandName": "delete",
"databaseName": "db",
...
"level": "debug",
"message": "Command started",
"msg": "Command started",
...
"time": "2023-07-06 10:23:42"
}
{
"commandName": "delete",
...
"level": "debug",
"message": "Command succeeded",
"msg": "Command succeeded",
...
"time": "2023-07-06 10:23:42"
}

Tip

Logging Packages

You can find more information on third-party logging packages in their respective GitHub repositories:

To see full code examples that integrate these loggers, see the logging tests in the Go driver Github repository.

For more information about setting client options, see the Connection Guide.

Tip

Monitoring

In addition to logging, you can enable server selection and topology monitoring in your application. To learn more, see the Monitoring Fundamentals guide.

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

Back

Transactions