[C#]How to Output HttpClient Communication Logs and Check Request Content

目次

Overview

When using IHttpClientFactory, you can output communication details such as HTTP request starts, ends, headers, and status codes simply by changing the log settings. This is a very effective debugging method for tracking what headers were sent or which URLs were accessed during API communication troubleshooting.

Specifications (Input/Output)

  • Input: Log level settings in appsettings.json.
  • Output: HTTP communication trace information displayed in the console or other log destinations.
  • Prerequisites: Uses packages such as Microsoft.Extensions.Http and Microsoft.Extensions.Logging.Console.

Basic Usage

In the Logging section of appsettings.json, set the level for the System.Net.Http.HttpClient namespace to Trace or Information.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      // Setting to output detailed HttpClient logs
      "System.Net.Http.HttpClient": "Trace"
    }
  }
}

Full Code Example

Below is a complete implementation example of a console application with the configuration file and logging enabled.

1. Required Packages

dotnet add package Microsoft.Extensions.Http
dotnet add package Microsoft.Extensions.Logging.Console
dotnet add package Microsoft.Extensions.Configuration.Json

2. appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "System": "Warning",
      // Setting this to Trace will show detailed header information.
      // Information will only show request start and end.
      "System.Net.Http.HttpClient": "Trace"
    }
  }
}

3. Program.cs & Worker

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
    static async Task Main()
    {
        // 1. Load configuration file
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .Build();

        // 2. Setup DI container and logging
        var services = new ServiceCollection();

        services.AddLogging(builder =>
        {
            builder.AddConfiguration(configuration.GetSection("Logging"));
            builder.AddConsole(); // Output to console
        });

        // Register HttpClient
        services.AddHttpClient();
        
        // Register the execution class
        services.AddTransient<MyWorker>();

        var provider = services.BuildServiceProvider();

        // 3. Execute
        var worker = provider.GetRequiredService<MyWorker>();
        await worker.RunAsync();
    }
}

public class MyWorker
{
    private readonly IHttpClientFactory _clientFactory;
    private readonly ILogger<MyWorker> _logger;

    public MyWorker(IHttpClientFactory clientFactory, ILogger<MyWorker> logger)
    {
        _clientFactory = clientFactory;
        _logger = logger;
    }

    public async Task RunAsync()
    {
        _logger.LogInformation("Starting process.");

        // Create client
        var client = _clientFactory.CreateClient();

        // Test URL
        var url = "http://httpbin.org/get";

        try
        {
            // Communication logs will automatically flow to the console here
            var result = await client.GetStringAsync(url);
            
            Console.WriteLine("\n--- Response Result ---");
            Console.WriteLine(result.Substring(0, Math.Min(result.Length, 100)) + "...");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "A communication error occurred");
        }
    }
}

Log Output Example during Execution

trce: System.Net.Http.HttpClient.Default.LogicalHandler[100]
      Start processing HTTP request GET http://httpbin.org/get
trce: System.Net.Http.HttpClient.Default.ClientHandler[100]
      Sending HTTP request GET http://httpbin.org/get
trce: System.Net.Http.HttpClient.Default.ClientHandler[101]
      Received HTTP response headers after 150.5ms - 200
trce: System.Net.Http.HttpClient.Default.LogicalHandler[101]
      End processing HTTP request after 160.2ms - 200

Customization Points

  • Control per Named Client: The category name becomes System.Net.Http.HttpClient.[ClientName].LogicalHandler, allowing you to enable logs only for specific API clients.
  • Adjusting Output Detail: Setting the level to Information outputs only “Start” and “End (Duration),” omitting header information. This is suitable for production environments where you want to reduce log volume.

Important Notes

  • Bodies are not included: Standard logging does not output request bodies (such as JSON content) for security and performance reasons. To see the body, you must implement a custom DelegatingHandler.
  • Sensitive Information: At the Trace level, headers like Authorization may be recorded in the logs. Manage log files carefully and use the RedactLoggedHeaders option to mask specific headers if necessary.

Advanced Usage

Logging Request/Response Bodies

If the standard features are insufficient, you can insert a custom handler.

public class LoggingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Output request log (read and display Content here, etc.)
        Console.WriteLine($"Request: {request.RequestUri}");
        if (request.Content != null)
        {
             string body = await request.Content.ReadAsStringAsync();
             Console.WriteLine($"Body: {body}");
        }

        var response = await base.SendAsync(request, cancellationToken);

        // Output response log
        return response;
    }
}

// Add handler during registration
services.AddTransient<LoggingHandler>();
services.AddHttpClient("MyClient")
    .AddHttpMessageHandler<LoggingHandler>();

Conclusion

The easiest way to check HttpClient communication is to set the log level for System.Net.Http.HttpClient to Trace in appsettings.json. This automatically records the request URL, method, header information, status code, and duration, making it easy to investigate the causes of communication errors. However, since it does not output the request body, you should consider implementing a custom handler if more detailed debugging is required.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次