Skip to main content
Version: v1.2.0

Logging

The Arcus.WebApi.Logging package provides a way to log several kinds of information during the receival and handling of HTTP requests.

To send the logging information to Application Insights, see this explanation.

Installation

These features require to install our NuGet package

PM > Install-Package Arcus.WebApi.Logging

Logging unhandled exceptions

The ExceptionHandlingMiddleware class can be added to the ASP.NET Core pipeline to log unhandled exceptions that are thrown during request processing. The unhandled exceptions are caught by this middleware component and are logged through the ILogger implementations that are configured inside the project.

The HTTP status code 500 is used as response code when an unhandled exception is caught. However, when the runtime throws a BadHttpRequestException we will reflect this by returning the corresponding status code determined by the runtime.

Usage

To use this middleware, add the following line of code in the Startup.Configure method:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptionHandling();

...
app.UseMvc();
}
}

If you have multiple middleware components configured, it is advised to put the ExceptionHandlingMiddleware as soon as possible. By doing so, unhandled exceptions that might occur in other middleware components will also be logged by the ExceptionHandlingMiddleware component.

Logging incoming requests

The RequestTrackingMiddleware class can be added to the ASP.NET Core pipeline to log all received HTTP requests. The incoming requests are logged by this middleware component using the ILogger implementations that are configured in the project.

The HTTP request body is not logged by default.

The HTTP request headers are logged by default, except certain security headers are by default omitted: Authentication, X-Api-Key and X-ARR-ClientCert. See configuration for more details.

Example

HTTP Request POST http://localhost:5000/weatherforecast completed with 200 in 00:00:00.0191554 at 03/23/2020 10:12:55 +00:00 - (Context: [Content-Type, application/json], [Body, {"today":"cloudy"}])

Usage

To use this middleware, add the following line of code in the Startup.Configure method:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRequestTracking();

// Make sure that the exception handling is placed after the request tracking because otherwise unhandled exceptions that result in 500 response status codes will not be tracked.
app.UseExceptionHandling();
app.UseMvc();
...
}
}

Configuration

The request tracking middleware has several configuration options to manipulate what the request logging emits should contain.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRequestTracking(options =>
{
// Whether or not the HTTP request body should be included in the request tracking logging emits.
// (default: `false`)
options.IncludeRequestBody = true;

// Whether or not the configured HTTP request headers should be included in the request tracking logging emits.
// (default: `true`)
options.IncludeRequestHeaders = true;

// All omitted HTTP request header names that should always be excluded from the request tracking logging emits.
// (default: `[ "Authentication", "X-Api-Key", "X-ARR-ClientCert" ]`)
options.OmittedRequestHeaderNames.Add("X-My-Secret-Header");
});

...
app.UseMvc();
}
}

Optionally, one can inherit from this middleware component and override the default request header sanitization to run some custom functionality during the filtering.

Following example shows how the request security headers can be emptied by not omitted:

using Arcus.WebApi.Logging;

public class EmptyButNotOmitRequestTrackingMiddleware : RequestTrackingMiddleware
{
public EmptyButNotOmitRequestTrackingMiddleware(
RequestDelegate next,
ILogger<RequestTrackingMiddleware> logger)
: base(next, logger)
{
}

protected override IDictionary<string, StringValues> SanitizeRequestHeaders(IDictionary<string, StringValues> requestHeaders)
{
requestHeaders["X-Api-Key"] = "<redacted>";
return requestHeaders;
}
}

And, configure your custom middleware like this in the Startup.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;

public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRequestTracking<EmptyButNotOmitRequestTrackingMiddleware>(options => options.OmittedHeaderNames.Clear());

...
app.UseMvc();
}
}

So the resulting log message becomes:

HTTP Request POST http://localhost:5000/weatherforecast completed with 200 in 00:00:00.0191554 at 03/23/2020 10:12:55 +00:00 - (Context: [X-Api-Key,])

Tracking application version

The Arcus.WebApi.Logging library allows you to add application version tracking to your ASP.NET application which will include your application version to a configurable response header.

This functionality uses the IAppVersion, available in the Arcus.Observability library, for retrieving the current application version. Such an instance must be registered in order for the version tracking to work correctly.

Warning: Only use the version tracking for non-public endpoints otherwise the version information is leaked and it can be used for unintended malicious purposes.

Adding the version tracking can be done by the following:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAppVersion, MyAppVersion>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Uses the previously registered `IAppVersion` service to include the application to the default `X-Version` response header.
app.UseVersionTracking();

// Uses the previously registered `IAppVersion` service to include the application to the custom `X-My-Version` response header.
app.UseVersionTracking(options => options.Header = "X-My-Version");
}
}

Application Insights

To get the information logged in Azure Application Insights, configure logging like this when building the IWebHost in Startup.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Serilog;
using Serilog.Configuration;

public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Log.Logger = new LoggerConfiguration()
.WriteTo.AzureApplicationInsights("my-instrumentation-key")
.CreateLogger();
}
}

Note, don't forget to add .UseSerilog in the Program.cs.

using Microsoft.AspNetCore.Hosting;
using Serilog;

public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

private static WebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseSerilog()
.UseStartup<Startup>();
}
}

To have access to the .AzureApplicationInsights extension, make sure you've installed Arcus.Observability.Telemetry.Serilog.Sinks.ApplicationInsights.

← back