Logging best practices


I have a question, I develop, or help develop, a few libraries in the .NET space related to geo, like Itinero, NetTopologySuite, OsmSharp, …

Some of my implementations would greatly benefit from decent logging, for now I wrote my own pluggable logging system for each.

What would the best-practices approach to improve this? How to other libraries handle logging? I don’t want to add a dependency on some specific library like NLog or Serilog, I want my users to be able to choose their own logging provider.


Hi xivk,

I recommend taking a look at LibLog:

It provides a logging abstraction internally to your library without making your library opinionated in the logging framework decision. It "contains transparent built-in support for NLog, Log4Net, EntLib Logging, Serilog, and Loupe, and allows your users to define a custom provider if necessary."
LibLog is a bit more costly performance-wise than calling a logger directly, but in my app profiling, it’s never shown up as a sore spot for me.

Another good option could be Microsoft.Extensions.Logging:

There were some concerns about additional libraries this abstraction pulls in that were not good for library maintainers. I have not evaluated with the new core 2.0 release if this has been resolved yet.


OK, LibLog looks perfect, exactly what I was looking for thanks!


How about LogUtility?


Hi folks:

I’m still just a little new overall to the framework, but I’ve moved a light speed through a universe :milky_way:! I have luckily avoided most pitfalls, but I have encountered seemingly most of them … and Logging is somewhat of a potential pitfall.

LibLog is excellent! :ok_hand: And I have recently begun looking at potentially using that. But, I took a different approach with a similar concept … and would love to hear any input on this topic.

Developing a commercial solution, I have 40+ “internal” libraries implementing modularized features; and I took an approach to solve this by:

  1. Libraries don’t use “Loggers”, but instead use System.Diagnostics
  2. I have my own static central source from which libraries fetch TraceSource instances
  3. This lives in my own small Diagnostics library
    — (TraceSource instances are just weakly held in a static dictionary, but always fetched there, so it enables instrumentation.)

Therefore, I have implemented central simple configuration: you can put a custom ConfigurationSection in any config file, and use all the standard Diagnostics configurations. My assemblies typically get a single TraceSource instance per assembly, and you could instrument any one, but you can also simply set a global TraceListener there as well, which is added to all TraceSource instances (dynamically). In fact, they do no default configuration themselves (aside from in fact removing the default listeners in release) — and you just configure them in the standard way in the Diagnostics config.

So you can write a simple TraceListener adapter that will pipe all of these TraceSources to your desired logging sink.

The libraries now know nothing about “Loggers” and just trace with the core library diagnostics; and you can just instrument that.

Any comments; or further input is appreciated; and would be helpful to me!

.NET Foundation Website | Blog | Projects | Code of Conduct