ASP.NET Core: Logging with Serilog to MongoDB Using Configuration

This is likely a bit esoteric, but I was setting up an ASP.NET Core 2.2 project recently where I wanted to store logs in MongoDB. I wanted to play with Serilog vs. some of the alternatives. I also wanted to use a configuration file, and I wasn’t able to find any good examples online, so I figured I’d create a quick example in this post. This example is applicable to ASP.NET Core 2.2, and may work for other versions, but isn’t tested with others.

First you’ll want to install the following NuGet packages:

Serilog
Serilog.AspNetCore
Serilog.Settings.Configuration
Serilog.Sinks.MongoDB

Next, go to your appsettings.json/appsettings.Development.json files. You can delete the Logging section in the default scaffolded files and add a Serilog section as below. Here is a basic example of my Development version with only the AllowedHosts section left from the scaffolded version:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "MongoDBBson",
        "Args": {
          "databaseUrl": "mongodb://localhost/logs",
          "collectionName": "log",
          "cappedMaxSizeMb": "50",
          "cappedMaxDocuments": "1000"
        }
      }
      // Add other sinks here if desired...
    ]
  },
  "AllowedHosts": "*"
}

Update 9/2021: The name on the WriteTo has been changed to “MongoDBBson” where it was previously “MongoDBCapped” Sometime between when this post was written and now, “MongoDBBson” started supporting the capped properties, and there are issues with the current sink using “MongoDBCapped” with replica sets.

A lot of this is straightforward, such as the url and connection name. In the example above, I’m using a capped collection with “Name”: “MongoDBCapped” in the WriteTo sinks section because in my application, I don’t care about keeping logs forever. If you want to use a normal collection, change the name to “MongoDB” and remove the capped… settings in “Args”.

For the “MinimumLevel”, you’ll likely want to change the values to higher levels for your production settings. Microsoft has a nice explanation of ASP.NET Core Log Levels.

Now you’re going to want to set Serilog up in code. There are a couple similar ways to do this, but I prefer adding the .UseSerilog call in Program.cs inside CreateWebHostBuilder. Right after .UseStartup, add the following code:

.UseSerilog((context, config) =>
{
    config.ReadFrom.Configuration(context.Configuration);
});

The whole section in Program.cs might look like this, if you have no other builder calls:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseSerilog((context, config) =>
        {
            config.ReadFrom.Configuration(context.Configuration);
        });

And that’s really it from a setup perspective. At this point, you can add constructor parameters to get a working logger from dependency injection. For example:

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }
    public IActionResult Index()
    {
        _logger.LogInformation("Hello from inside HomeController.Index!");
        return View();
    }
    // Rest of the class here...
}