How do I log my queries in MongoDB C# Driver 2.0?
Asked Answered
P

4

23

Just upgraded my application to the latest stable MongoDB C# Driver 2.0.

During the migration, basic functionality has been broken and even the simplest query like: this.collection.Find(e => e.Id == id).SingleOrDefaultAsync() doesn't return the correct data.

Checked the class mappings and conventions but I would like to see the output query in order to properly identify the issue.

So, how should it be done on the MongoClient side?

Setting profiling on the database level is possible but not a good solution since we have several applications and developers using the database.

My application is currently using Ninject.Extensions.Logging and log4net in the UI, business and EF data access.

Polyphony answered 19/5, 2015 at 18:56 Comment(8)
Possible dupe of #30306693Avidity
"Setting profiling on the database is not a good since we have several developers using the database". huh? Can't you use a local database for debugging? Is that non-functioning application actually deployed?Drove
@Drove I'm trying to create a functioning development environment so all developers can share. The database is feeding data from external app, and another app is reading that data.Polyphony
@Avidity - the second answer in your suggested dupe is a good one time solution for a specific query, but is there a logging solution for all app-wide queries?Polyphony
"functioning development environment" and "developers can share [data]" sounds like a contradiction to me...Drove
@Drove - Whether our development environment is functional to us or not, is our own decision. My question here is irrelevant to that. I am trying to log the queries and operations that are being executed by the MongoDB C# Driver. That should be possible whether the DB is shared or not. Just like in EF where you can output the SQL queries to whatever logging implementation you desire using DI.Polyphony
@ShayNissel, did this get solved? There isn't a good way to log queries right now. We are working on something for 2.1. The best thing to do would be to do what is suggested in the linked "dupe" ticket. There are 2 ways mentioned there. On a separate note, are you waiting on the result? Simply calling SingleOrDefaultAsync() and not waiting on the result will cause everything to not work.Filberte
@CraigWilson, I didn't integrate logging into my MongoDB queries yet. When needed (for debugging) I use the redundant rendering suggestion from the "dupe". Waiting on 2.1 eagerly. About your Async question, I converted all my repositories and their calling services to use async and await.Polyphony
P
52

For newer C# MongoDB drivers the API has changed. You have to use the more complex constructor that accepts a MongoClientSettings object, instead of the connection string.

Use the following code to keep using a connection string, but enable the logging of each command:

var mongoConnectionUrl = new MongoUrl(connectionString);
var mongoClientSettings = MongoClientSettings.FromUrl(mongoConnectionUrl);
mongoClientSettings.ClusterConfigurator = cb => {
    cb.Subscribe<CommandStartedEvent>(e => {
        logger.Log($"{e.CommandName} - {e.Command.ToJson()}");
    });
};
var mongoCfgClient = new MongoClient(mongoClientSettings);
Planetary answered 4/8, 2017 at 13:7 Comment(0)
C
6

Logging to VS output with 2.7.3 driver.

using MongoDB.Bson;
using MongoDB.Driver;
using System;
#if TRACE
using System.Diagnostics;
using MongoDB.Driver.Core.Configuration;
#endif

...

public static ClusterBuilder ConfigureCluster(ClusterBuilder builder)
{
#if TRACE
    var traceSource = new TraceSource(nameof(Geotagging), SourceLevels.Verbose);
    builder.TraceWith(traceSource);
    builder.TraceCommandsWith(traceSource);
#endif
    return builder;
}

public MongoClient BuildMongoClient(string connection_string)
{
    var mongoUrlBuilder = new MongoUrlBuilder(connection_string);
    var settings = MongoClientSettings.FromUrl(mongoUrlBuilder.ToMongoUrl());
    settings.ClusterConfigurator = cb => ConfigureCluster(cb);
    return new MongoClient(settings);
}
Clearance answered 19/6, 2019 at 14:4 Comment(0)
G
5

You can enable logging by the mongo driver itself:

var settings = new MongoClientSettings
{
    ClusterConfigurator = cb =>
    {
        var textWriter = TextWriter.Synchronized(new StreamWriter("mylogfile.txt"));
        cb.AddListener(new LogListener(textWriter));
    }
};

You can hook it up to log4net if you wish.

Guillemot answered 13/8, 2015 at 9:57 Comment(2)
Just for clarification this only works for 2.0, later drivers have removed support for this.Mendymene
I have added an answer that is also suitable for newer drivers.Planetary
A
2

Instead of hooking into events and manually logging, you can also use the MongoDB C# client logging system.

Starting in version 2.18, the .NET/C# Driver uses the standard .NET logging API.

The documentation on the C# MongoDB client page creates its own logger factory, which obviously works, but you can also hook in the default .NET logger (or rather, the ILoggerFactory).

var settings MongoClientSettings.FromConnectionString("...");
settings.LoggingSettings = new 
// Get your ILoggerFactory from DI somewhere.
LoggingSettings(services.GetService<ILoggerFactory>());
var client = new MongoClient(settings);

Commands are logged to the MongoDB.Command category using debug level. All available log categories are described in the manual.

For example when configuring through appsettings.json, you would use:

{
  "Logging": {
    "LogLevel": {
      "MongoDB.Command": "Debug"
    }
  }
}
Anneal answered 23/11, 2023 at 13:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.