DelegatingHandler that logs and times every outgoing HttpClient request.
dotnet add package Philiprehberger.HttpDebugHandlerDelegatingHandler that logs and times every outgoing HttpClient request.
dotnet add package Philiprehberger.HttpDebugHandler
using Philiprehberger.HttpDebugHandler;
// Default: writes to Console
var client = new HttpClient(new DebugHandler(new HttpClientHandler()));
// Custom callback
var handler = new DebugHandler(log =>
{
Console.WriteLine($"{log.Method} {log.RequestUri} => {log.StatusCode} in {log.ElapsedMilliseconds} ms");
})
{
InnerHandler = new HttpClientHandler()
};
var client = new HttpClient(handler);
var response = await client.GetAsync("https://example.com");
// Output: GET https://example.com/ => 200 in 142 ms
builder.Services.AddTransient<DebugHandler>();
builder.Services.AddHttpClient("my-client")
.AddHttpMessageHandler<DebugHandler>();
Enable request and/or response body logging:
var handler = new DebugHandler(log =>
{
Console.WriteLine($"{log.Method} {log.RequestUri} => {log.StatusCode}");
if (log.RequestBody is not null)
Console.WriteLine($" Request body: {log.RequestBody}");
if (log.ResponseBody is not null)
Console.WriteLine($" Response body: {log.ResponseBody}");
})
{
InnerHandler = new HttpClientHandler(),
CaptureRequestBody = true,
CaptureResponseBody = true,
MaxBodyCaptureSize = 4096 // optional, default is 65536 (64 KB)
};
Capture request and response headers:
var handler = new DebugHandler(log =>
{
if (log.RequestHeaders is not null)
foreach (var h in log.RequestHeaders)
Console.WriteLine($" > {h.Key}: {h.Value}");
if (log.ResponseHeaders is not null)
foreach (var h in log.ResponseHeaders)
Console.WriteLine($" < {h.Key}: {h.Value}");
})
{
InnerHandler = new HttpClientHandler(),
CaptureHeaders = true
};
Get notified when a request exceeds a time threshold:
var handler = new DebugHandler(log =>
{
Console.WriteLine($"{log.Method} {log.RequestUri} => {log.StatusCode} in {log.ElapsedMilliseconds} ms");
})
{
InnerHandler = new HttpClientHandler(),
SlowRequestThreshold = TimeSpan.FromSeconds(2),
OnSlowRequest = log =>
Console.WriteLine($"SLOW REQUEST: {log.Method} {log.RequestUri} took {log.ElapsedMilliseconds} ms")
};
RequestLog| Property | Type | Description |
|---|---|---|
Method | string | HTTP method (GET, POST, ...) |
RequestUri | Uri? | Request URL |
StatusCode | int | HTTP response status code |
ElapsedMilliseconds | long | Round-trip time in milliseconds |
Timestamp | DateTimeOffset | UTC time the request was sent |
RequestBody | string? | Request body (when CaptureRequestBody is enabled) |
ResponseBody | string? | Response body (when CaptureResponseBody is enabled) |
RequestHeaders | Dictionary<string, string>? | Request headers (when CaptureHeaders is enabled) |
ResponseHeaders | Dictionary<string, string>? | Response headers (when CaptureHeaders is enabled) |
DebugHandler| Member | Description |
|---|---|
DebugHandler() | Writes formatted log lines to Console |
DebugHandler(Action<RequestLog>) | Invokes the provided callback for every request |
CaptureRequestBody | bool — capture request body content (default false) |
CaptureResponseBody | bool — capture response body content (default false) |
CaptureHeaders | bool — capture request and response headers (default false) |
MaxBodyCaptureSize | int — max characters to capture per body (default 65536) |
SlowRequestThreshold | TimeSpan? — threshold for slow request detection |
OnSlowRequest | Action<RequestLog>? — callback for requests exceeding the threshold |
dotnet build src/Philiprehberger.HttpDebugHandler.csproj --configuration Release
If you find this project useful: