.NET Core Logger using Serilog – Part 2

Recap

In the previous part of this series, we started with our logger implementation in .NET Core Web Api project. We’ve identified various types of logs and also created our LogDetail entity class. Then we create an AppLogger which centralize writing of logs to files. You can read the part 1 on this URL.

We will first continue by putting together our try-catch and exception handling logic in a central place. Lets implement this first.

Centralized Exception Handling

Lets first centralize exception handling concern using Asp .NET Core middleware component. For this purpose I created an ExceptionHandler.cs class and use it in Startup.cs file Configure method as follows:

By configuring and using this middleeware, we can now handle our exception handling concerns in a single place. This will help keep our code base clean and not to flood it with try-catch block everywhere in the controllers or other places.

Now because we have a centralize exception handling place, we can introduce our logging code there as well later. Check below the code for the ExceptionHandler:

We have a try-catch block and by doing this way you don’t have to pollute your controllers code with general try/catch blocks and this is a common way to reduce that boiler plate code even if you are not doing logging.

Next, lets see HandleExceptionAsync method code and I also put a place-holder for our logging code:

So, we will come back and put our logging call code here later. The rest of the code is just preparing a message (error-code) and sending it to client. This way we are not exposing sensitive error details to the client and only sending them the error-code. That’s it, the middleware will fit nicely in ASP.NET Core pipeline and we can now move to other concerns.

Lets put our ExceptionHandling middleware to test. I created the following method in WeatherForecastController.cs to simulate an exception and we will call this endpoint using postman and see what is the response we receive from ExceptionHandling middleware:

REST Call

So, we get the expected response. Our middleware is working and we are not exposing sensitive server data to client (Postman). But, same time we want to log this exception details on server (file), so we can analyze it later.

Log Errors to File

I will start by creating a class “WebHelper.cs” in our CoreLogger folder. This class internally uses AppLogger which we created earlier.

We will discuss the implementation of this class later. But first introduce logging code in our exception handler, we saw earlier. We will add the following line in our ExceptionHandler middleware:

Now the exception-handler code is complete and it is just making a method call to the WebHelper.LogWebError() method will some parameters, we are passing product i.e. our web-application, the layer is the web-api and then we are passing along the actual exception ex and the HttpContext to the method, which will then take this information and further process it. So the code in the ExceptionHandler is very simple.

File Persistence

Before we dive into the implementation details of WebHelper class. first see the end-result of what information we are storing in the file and then we will see how it is being done.

Lets run the API code and call the simulateError method again using postman.

So, to postman client, we are still giving the error-id information and not exposing anything else, so that part did not change from last time. Now, if you visit the location for the log files (which you set via environmental variables in part-1 of this series) you will see the following files:

So, Serilog is creating these files (for each LogType) as we specified in the part-1. Lets open up the errorfile.txt and see its content that what was saved to it.

Ok, this is a lot of information. This was captured in the WebHelper.LogWebError() method (which we haven’t talked about yet). Now let me open the JSON payload part in a formatted manner so its easier to read.

You can see, it is also capturing custom data in our exception. stack trace along with layer, product, method information. Some information which is related to performance e.g. ElapsedMilliseconds is not captured here (coz we have different type of log for that performance log, we will see that one in later part).

WebHelper.cs Code

We saw this class above, now lets see the method codes and how those are capturing these details. The code is very straight forward and let me know if something is not clear.

LogWebError Method

This is the method, we called from ExceptionHandler, it is calling another method (see next method) to get hydrated LogDetail entity and then passing it to AppLogger.WriteError() method.

GetWebLogDetail method

This is the method which starts preparing LogDetail entity and it also calls two other methods GetUserData and GetRequestData for some of the specific information for LogDetail. As you can see, if you want to capture some more information about error, you can introduce it here, but its already very detailed.

Summary

In this post, we moved one step forward, we saw how to manage a centralized exception-handling in ASP .Net Core web application. Then we introduced our logging functionality in the mix and also saw some more of the infrastructure code. Our journey is not finished yet, we will explore some of the more code and also deal with other types of logs as well in coming posts. Till Next time, Happy Coding.