The .NET Stacks, #60: 📝Logging improvements in .NET 6

This week, we're talking about logging improvements that are coming with the .NET 6 release.

Dave Brock
Dave Brock

Happy Monday! It's hard to believe it's August already. What are we talking about this week?

  • One big thing: Logging improvements in .NET 6
  • The little things: Notes from the community
  • Last week in the .NET world

One big thing: Logging improvements in .NET 6

Over the last few months, we've highlighted some big features coming with .NET 6. Inevitably, there are some features that fly under the radar, including various logging improvements that are coming. Let's talk about a few of them.

Announced with Preview 4 at the end of May, .NET will include a new Microsoft.Extensions.Logging compile-time source generator. The Microsoft.Extensions.Logging namespace will expose a LoggerMessageAttribute type that generates "performant logging APIs" at compile-time. (The source code relies on ILogger, thankfully.)

From the blog post:

The source generator is triggered when LoggerMessageAttribute is used on partial logging methods. When triggered, it is either able to autogenerate the implementation of the partial methods it’s decorating, or produce compile-time diagnostics with hints about proper usage. The compile-time logging solution is typically considerably faster at run time than existing logging approaches. It achieves this by eliminating boxing, temporary allocations, and copies to the maximum extent possible.

Rather than using LoggerMessage APIs directly, the .NET team says this approach offers simpler syntax with attributes, the ability to offer warnings as a "guided experience," support for more logging parameters, and more.

As a quick example, let's say I can't talk to an endpoint. I'd configure a Log class like this:

public static partial class Log
    [LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not reach `{uri}`")]
    public static partial void CouldNotOpenSocket(ILogger logger, string uri);

There is much, much more at the Microsoft doc, Compile-time logging source generation.

On the topic of HTTP requests, ASP.NET Core has a couple of new logging improvements worth checking out, too. A big one is the introduction of HTTP logging middleware, which can log information about HTTP requests and responses, including the headers and body. According to the documentation, the middleware logs common properties like path, query, status codes, and headers with a call to LogLevel.Information. The HTTP logging middleware is quite configurable: you can filter logging fields, headers to log (you need to explicitly define the headers to include), media type options, and a log limit for the response body.

This addresses a common use case for web developers. As always, you'll need to keep an eye on possible performance impacts and mask logging sensitive information (like PII data).

Lastly, with .NET 6 Preview 5 the .NET team rolled out subcategories for Kestrel log filtering. Previously, verbose Kestrel logging was quite expensive as all of Kestrel has shared the same category name. There are new categories on top of *.Server.Kestrel, including BadRequests, Connections, Http2, and Http3. This allows you to be more selective on which rules you want to enable. As shown in the blog post, if you only want to filter on bad requests, it's as easy as this:

  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"

If you want to learn more about ASP.NET Core logging improvements in .NET 6, Maryam Ariyan and Sourabh Shirhatti will be talking about it in Tuesday's ASP.NET standup.

The little things: Notes from the community

AutoMapper is a powerful but self-proclaimed "simple little library" for mapping objects. From Shawn Wildermuth on Twitter, Dean Dashwood has written about Three Things I Wish I Knew About AutoMapper Before Starting. It centers around subtleties when working with dependency injection in models, saving changed and nested data, and changing the models. It's actually a GitHub repo with a writeup and some code samples—highly recommended.

Sometimes one sentence does the trick: Cezary Piątek has a nice MsBuild cheatsheet on GitHub.

This week, Mike Hadlow wrote about creating a standalone ConsoleLoggerProvider in C#. If you want to create a standalone provider to avoid working with dependency injection and hosting, Mike found an ... interesting ... design. He develops a simple no-op implementation.

Well, it's been 20 years since the Agile Manifesto, and Al Tenhundfeld celebrates it with the article Agile at 20: The Failed Rebellion. I think we can all agree that (1) everybody wants to claim they are Agile, and (2) Agile is a very, um, flexible word—nobody is really doing Agile (at least according to the Manifesto). He explores why; an interesting read.

🌎 Last week in the .NET world

🔥 The Top 3

📢 Announcements

📅 Community and events

🌎 Web development

🥅 The .NET platform

⛅ The cloud

📔 Languages

🔧 Tools

📱 Xamarin

🏗 Design, testing, and best practices

🎤 Podcasts

🎥 Videos

.NET Stacks