Crip.AspNetCore.Logging 2.0.0

dotnet add package Crip.AspNetCore.Logging --version 2.0.0
NuGet\Install-Package Crip.AspNetCore.Logging -Version 2.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Crip.AspNetCore.Logging" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Crip.AspNetCore.Logging --version 2.0.0
#r "nuget: Crip.AspNetCore.Logging, 2.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Crip.AspNetCore.Logging as a Cake Addin
#addin nuget:?package=Crip.AspNetCore.Logging&version=2.0.0

// Install Crip.AspNetCore.Logging as a Cake Tool
#tool nuget:?package=Crip.AspNetCore.Logging&version=2.0.0

Crip.AspNetCore.Logging

issues forks stars license

Make HTTP request logging ease.

Setup request/response logging in application

Configure log level for all requests:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware": "Trace"
    }
  }
}

Configure dependency injection in Startup.ConfigureServices:

services.AddRequestLogging();

Add logging middleware in Startup.Configure:

app.UseRouting();

// After routing
app.UseRequestLoggingMiddleware();
// And before endpoints

app.UseEndpoints(endpoints => ... );

In case of net6.0 it is not important where place app.UseRequestLoggingMiddleware();. Check out example net6.0 project

And now you are ready to see all request/response in logging output:

[ 12:52:31 VRB ] POST http://localhost:5000/api/test/verbose HTTP/1.1
Connection: keep-alive
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate, br
Host: localhost:5000
Content-Length: 27
                  { "body": "content" }
  { Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose } { EventName="HttpRequest", Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx" }

  [ 12:52:31 VRB ] HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
                { "level": "Verbose" }
  { Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose } { EventName="HttpResponse", StatusCode=200, Elapsed=6, Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx" }

  [ 12:52:31 INF ] POST http://localhost:5000/api/test/verbose at 00:00:00.006 with 200 OK {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose} {EventName="HttpResponse", StatusCode=200, Elapsed=6, Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx"}

Setup HTTP client request/response logging

Configure log level for a service:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.LoggingHandler": "Trace"
    }
  }
}

Configure dependency injection in Startup.ConfigureServices:

services.AddRequestLogging();

Register HTTP client with message handler:

services
    .AddRequestLoggingHandler()
    .AddHttpClient<MyHttpClient>()
    .AddHttpMessageHandler<LoggingHandler<MyHttpClient>>();

// Or use predefined extension method:
services.AddLoggableHttpClient<MyHttpClient>();

Configuration options

Disable response logging

If response content logging is not required - it could be disabled at service registration:

services.AddRequestLogging(options => options.LogResponse = false);

Change verbosity level to reduce logs

With different verbosity level, different output will be written to logs

  • Trace

    • Writes log message with incoming request headers and body
    • Writes log message with returned response headers and body
    • Writes basic response timing/status message
    [12:52:31 VRB] POST http://localhost:5000/api/test/verbose HTTP/1.1
    Connection: keep-alive
    Content-Type: application/json
    Accept: */*
    Accept-Encoding: gzip, deflate, br
    Host: localhost:5000
    Content-Length: 27
    {"body":"content"}
      {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose} {EventName="HttpRequest", Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx"}
    
    [12:52:31 VRB] HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    {"level":"Verbose"}
      {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose} {EventName="HttpResponse", StatusCode=200, Elapsed=6, Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx"}
    
    [12:52:31 INF] POST http://localhost:5000/api/test/verbose at 00:00:00.006 with 200 OK {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Verbose} {EventName="HttpResponse", StatusCode=200, Elapsed=6, Endpoint="http://localhost:5000/api/test/verbose", HttpMethod="POST", RequestId="xxx", RequestPath="/api/test/verbose", SpanId="|xxx.", TraceId="xxx", ParentId="", ConnectionId="xxx"}
    
  • Debug

    • Writes log message with incoming request headers
    • Writes log message with returned response headers
    • Writes basic response timing/status message
    [12:55:58 DBG] POST http://localhost:5000/api/test/debug HTTP/1.1
    Connection: keep-alive
    Content-Type: application/json
    Accept: */*
    Accept-Encoding: gzip, deflate, br
    Host: localhost:5000
    Content-Length: 27
    {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Debug} {EventName="HttpRequest", Endpoint="http://localhost:5000/api/test/debug", HttpMethod="POST", RequestId="yyy", RequestPath="/api/test/debug", SpanId="|yyy.", TraceId="yyy", ParentId="", ConnectionId="yyy"}
    
    [12:55:58 DBG] HTTP/1.1 200 OK
    Date: Fri, 26 Aug 2022 09:55:57 GMT
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=utf-8
    {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Debug} {EventName="HttpResponse", StatusCode=200, Elapsed=5, Endpoint="http://localhost:5000/api/test/debug", HttpMethod="POST", RequestId="yyy", RequestPath="/api/test/debug", SpanId="|yyy.", TraceId="yyy", ParentId="", ConnectionId="yyy"}
    
    [12:55:58 INF] POST http://localhost:5000/api/test/debug at 00:00:00.004 with 200 OK {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Debug} {EventName="HttpResponse", StatusCode=200, Elapsed=5, Endpoint="http://localhost:5000/api/test/debug", HttpMethod="POST", RequestId="yyy", RequestPath="/api/test/debug", SpanId="|yyy.", TraceId="yyy", ParentId="", ConnectionId="yyy"}
    
  • Information

    • Writes basic response timing/status message
    [12:57:24 INF] POST http://localhost:5000/api/test/info at 00:00:00.001 with 200 OK {Crip.AspNetCore.Logging.RequestLoggingMiddleware.Test.Info} {EventName="HttpResponse", StatusCode=200, Elapsed=2, Endpoint="http://localhost:5000/api/test/info", HttpMethod="POST", RequestId="zzz", RequestPath="/api/test/info", SpanId="|zzz.", TraceId="zzz", ParentId="", ConnectionId="zzz"}
    
  • Any other level will not write logs at all.

Configure verbosity for controller

Each controller has its own source context. This allows configure specific verbosity for a controller. If controller is named OrdersController, you can set verbosity for it in configuration:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware": "None",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware.Orders": "Trace"
    }
  }
}

In this case only OrdersController requests/responses will be written to logs.

Configure verbosity for controller method

Each controller method has its own source context. This allows configure specific verbosity for a controller method. If controller is named OrdersController and you want see requests going to Index method, you can set verbosity for it in configuration:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware": "None",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware.Orders.Index": "Trace"
    }
  }
}

In this case only OrdersController Index method requests/responses will be written to logs.

Configure verbosity for mapped method

When registering methods like in net6.0 minimal API, you can provide name, and that name will be used for logging context:

app
    .MapGet("/", () => Results.Json(new { status = "OK" }))
    .WithName("SomeRouteName");

You can set verbosity for it in configuration:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware": "None",
      "Crip.AspNetCore.Logging.RequestLoggingMiddleware.SomeRouteName": "Trace"
    }
  }
}

In this case only this method requests/responses will be written to logs.

If there is no name for request method (for example, unknown controller), Crip.AspNetCore.Logging.RequestLoggingMiddleware context will be used.


Configure verbosity for HTTP client

When you register client message handler with type .AddHttpMessageHandler<LoggingHandler<MyHttpClient>>(), this value is used as source context postfix.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Crip.AspNetCore.Logging.LoggingHandler": "None",
      "Crip.AspNetCore.Logging.LoggingHandler.MyHttpClient": "Trace"
    }
  }
}

In this case only MyHttpClient requests/responses will be written to logs.

Filter endpoints

If there is some endpoints you would like to exclude from logs, you can configure predicate:

services.AddRequestLoggingExclude("/images*", "/swagger*")

Or if you like to include only API requests in logging:

services.AddSingleton<IHttpRequestPredicate>(provider =>
    new EndpointPredicate(false, "/api*"));

Or create your own IHttpRequestPredicate implementation and add it to service collection.

Filter logged content

By default AuthorizationHeaderLoggingMiddleware is added to DI. You can create your own implementations of the IHeaderLogMiddleware or IRequestContentLogMiddleware to modify logged content for your own needs.

IHeaderLogMiddleware

AuthorizationHeaderLoggingMiddleware implements IHeaderLogMiddleware interface and will hide Authorization header values replacing value with *****.

[ 15:26:52 VRB ] GET http://localhost:5000/api/test HTTP/1.1
Connection: keep-alive
Authorization: Bearer *****
Host: localhost:5000

To hide custom authorization header value you can configure options (where header name is case insensitive):

services
    .AddRequestLogging(options =>
    {
        options.AuthorizationHeaders.AuthorizationHeaderNames.Add("x-auth");
    })
[ 15:26:52 VRB ] GET http://localhost:5000/api/test HTTP/1.1
Connection: keep-alive
X-Auth: Basic *****
Host: localhost:5000

You can add CookieHeaderLoggingMiddleware to avoid long cookie value write to logs:

services
    .AddRequestLogging()
    .AddRequestLoggingCookieValueMiddleware();
[ 15:34:27 VRB ] GET http://localhost:5000/api/test HTTP/1.1
Connection: keep-alive
Accept-Encoding: gzip, deflate, br
Cookie: a=Rtgyhjk456***
Host: localhost:5000
IRequestContentLogMiddleware

If you need modify content before you log it - you can implement IRequestContentLogMiddleware. Crip.AspNetCore.Logging.LongJsonContent library provides some implementations for middleware:

  • LongJsonContentMiddleware

For more technical details take a look in example projects:

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Crip.AspNetCore.Logging:

Package Downloads
Crip.AspNetCore.Logging.LongJsonContent

AspNetCore request logging middleware.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.0 201 7/4/2023
2.0.0-rc.11 77 7/3/2023
2.0.0-rc.10 72 7/3/2023
2.0.0-rc.7 115 7/3/2023
2.0.0-rc.6 79 7/2/2023
2.0.0-rc.2 74 7/2/2023
1.1.3 395 8/26/2022
1.1.2 380 8/26/2022
1.1.0 372 8/26/2022
1.0.4 375 8/25/2022
1.0.2 406 12/1/2020
1.0.2-rc.13 203 12/1/2020
1.0.2-beta.12 200 12/1/2020
1.0.2-alpha.11 201 12/1/2020
1.0.1.5 405 12/1/2020
1.0.0.22 371 11/28/2020
1.0.0.21 365 11/28/2020
1.0.0 375 8/25/2022