HTTP Logging in ASP.NET Core

HTTP Logging is a middleware that logs information about HTTP requests and HTTP responses. HTTP logging provides logs of:

  • HTTP request information
  • Common properties
  • Headers
  • Body
  • HTTP response information

HTTP Logging is valuable in several scenarios to:

  • Record information about incoming requests and responses.
  • Filter which parts of the request and response are logged.
  • Filtering which headers to log.

HTTP Logging can reduce the performance of an app, especially when logging the request and response bodies. Consider the performance impact when selecting fields to log. Test the performance impact of the selected logging properties.

Warning

HTTP Logging can potentially log personally identifiable information (PII). Consider the risk and avoid logging sensitive information.

Enabling HTTP logging

HTTP Logging is enabled with UseHttpLogging, which adds HTTP logging middleware.

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");

app.Run();

By default, HTTP Logging logs common properties such as path, status-code, and headers for requests and responses. Add the following line to the appsettings.Development.json file at the "LogLevel": { level so the HTTP logs are displayed:

 "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

The output is logged as a single message at LogLevel.Information.

Sample request output

HTTP Logging options

To configure the HTTP logging middleware, call AddHttpLogging in Program.cs.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

LoggingFields

HttpLoggingOptions.LoggingFields is an enum flag that configures specific parts of the request and response to log. HttpLoggingOptions.LoggingFields defaults to RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.

RequestHeaders

Headers are a set of HTTP Request Headers that are allowed to be logged. Header values are only logged for header names that are in this collection. The following code logs the request header "sec-ch-ua". If logging.RequestHeaders.Add("sec-ch-ua"); is removed, the value of rhe request header "sec-ch-ua" is redacted. The following highlighted code calls HttpLoggingOptions.RequestHeaders and HttpLoggingOptions.ResponseHeaders :

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions

MediaTypeOptions provides configuration for selecting which encoding to use for a specific media type.

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions methods

RequestBodyLogLimit and ResponseBodyLogLimit

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();