One way to debug an application is through logs. They can be used to identify issues, understand the execution flow, and also monitor the application’s behavior. Among their types, database query logs are very useful for understanding what is happening with queries and other write operations. In this post, I will show how to enable MongoDB query logs in the official Go driver.

By default, logs in the official MongoDB driver for Go are disabled. To enable them, you just need to implement your own CommandMonitor and set it in the ClientOptions configuration.

Whenever I work with database connections, I like to create a struct that holds the necessary connection information. In this case, I’ll create a struct called MongoConfig.

type MongoConfig struct {
	URL       string       // MongoDB connection URL
	AppName   string       // Application name
	DebugMode bool         // Flag to enable debug logs
	Log       slog.Logger  // Logger to be used
}

After that, I implement a createMongoClient function that takes this configuration struct and returns a *mongo.Client. The advantage of passing configurations via a struct is that if you want to add other parameters like ConnectionTimeout or MaxPoolSize, for example, you don’t need to change the function’s signature.

func createMongoClient(cfg MongoConfig) (*mongo.Client, error) {
	clientOptions := options.Client().ApplyURI(cfg.URL)
	clientOptions.SetAppName(cfg.AppName)

	if cfg.DebugMode { // Verifico se a flag de debug está habilitada
		monitor := &event.CommandMonitor{
			Started: func(_ context.Context, e *event.CommandStartedEvent) {
				if e.CommandName != "endSessions" { // Ignoro os comandos de finalização de sessão
					cfg.Log.Info(e.Command.String())
				}
			},
		}

		clientOptions.SetMonitor(monitor)
	}

	client, err := mongo.Connect(context.Background(), clientOptions)
	if err != nil {
		return nil, err
	}

	return client, nil
}

Afterward, I use the function to create the MongoDB client and perform operations in my application.

mongoCfg := MongoConfig{
		URL:       "mongodb://localhost:27017",
		AppName:   "MongoDB with query log",
		DebugMode: true,
		Log:       *slog.Default(),
	}

	client, err := createMongoClient(mongoCfg)
	if err != nil {
		log.Fatal(err)
	}

Examples of logs for some operations:

PING
2023/09/02 08:48:09 INFO {"ping": {"$numberInt":"1"},"lsid": {"id": {"$binary":{"base64":"HBu0mDZaRHaNx0TPpBcaeg==","subType":"04"}}},"$db": "admin"}

INSERT
2023/09/02 09:04:43 INFO {"insert": "users","ordered": true,"lsid": {"id": {"$binary":{"base64":"ZIZW5N5OR+ympGFggFu6uA==","subType":"04"}}},"$db": "example-mongo","documents": [{"_id": {"$oid":"64f324db99a1dac5fdc37251"},"name": "Eduardo","alias": "eduardohitek","site": "https://eduardohitek.dev"}]}

FIND
2023/09/02 09:05:59 INFO {"find": "users","filter": {"alias": "eduardohitek"},"lsid": {"id": {"$binary":{"base64":"+ji9+sJIRVC0HsawBmTAPw==","subType":"04"}}},"$db": "example-mongo"}

Here is a gist with the code used in the post.