Skip to main content

LoggingMiddleware

Namespace: RA.Utilities.Api.Middlewares

The LoggingMiddleware is a high-performance ASP.NET Core middleware that provides comprehensive structured logging for HTTP requests and responses. It captures the full request/response cycle — method, path, headers, body, status code, and processing duration — and logs it as structured data for easy querying in modern logging platforms.

This middleware supersedes the HttpLoggingMiddleware from the deprecated RA.Utilities.Api.Middlewares package, adding log-scope enrichment, header filtering, and slow-response warning thresholds.

Key Features​

  1. Comprehensive Logging: Captures method, path, query string, headers, body, status code, remote address, and total processing time for every request.

  2. High Performance: Uses Microsoft.IO.RecyclableMemoryStream to pool and reuse memory buffers, minimizing garbage collection pressure in high-throughput environments.

  3. Structured Logging: Request and response bodies are parsed as JSON when possible, producing structured objects in your logs rather than opaque strings. This enables powerful querying in tools like Seq, Splunk, or Elasticsearch.

  4. Log-Scope Enrichment: Each request's log scope is automatically enriched with the X-Request-Id value, so every log entry in the pipeline carries the correlation ID.

  5. Configurable: Exclude specific paths (e.g., /swagger, /health) from logging; redact sensitive headers (e.g., Authorization); set a maximum body size to prevent large payloads from overwhelming your logging system; and configure a slow-response warning threshold.

🚀 Usage Guide​

Step 1: Register the middleware services in Program.cs​

Call AddLoggingMiddleware() in your service configuration. Customize behavior with the options callback.

// Program.cs
using RA.Utilities.Api.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddLoggingMiddleware(options =>
{
options.MaxBodyLogLength = 16384; // 16 KB max body size
options.WarningThresholdMilliseconds = 2000; // Log Warning if > 2s
options.PathsToIgnore.Add("/swagger");
options.PathsToIgnore.Add("/health");
options.ExcludedHeaders.Add("Authorization"); // Redact from logs
});

var app = builder.Build();

Step 2: Add the middleware to the pipeline​

Place app.UseLoggingMiddleware() early in your middleware pipeline so it captures the full request/response cycle.

// Program.cs (continued)

var app = builder.Build();

app.UseLoggingMiddleware();

app.UseRouting();

app.MapControllers();

app.Run();

Log Output​

When a request is processed, the middleware generates two structured log entries:

Request Log:​

{
"Scheme": "https",
"Host": "api.example.com",
"Method": "POST",
"Path": "/api/users",
"QueryString": "?include=profile",
"RemoteAddress": "192.168.1.100",
"RequestHeaders": { "Content-Type": "application/json", "Accept": "application/json" },
"RequestBody": { "name": "John Doe", "email": "john.doe@example.com" }
}

Response Log:​

{
"Path": "/api/users",
"RemoteAddress": "192.168.1.100",
"StatusCode": 201,
"Duration": "15.42 ms",
"ResponseHeaders": { "Content-Type": "application/json", "Location": "/api/users/123" },
"ResponseBody": { "id": 123, "name": "John Doe" }
}

The request log is written at LogLevel.Information; the response log is written at LogLevel.Warning. Both logs are skipped entirely when Information logging is not enabled. When the total elapsed time exceeds WarningThresholdMilliseconds (if configured), an additional Warning entry is written alongside the response log: HTTP call to {Method} {Url} took too long ({ElapsedMilliseconds} ms). Request correlation (X-Request-Id) is carried by the log scope, not by properties on the log templates. Headers listed in ExcludedHeaders are redacted from both request and response header dictionaries. Bodies larger than MaxBodyLogLength are truncated with a descriptive message.