【C#】HttpClientの通信ログを出力してリクエスト内容を確認する方法

目次

概要

IHttpClientFactory を使用している場合、ログ設定を変更するだけで HTTP リクエストの開始、終了、ヘッダー情報、ステータスコードなどの通信詳細をログに出力できます。 APIとの通信トラブル時に「どんなヘッダーを送ったか」「どのURLにアクセスしたか」を追跡するために非常に有効なデバッグ手段です。

仕様(入出力)

  • 入力: appsettings.json でのログレベル設定。
  • 出力: コンソール等のログ出力先に表示されるHTTP通信のトレース情報。
  • 前提: Microsoft.Extensions.Http, Microsoft.Extensions.Logging.Console 等のパッケージを使用。

基本の使い方

appsettings.jsonLogging セクションで、System.Net.Http.HttpClient 名前空間のレベルを Trace または Information に設定します。

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      // HttpClientのログを詳細に出力する設定
      "System.Net.Http.HttpClient": "Trace"
    }
  }
}

コード全文

設定ファイルと、ログ出力を有効にしたコンソールアプリケーションの完全な実装例です。

1. 必要なパッケージ

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",
      // ここを Trace にすると詳細なヘッダー情報まで出ます
      // Information だとリクエスト開始・終了のみが出ます
      "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. 設定ファイルの読み込み
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .Build();

        // 2. DIコンテナとロギングのセットアップ
        var services = new ServiceCollection();

        services.AddLogging(builder =>
        {
            builder.AddConfiguration(configuration.GetSection("Logging"));
            builder.AddConsole(); // コンソールに出力
        });

        // HttpClientの登録
        services.AddHttpClient();
        
        // 実行クラスの登録
        services.AddTransient<MyWorker>();

        var provider = services.BuildServiceProvider();

        // 3. 実行
        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("処理を開始します。");

        // クライアント生成
        var client = _clientFactory.CreateClient();

        // テスト用URL
        var url = "http://httpbin.org/get";

        try
        {
            // ここで通信を行うと、コンソールに自動的にログが流れます
            var result = await client.GetStringAsync(url);
            
            Console.WriteLine("\n--- レスポンス結果 ---");
            Console.WriteLine(result.Substring(0, Math.Min(result.Length, 100)) + "...");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "通信エラーが発生しました");
        }
    }
}

実行時のログ出力例

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

カスタムポイント

  • 名前付きクライアントごとの制御: System.Net.Http.HttpClient.【クライアント名】.LogicalHandler というカテゴリ名になるため、特定のAPIクライアントだけログを出すといった細かい制御が可能です。
  • 出力内容の調整: Information レベルにすると「開始」と「終了(所要時間)」だけが出力され、ヘッダー情報は省略されます。本番環境などログ量を抑えたい場合に適しています。

注意点

  1. ボディ(中身)は出ない: 標準のログ機能では、セキュリティとパフォーマンスの観点からリクエストボディ(JSONの中身など)は出力されません。ボディまで見たい場合は独自の DelegatingHandler を実装する必要があります。
  2. 機密情報: Trace レベルにすると Authorization ヘッダーなどもログに残る可能性があります。ログファイルの管理には十分注意し、必要であれば RedactLoggedHeaders オプションで特定のヘッダーを伏せ字にする設定を行ってください。

応用

リクエスト/レスポンスのボディも含めてログ出力する

標準機能では不足する場合、カスタムハンドラを挟み込みます。

public class LoggingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // リクエストログ出力(ここで Content を読み取って表示するなど)
        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);

        // レスポンスログ出力
        return response;
    }
}

// 登録時にハンドラを追加
services.AddHttpClient("MyClient")
    .AddHttpMessageHandler<LoggingHandler>();

まとめ

HttpClientの通信内容を確認するには、appsettings.jsonSystem.Net.Http.HttpClient のログレベルを Trace に設定するのが最も手軽な方法です。これによりリクエストURL、メソッド、ヘッダー情報、ステータスコード、所要時間が自動的に記録されるようになり、通信エラーの原因調査が容易になります。ただし、リクエストボディの内容までは出力されないため、より詳細なデバッグが必要な場合はカスタムハンドラの導入を検討する必要があります。

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

この記事を書いた人

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

目次