LoggingHandler
Namespace: RA.Utilities.Integrations.DelegatingHandlers
The LoggingHandler is a DelegatingHandler
that acts as middleware for your HttpClient instances.
Its primary purpose is to intercept and log the details of outgoing HTTP requests and their corresponding responses.
This provides a comprehensive audit trail and invaluable diagnostic information for any communication between your services and external APIs.
It achieves this by performing the following steps within the HttpClient pipeline:
- Executes the Request: It passes the request down the handler chain (using
base.SendAsync) and waits for theHttpResponseMessageto return. - Logs the Request:
After the call completes, it constructs a detailed
HttpRequestLogTemplateobject containing:
- The request scheme, host, method, path, and query string.
- Request headers.
- The request body (which it intelligently tries to parse as JSON for better structured logging).
- Logs the Response: It then constructs an
HttpResponseLogTemplateobject with:
- The HTTP status code.
- Response headers.
- The response body.
- Structured Logging:
It uses
ILoggerto write these objects as structured logs. This is far more powerful than plain text logging, as it allows you to easily search, filter, and analyze your HTTP traffic in logging tools like Seq, Datadog, or the ELK stack.
The key benefit is deep visibility. When debugging an issue, you can see the exact payload your application sent to another service and the exact response it received, which is critical for troubleshooting integration problems.
⚙️ How It's Used
This handler is typically added to an HttpClient during its registration in Program.cs:
services.AddHttpClientIntegration<IMyApiClient, MyApiClient, MyApiSettings>(...)
.AddLoggingHandler(); // <-- This adds the handler to the pipeline
Log Levels & Correlation
Both the request and the response logs are written at LogLevel.Information, and logging is skipped entirely when Information is not enabled. After the response returns, the handler starts a stopwatch and reads the request/response bodies for logging — the logged Duration therefore measures the time spent capturing the log payload, not the network call. If that capture takes longer than the handler's warning threshold (35 seconds), an additional Warning entry is written: HttpClient call to {Method} {Url} took too long ({ElapsedMilliseconds} ms). When a body cannot be parsed as JSON, it is logged as a plain string with a Warning explaining the deserialization failure.
Request correlation (X-Request-Id) is carried by the ambient logging scope — for example the one created by LoggingMiddleware or the Serilog RequestIdEnricher from RA.Utilities.Logging.Core — not by properties on the log templates.
This handler was previously named RequestResponseLoggingHandler. In v10.2.0 it was renamed to LoggingHandler; its constructor still takes only an ILogger<LoggingHandler>, and AddLoggingHandler() attaches it — only update your code if you construct or register the handler manually. See the migration guide.