Logging is a crucial aspect of software development as it allows developers to track the execution of their code, identify issues, and debug problems. In other words, logging helps developers to better understand what is happening in their code, locate where issues are occurring, and troubleshoot those issues. This tutorial covers the use of the generic Microsoft ILogger interface to implement logging in a C# application. ILogger is a simple and lightweight interface that can be easily incorporated into any C# project. It provides a convenient way to add logging capabilities to a C# application. By the end of this tutorial, you should have a thorough understanding of how to use ILogger to add C# logging to your C# applications.
Things you should know
For this tutorial you need to know or have the following terms/techniques:
- General C# and .NET knowledge
I am using .NET 6 for this tutorial. - Visual Studio 2022 or higher
- Dependency Injection
Table Of Contents
What is logging?
Logging is keeping track of software. It doesn’t have to be your own application perse. Most applications use loggings to identify problems or keep track of what the code is doing. Logging is one of the first locations where you should look if a program has an issue.
There are several ways to implement logging in your own application. There are multiple third parties that you can use. One of the biggest and most widely used is NLog. It’s a big package with a lot of possibilities. You can use it to write logs to different locations, such as files and databases.
But .NET has its own package as well, called the ILogger<TCategoryName>. We just have to add it to the configuration of our application and tell it where to write the logs. Easy! Downside is that it’s pretty basic.
What to log in an application?
Some applications log a lot, making log files really big. So, what do you want to log? It really depends. The most vital parts of an application are good things to log. Application startup, the configuration used (without usernames and passwords!), and stuff like that.
I once saw a logging that logged each method that was called. One request activated 200 methods, some multiple times. That created a big log file. The reason was to trace errors and see the path the application has taken until it crashed. There are better ways of doing this and crashes are usually created by exception, which have a stack trace, showing you exactly where the problem is located.
A good idea would be a flag that turns on or turns off logging. This way you can log more if needed. For example, a client has a problem with your application. It keeps crashing. You were smart and build in logging. With a simple setting, the logging is turned on and gives you an exclusive log file just once. This way you can log a lot, but not all the time.
Exceptions are a must to log. These are easy to fetch as soon as they happen. Other information could be calculations. I once worked at a company that makes contact lenses. The software could calculate what kind of contact lenses a client needs. These calculations are complex and they are logged each time an optician uses those calculations.
Never log personal information! This is really important. Log files are usually somewhere on a disk and not as well secured as you can make your software. Or you store log information in the cloud or a database. It’s not a good idea to keep personal information in your logs due to GDPR.
Complete project
If you don’t want to read this whole article (although I took a lot of effort of writing it), you can skip it all and just download the code on my GitHub:
https://github.com/KensLearningCurve/LoggingInACSharpApplication
This repository has 2 branches: main, and EndProject. Main contains the start project, which I will use in this tutorial to show you the steps to implement logging. The EndProject contains the solution code that I will be writing in the article below.
Starting code
Alright, let’s start!
If you want to follow this article by using the same code as I am, download the project from my GitHub repository, listed above. Make sure you are on the Main branch.
If you open the project you will see three projects:
LoggingExample.Business:
This project has all the logic that will be used in the console application. Usually, we use a business layer to reuse the logic in different projects within the solution.
This project contains a DataContext, which uses Entity Framework to send and retrieve data to and from a database. You might want to change the connection string and update your own database.
The MovieService is a class that contains all kinds of methods handling movies. The IRepository interface is injected into the constructor.
The last class is the Repository, which is a generic handler for the database. A repository pattern is a widely used pattern.
LoggingExample.ConsoleApp:
This is the console application that will be used to show the titles of movies, via the MovieService. I configured the dependency injection and the DbContext in the Program.cs.
LoggingExample.Domain:
The domain project doesn’t contain any logic, but only the model Movie and the interfaces. A domain project is used if models, interfaces, enums, etc are used in different projects, but not the logic.
I kept the project small so you can get a better view of what we are changing. The console application does a call to movieService.GetAll(), which retrieves the movies from the database.
Adding some logging
To use Microsoft logging we need to follow a few steps. First, we need to install a package. Then we need to add the logging to the ServiceCollection. When that is done we can inject the ILogger into constructors where we want to use logging.
Setting up
The first thing we need to do is tell our application we want to use logging. In the Program.cs is a ServiceCollection. Here I added the dependency injection, DbContext, and more. To use logging we add the logging too:
The AddLogging is an extension from Microsoft.Extensions.DependencyInjection. There is no implementation because it doesn’t know where to print the logs. We add that via a package.
There are several packages that you can use:
- Microsoft.Extensions.Logging.Console
- Microsoft.Extensions.Logging.Debug
- Microsoft.Extensions.Logging.EventLog
Each package has a different output. The console package sends the log information to the console output. The debug prints the log information to the debug output of Visual Studio. The last one, the event log, send the log information to the Windows Event Log.
Let’s say we want to print the log information to the console application. Install the Microsoft.Extensions.Logging.Console and add the following code to the Program.cs:
I added this line below the line where I initialize the ServiceCollection.
Now, don’t do anything. Just start the application and see what happens.
It seems Entity Framework has the ILogger injected somewhere and is now printing that information to the console output. Because that’s the trick here: Injecting the interface ILogger and using that to send log information to the console, debug output, or the Event Viewer.
Adding own logging
The next part is about how we can add our own logging messages. In some cases, you might want to keep a log of what your application is doing. You can log information, errors, warnings, or debug information.
We already told our application that we want to use logging. With the AddLogging we connected the ILogger interface with the implementation in the AddConsole. All we need to do is inject the ILogger into our own classes. Let’s start with the MovieService class.
The ILogger is generic, which means it needs a type. This type is used as the category name, this is usually the class itself. Injecting the ILogger in the MovieService looks like this:
When this is done you can use the logger-property in the class. Let’s add some logging to the GetAll method.
Let’s start the application and check the result.
Log levels
I used the logger.LogInformation, which is a log level. Log levels indicate the severity of the message. There are six log levels with their severity:
- Trace = 0,
- Debug = 1,
- Information = 2,
- Warning = 3,
- Error = 4,
- Critical = 5,
- None = 6
If you don’t set anything all log levels will be shown. But you can set the minimal level. This means that if you set the minimal level to Debug you will only see debug and the levels below it. If you set the minimal level to the level warning, you will only see the levels warning, error, critical, and none.
As default the level is set to information. Let’s add a debug logging to the GetAll():
If you start the application you will only see the logging of line 3 and not line 7. If you change LogLevel.Debug to LogLevel.Warning you will see the warning on the screen.
So, how can we change the log level settings? Easy, in the configuration of the AddLogging. Back in the Program.cs, let’s change the code:
Here I add the Configure with the type LoggerFilterOptions. With this, I can set the minimal level to whatever I want. I have set it to debug. Let’s change the logger in MovieService.GetAll() back to debug and run the application.
Okay… That’s a lot of debug information. Maybe a bit too much. But it does work because I see my debug message too.
Suppressing logs
If you don’t want the debug (or other levels) information from a third-party library you can suppress them, or turn them off. You can do this with the category name. Remember this one?
You can set the minimal log level for each category name. I don’t want to see the debug information of Entity Framework. So, if I set it to warning they should disappear. You can do this in the Program.cs, where you configure the logging. Here is an example:
Adding the AddFilter, with the category name, you can set the log level. I set this one to the warning level, meaning it won’t show debug anymore.
Restarting the application shows a lot more debug logging. I see the category name Microsoft.EntityFrameworkCore.ChangeTracking and some others. All of them start with Microsoft.EntityFrameworkCore. You don’t have to add all the category names to the filter. You can also use a wildcard, the *:
This will remove all the Entity Framework Core logging.
Logging to the debug output
The above code works like it should. It logs to the console because we told it explicitly to print the logs to the console.
But we can also print the logs to the debug output of Visual Studio. Simply follow these steps:
- install the NuGet Package Microsoft.Extensions.Logging.Debug.
- Change configure.AddConsole() to configure.AddDebug().
Done!
If you start the application now you won’t see the logs in the console, but in the Visual Studio debug output.
It’s a bit hard to read because the output shows a lot more information, but the log information is there and the console application is nice and clean.
Conclusion
This tutorial shows a simple way of using logging in a C# application. While I used a console application, an API for example works practically the same. The configuration is a little bit different, but that’s minimal.
I covered the basics of logging using the ILogger<TCategory>. You now know what it is and how to use it. I only told you about how to print the logs to a console and the debug output. The event logger is a bit different and I will cover that in a different tutorial.

