What Is Logging?

Logging is the process of recording events and messages that occur in a system. These messages are usually stored in a file, but they can be sent to other destinations such as databases or other monitoring software.

Logging is a general purpose, but we mostly use it for:

– Troubleshooting and debugging: Logging provides historical activities of a system, making it easy to find problems such as exceptions in the code. We can analyze the log to see if it happened and try making educated guesses.

– Auditing and security. Log can be used to audit security events, user activities and system changes.

– Performance monitoring: Log can capture performance-related data such as the response time of a system. We can use it to identify bottlenecks and potential performance problems.

Logging Level

Logging Levels are defined differently for each implementation. However, they usually contain these 4 levels:

– Debug: This level contains detailed information for developers to perform troubleshooting. We usually don’t turn on this level in the production environment because it could produce a log of logging data.

– Information: This level logs information of system operations.

– Warning: This level indicates potential issues that might require attention but are not critical issues yet.

– Error: This level indicates that an error occurred in the system.

In .NET Core, the framework defines more log levels to distinguish their intention even further. These log levels include: Trace, Debug, Information, Warning, Error, Critical, None.

In the following sections, we will put them into practice and have a better understanding of log level.

How logging is implemented in .NET Core?

ILogger, ILoggerProvider and ILoggerFactory

Logging in .NET core is built of so many components and classes. However, I will only introduce 3 main components that we usually interact with and use most of the time in the framework.

– ILogger is the interface that represents a type we interact with to perform the logging. In the real world, we don’t usually use this interface but ILogger instead. The ILogger eventually inherits the interface ILogger. This interface exposes a method that we can use to write logs with appropriate log levels such as Log, LogCritical, LogDebug, LogError, LogInformation, LogTrace, LogWarning… You can find more about the interface here.

– ILoggerProvider is used to create ILogger instances. Applications are not supposed to use this interface directly, they are only supposed to use ILoggerFactory to create instances of ILogger.

– ILoggerFactory is also used to create ILogger instances and is supposed to be used in the application code. We will register the ILoggerProvider with ILoggerFactory so that the framework will use it.

How is the Logger bootstrapped internally?

We can set a breakpoint in the Program.cs to see how it bootstrap the logging mechanism.

By inspecting the IServiceCollection, we get some insights of what the framework does under the hood. By default, the framework registers some ServiceDescriptor for all the interfaces that we mentioned in the previous section.

Figure 01: Code change to inspect IServiceCollection

Figure 01: Code change to inspect IServiceCollection

Further analysis of the IServiceCollection at runtime reveals that the framework bootstraps an ILogger, ILoggerFactory with Singleton lifetime. We have 4 ILoggerProvider registered by default (ConsoleLoggerProvider, DebugLoggerProvider, EventSourceLoggerProvider, EventLogLoggerProvider). Calling services.Logging.ClearProviders() would clear all the ServiceDescriptor from the IServiceCollection.

Figure 02: Inspect IServiceCollection at runtime

Figure 02: Inspect IServiceCollection at runtime

Logging Scope

The interface ILogger comes with a very handy method BeginScope that could be used to log a portion of code that has the same attribute (state). This method doesn’t show any distinct output when we use the default console logger. However, it comes very handy when we use Serilog and Seq.

Figure 03: Logging Scope example

Figure 03: Logging Scope example

Log Filtering

The framework also allows us to configure log filtering by specifying the desired log level for a specific log category via the AddFilter method. If no log filter is specified, then the minimum log level is applied.

Figure 04: Log filterFigure 04: Log filter

What is Serilog and Structured Logging

What is Serilog?

Serilog is a logging library for .NET and .NET Core that supports structured logging. It has the ability to store (sink) logs using a plain text file, Database, or even Seq (another software that supports the GUI for log querying and visualization)…

How does Serilog work?

We won’t dig deep into how Serilog works internally. However, we will take a glance at the highest level, by using the same technique that we used to observe the way the framework bootstrap logging. We can see that Serilog simply just replaces the ILoggerFactory by adding another ServiceDescriptor for ILoggerFactory.

Figure 05: Serilog replace ILoggerFactory using their own implementationFigure 05: Serilog replaces ILoggerFactory using its implementation

Serilog Integration Guide.

In this guide, we will integrate the .NET 8 with Serilog and we will try to sink the log to the file and Console. We will use the template  which contains all the code inside the Program.cs (without the Startup.cs file) file so that it would be easier to keep track of the post. First, we will bootstrap our project by using the following command in Windows Terminal:

dotnet new webapi -o SerilogIntegrationGuide 

The SerilogIntegrationGuide is not mandatory, It’s the name of your project and you can name it whatever you want as long as it respects the naming convention of your operating system.

After the project is fully created, then we can use the following command to install Serilog:

dotnet add package Serilog.AspNetCore 

Before we change our code to integrate with Serilog, let’s capture the output of our current program by hitting an endpoint of our web api.

Figure 06: Plain output of the default console loggingFigure 06: Plain output of the default console logging

The output is plain text without any format and is very hard to read. Now let’s add the Serilog package and change some code before we observe the output again.

Figure 07: Serilog integration code changeFigure 07: Serilog integration code change

Serilog integration is very easy, by creating the LoggerConfiguration and adding the line builder.Services.AddSerilog(), we have completed the integration with the logging library. Now let’s run the project, hit the endpoint and observe the output again.

Figure 08: Serilog console outputFigure 08: Serilog console output

The output is nicely formatted.

Now let’s try sinking (save) the log into the file instead. To sink the log to the file, we have to install another Nuget package by running the following command in the terminal

dotnet add package Serilog.Sinks.File –version 5.0.0 

After running the command, we have to make some changes to the code to make the logs dump into a file.

Figure 09: File rolling integration code change

Figure 09: File rolling integration code change

Then, we can run the project again and observe that the log file is created inside our project folder. The second parameter “rollingInterval” indicates that a new log file will be created after each hour so the log file is guaranteed to be small and contains only the logs with the scope of 1 hour.

Conclusion

In conclusion, logging provides a vital mechanism for understanding and maintaining your C# applications. By leveraging Serilog, you gain a powerful and flexible tool to capture, enrich, and store log data. This approach empowers you to troubleshoot issues efficiently, monitor application health, and gain valuable insights into system behavior. As your application evolves, Serilog’s scalability and extensibility ensure it can continue to be a cornerstone of your observability strategy.

In this article, we explored the vital role of logging and structured logging with Serilog within .NET applications. For further assistance or to discuss your project needs, feel free to reach out to us at Saigon Technology. Our team is well-equipped to provide you with the latest .NET technologies and support. Contact us today to bring your vision to life.

Resources

Demo source code: https://github.com/saigontechnology/Blog-Resources/tree/main/DotNet/do.tran/LoggingInDotNet

contact

.NET Development Services

Maximize efficiency and growth with our expert .NET development solutions tailored for you!
Uncover Our Expertise arrow-narrow-right.png
Content manager
Thanh (Bruce) Pham
CEO of Saigon Technology
A Member of Forbes Technology Council

Related articles

What You Need to Know about State Management: 6 Techniques for ASP.NET Core MVC
Methodology

What You Need to Know about State Management: 6 Techniques for ASP.NET Core MVC

This blog post covers 6 state management techniques for ASP.NET Core MVC. Saigon Technology, with 10+ years of .NET core experience, discussed them.
Unlocking the Potential of .NET MAUI for Frontend and Web Developers
Methodology

Unlocking the Potential of .NET MAUI for Frontend and Web Developers

Let our .net development company help you hire .net developers and unlock the potential of .NET MAUI. Begin your Web Application Development projects with .NET MAUI.
Build Customer Service (.NET, Minimal API, and PostgreSQL)
Methodology

Build Customer Service (.NET, Minimal API, and PostgreSQL)

In the previous section (part 2), I provided an overview of how to set up a working environment using Docker containers and build a Product Service. In this section (part 3), we will shift our focus to building Customer Service using .NET, Minimal API, and PostgreSQL.
calendar 13 Jun 2024
Say Hello to .NET MAUI
Methodology

Say Hello to .NET MAUI

This series introduces .NET MAUI and shows how to develop an application with it. The first article covers what .NET MAUI is, how it works, and its key features.
calendar 10 Apr 2024
How to build UI with .NET MAUI
Technologies

How to build UI with .NET MAUI

This article will help you learn how to create a UI with MAUI layouts and controls. It also gives some tips when developing applications with MAUI.
calendar 10 Apr 2024
Real-time ASP.NET with SignalR
Technologies

Real-time ASP.NET with SignalR

Today we are going to dive into SignalR for .NET. What is a real-time app, and how does SignalR work in .NET? Cover SignalR concepts and build a chat app.
calendar 19 Sep 2024

Want to stay updated on industry trends for your project?

We're here to support you. Reach out to us now.
Contact Message Box
Back2Top