Application diagnostics
.NET .NET Core ASP.NET Core Best Practices C# Diagnostics Serilog Visual Studio Web API

Using Serilog File Logging in a .NET Core Web API

Welcome to today’s post.

In today’s post I will introduce a third-party file logging provider package for .NET Core.

Before we can deploy our application into a production environment, there is a need to allow our application to be supportable. For this to be possible, our application will need to provide diagnostics logging capabilities. When an issue occurs within our application, we can be in a position to diagnose potential faults by examining logs that are output from our application.

When to use Diagnostic Output Logs

Ideally, as a best practice, instead of outputting logs from commonly executed parts of our application, we would output logs from within exception blocks that can provide us with further diagnostic details on the cause of an error. These are classified as error logs.

We could also output logs that provide performance-related information that can be used to determine when our application is performing sub-optimally. From the logged information, we can then fine-tune our application for performance. These are classified as information logs.

Logging provides us with the troubleshooting tools that cannot be achieved from interactive development tool such as IDE debuggers that are available within a local development environment.

Why would we be using a third-party file logging provider instead of a logging provider from Microsoft?

The reason is stated on the Microsoft site for ASP.NET Core logging.

ASP.NET Core does not include a logging provider that writes logs to files. To be able to write logs to files from an ASP.NET Core app, the recommendation is to use a third-party logging library.

Examples of popular third-party file logging libraries include:

  • Log4Net
  • NLog
  • Serilog

For a full list of third-party logging providers refer to the Microsoft site for ASP.NET Core logging.

Setup of the Serilog File Logging Library

The package I will be discussing in this section is how to setup and configure the Serilog logging library in a .NET Core application.

I will first explain how to install the third-party file logging library, Serilog.

To enable logging for non-hosted .NET Core Console or Service applications, you will need to install the following Serilog NuGet packages:

  • Serilog
  • Serilog.Sinks.Console
  • Serilog.Sinks.File

In the package manager install the packages in the above order.

For web hosted ASP.NET Core applications, which include ASP.NET Core Web API and ASP.NET Core Web MVC applications, you will need to install the following Serilog NuGet package:

Serilog.ASPNetCore

In the package manager the package is shown as follows:

With .NET Core 3.1, the matching version to install is v4.0.0.

With .NET Core 5.0, the matching version to install is v4.1.0.

To configure Serilog to run in a generic host within an ASP.NET Core application, we do the following:

  1. Assign the Log,Logger to an instance of LoggerConfiguration().
  2. Call the UseSerilog() extension method to enable Serilog as the logging provider in the code excerpt below:
using Serilog;
using Serilog.Events;
..

public class Program
{
    public static int Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
            .Enrich.FromLogContext()
            .WriteTo.Console()
            .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();

        try
        {
            Log.Information("Starting the Web Host...");
            BuildWebHost(args).Run();
            return 0;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseSerilog()
            .UseStartup<Startup>()
            .Build();
    }
}

In the next section, we will see how the diagnostic outputs are output to files and to the console.

Debug Outputs from the Serilog File Logs

When the application is run, in the Web Server console output window, you will see the log entry showing with the date time stamp followed by INF..

Note that the extension method call:

.WriteTo.Console()

Ensures the output will log to the console.

After opening the file explorer path of the project, we can see the \Log folder and the output log file log.txt with the same log output from the console:

Again, the call to the following extension method:

.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)

Ensures the log is output to the specified file.

If we call a Web API controller method, then the following output will be shown:

Response sent: http://localhost:25138/api/Book/AllBooks with HTTP status 200.0
[22:50:13 INF] Executed action BookLoan.Controllers.BookController.AllBooks (BookLoan.Catalog.API) in 1439.1413ms
[22:50:13 INF] Executed endpoint 'BookLoan.Controllers.BookController.AllBooks (BookLoan.Catalog.API)'
[22:50:13 INF] The response could not be cached for this request.
[22:50:13 INF] Request finished in 2084.8373ms 200 application/json; charset=utf-8
Response sent: http://localhost:25138/api/Book/AllBooks with HTTP status 200.0

In the next section, I will show how to limit output from the Serilog logging provider with some handy configurations.

Limiting Logging Outputs

The above can be quite verbose if there are many HTTP request calls in our debug session, so we can override the default Microsoft logging provider for requests. This is how we reconfigure it for Serilog logging:

To use less verbose logging pf HTTP requests, in the LoggerConfiguration, use the Override() extension method to limit logs to AspNetCore logs at a level of Warning

Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
       .Enrich.FromLogContext()
       .WriteTo.Console()
       .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
       .CreateLogger();

Then call the UseSerilogRequestLogging() middleware in Configure() for the overridden logging filter to take effect:

using Serilog;
…

public void Configure(IApplicationBuilder app, IHostEnvironment env, 
    ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseSerilogRequestLogging();
	…
}

We now run the application again and observe the log output.

[23:23:28 INF] HTTP GET /api/Book/AllBooks responded 200 in 578.2022 ms
Response sent: http://localhost:25138/api/Book/AllBooks with HTTP status 200.0

There are a few other configurations that can be explored including enriching the output with additional properties, which can be explored on the Serilog ASP.NET Core documentation.

The Serilog third-party file logging package for .NET Core has been around for a few years before the .NET Core release and has quite a great deal of support from the developer community since the .NET Core releases up until the present .NET Core, so I recommend this as an ideal file diagnostics logger. In addition, there are extensions to handle logging in a web API or application hosted with Azure App Services.

That is all for today’s post.

I hope you have found this post useful and informative.

Social media & sharing icons powered by UltimatelySocial