Implementing Serilog in ASP.NET C# Web API for Enhanced Logging of Requests and Responses

Implementing Serilog in ASP.NET C# Web API for Enhanced Logging of Requests and Responses

Introduction

Logging is a critical aspect of any web application. It helps in debugging, performance monitoring, and understanding user interactions. In ASP.NET C#, integrating Serilog as a middleware for logging requests and responses, including the data passed in and out, can significantly improve your Web API’s observability and troubleshooting capabilities.

Over the last few weeks, I have been writing a few different Web APIs that use Azure Table Storage rather than an SQL or Postgres database because table storage is very cheap, and databases are expensive, and I wanted to experiment with table storage to see how useful it was in a real-life application.

In this blog post, I will walk through the steps to create a middleware class in an ASP.NET C# Web API using Serilog for comprehensive logging.

Setting Up Serilog

Firstly, you need to integrate Serilog into your ASP.NET C# project. Serilog is a powerful and easy-to-use logging library.

  1. Install Serilog Packages: Via NuGet Package Manager, install Serilog, Serilog.AspNetCore, and Serilog.Sinks.File (or any other sink of your choice).
  2. Configure Serilog: In your Program.cs or Startup.cs, configure Serilog as the logging provider:
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

Creating the Middleware

Middleware in ASP.NET Core is software that’s assembled into an application pipeline to handle requests and responses.

  1. Create a New Middleware Class: Create a new class, SerilogMiddleware.cs, in your project.
  2. Implementing the Middleware Logic: This class will intercept all HTTP requests and responses, allowing us to log the necessary information.
public class SerilogMiddleware
{
    private readonly RequestDelegate _next;

    public SerilogMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        // Log the Request
        Log.Information($"Request {context.Request?.Method}: {context.Request?.Path.Value}");

        // Read and log the request body data
        string requestBodyPayload = await ReadRequestBody(context);
        Log.Information($"Request Payload: {requestBodyPayload}");

        // Copy a pointer to the original response body stream
        var originalBodyStream = context.Response.Body;

        using (var responseBody = new MemoryStream())
        {
            // Point the response body to a memory stream
            context.Response.Body = responseBody;

            await _next(context);

            // Read and log the response body data
            context.Response.Body.Seek(0, SeekOrigin.Begin);
            string responseBodyPayload = await new StreamReader(context.Response.Body).ReadToEndAsync();
            context.Response.Body.Seek(0, SeekOrigin.Begin);

            Log.Information($"Response {context.Response?.StatusCode}: {responseBodyPayload}");

            // Copy the contents of the new memory stream (which contains the response) to the original stream, which is then returned to the client.
            await responseBody.CopyToAsync(originalBodyStream);
        }
    }

    private async Task<string> ReadRequestBody(HttpContext context)
    {
        context.Request.EnableBuffering();

        var buffer = new byte[Convert.ToInt32(context.Request.ContentLength)];
        await context.Request.Body.ReadAsync(buffer, 0, buffer.Length);
        string bodyAsText = Encoding.UTF8.GetString(buffer);
        context.Request.Body.Seek(0, SeekOrigin.Begin);

        return bodyAsText;
    }
}

Registering the Middleware

In the Startup.cs file, register the middleware in the Configure method.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... other configurations ...

    // Register the Serilog middleware
    app.UseMiddleware<SerilogMiddleware>();

    // ... other configurations ...
}

Conclusion

You’ve set up a robust logging mechanism by implementing the Serilog middleware in your ASP.NET C# Web API. This will log all requests and responses along with their payloads, giving you detailed insights into the operation of your API. This setup is invaluable for diagnosing issues, understanding user behaviour, and ensuring the smooth operation of your application.

Remember, while logging is essential, it’s also crucial to be mindful of what you log, especially when dealing with sensitive data. Always adhere to best practices and legal requirements regarding data handling and privacy.

You can download Serilog from here: – https://serilog.net

Stephen

Hi, my name is Stephen Finchett. I have been a software engineer for over 30 years and worked on complex, business critical, multi-user systems for all of my career. For the last 15 years, I have been concentrating on web based solutions using the Microsoft Stack including ASP.Net, C#, TypeScript, SQL Server and running everything at scale within Kubernetes.