次の方法で共有


ASP.NET Core での HTTP ログ

これは、この記事の最新バージョンではありません。 現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、 この記事の .NET 9 バージョンを参照してください。

HTTP ログは、受信 HTTP 要求と HTTP 応答に関する情報をログするミドルウェアです。 HTTP ログにより、次のログが提供されます。

  • HTTP 要求情報
  • 共通プロパティ
  • ヘッダー
  • 本文
  • HTTP 応答情報

HTTP ログは次のことができます。

  • すべての要求と応答をログするか、特定の条件を満たす要求と応答のみをログする。
  • 要求と応答のどの部分をログするかを選択する。
  • ログの機密情報を編集できるようにする。

HTTP ログは、特に要求本文と応答本文をログに記録する場合に、 アプリのパフォーマンスを低下させることができます。 ログに記録するフィールドを選択する際には、パフォーマンスへの影響を考慮してください。 選択したログ プロパティがパフォーマンスに及ぼす影響をテストします。

警告

HTTP ログによって、個人を特定できる情報 (PII) がログされるおそれがあります。 リスクを考慮し、機密情報をログに記録しないようにします。 編集の詳細については、機密データの編集を確認してください

HTTP ログを有効にする

HTTP ログを有効にするには、次の例に示すように、AddHttpLoggingUseHttpLogging を呼び出します。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");

app.Run();

上記の例では、AddHttpLogging を呼び出す箇所の空のラムダ式により、既定の構成でミドルウェアが追加されます。 既定では、HTTP ログにより、要求と応答についてのパス、状態コード、ヘッダーといった一般的なプロパティがログされます。

HTTP のログが表示されるように、appsettings.Development.json ファイルの "LogLevel": { レベルに次の行を追加します。

"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

既定の構成では、要求と応答は、次の例のようなメッセージのペアとしてログされます。

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/2
      Method: GET
      Scheme: https
      PathBase:
      Path: /
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
      Host: localhost:52941
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.61
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-US,en;q=0.9
      Upgrade-Insecure-Requests: [Redacted]
      sec-ch-ua: [Redacted]
      sec-ch-ua-mobile: [Redacted]
      sec-ch-ua-platform: [Redacted]
      sec-fetch-site: [Redacted]
      sec-fetch-mode: [Redacted]
      sec-fetch-user: [Redacted]
      sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: text/plain; charset=utf-8
      Date: Tue, 24 Oct 2023 02:03:53 GMT
      Server: Kestrel

HTTP ログのオプション

HTTP ログ ミドルウェアのグローバル オプションを構成するには、AddHttpLoggingProgram.cs を呼び出し、ラムダ式を使って HttpLoggingOptions を構成します。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging();

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

前のサンプルと次のサンプルでは、 UseHttpLoggingUseStaticFiles後に呼び出されるため、静的ファイルに対して HTTP ログは有効になりません。 静的ファイル HTTP ログを有効にするには、UseHttpLogging の前に UseStaticFiles を呼び出します。

LoggingFields

HttpLoggingOptions.LoggingFields は、要求と応答の特定の部分をログに記録するよう構成する列挙型のフラグです。 LoggingFields の既定値は RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders です。

RequestHeaders および ResponseHeaders

RequestHeadersResponseHeaders は、ログされる HTTP ヘッダーのセットです。 これらのコレクションにヘッダー名が含まれているヘッダー値のみがログされます。 次のコードでは sec-ch-uaRequestHeaders に追加しているため、sec-ch-ua ヘッダーの値はログされます。 また、MyResponseHeaderResponseHeaders に追加しているため、MyResponseHeader ヘッダーの値もログされます。 これらの行を削除した場合、これらのヘッダーの値は [Redacted] になります。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging();

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions

MediaTypeOptions では、特定のメディアの種類に対して使用するエンコードを選択するための構成が提供されます。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging();

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

この方法を使って、既定ではログされないデータ (たとえば、application/x-www-form-urlencodedmultipart/form-data などのメディアの種類を持つ可能性があるフォーム データなど) のログを有効にすることもできます。

MediaTypeOptions メソッド

RequestBodyLogLimit および ResponseBodyLogLimit

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging();

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

CombineLogs

CombineLogstrue に設定すると、要求と応答に対して有効なすべてのログを、最後に 1 つのログに統合するようにミドルウェアを構成できます。 これには、要求、要求本文、応答、応答本文、期間が含まれます。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
    logging.CombineLogs = true;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging();

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

エンドポイント固有の構成

Minimal API アプリのエンドポイント固有の構成では、WithHttpLogging 拡張メソッドを使用できます。 次の例は、1 つのエンドポイントの HTTP ログを構成する方法を示しています。

app.MapGet("/response", () => "Hello World! (logging response)")
    .WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);

コントローラーを使用するアプリのエンドポイント固有の構成では、 [HttpLogging] 属性 を使用できます。 この属性は、次の例に示すように、Minimal API アプリでも使用できます。

app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
    () => "Hello World! (logging duration)");

IHttpLoggingInterceptor

IHttpLoggingInterceptor は、ログする詳細をカスタマイズするために、要求ごとおよび応答ごとのコールバックを処理するために実装できるサービス用のインターフェイスです。 エンドポイント固有のログ設定が最初に適用され、その後これらのコールバックでオーバーライドできます。 実装では、次のことができます。

  • 要求または応答を検査する。
  • 任意の HttpLoggingFields を有効または無効にする。
  • ログされる要求本文または応答本文の量を調整する。
  • ログにカスタム フィールドを追加する。

IHttpLoggingInterceptorAddHttpLoggingInterceptor を呼び出して、Program.cs の実装を登録します。 複数の IHttpLoggingInterceptor インスタンスが登録されている場合は、登録された順序で実行されます。

次の例は、IHttpLoggingInterceptor の実装を登録する方法を示しています。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();

次の例は、以下のような IHttpLoggingInterceptor の実装です。

  • 要求メソッドを検査し、POST 要求のログを無効にします。
  • POST 以外の要求の場合:
    • 要求パス、要求ヘッダー、応答ヘッダーを編集します。
    • 要求と応答のログに、カスタム フィールドとフィールド値を追加します。
using Microsoft.AspNetCore.HttpLogging;

namespace HttpLoggingSample;

internal sealed class SampleHttpLoggingInterceptor : IHttpLoggingInterceptor
{
    public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
    {
        if (logContext.HttpContext.Request.Method == "POST")
        {
            // Don't log anything if the request is a POST.
            logContext.LoggingFields = HttpLoggingFields.None;
        }

        // Don't enrich if we're not going to log any part of the request.
        if (!logContext.IsAnyEnabled(HttpLoggingFields.Request))
        {
            return default;
        }

        if (logContext.TryDisable(HttpLoggingFields.RequestPath))
        {
            RedactPath(logContext);
        }

        if (logContext.TryDisable(HttpLoggingFields.RequestHeaders))
        {
            RedactRequestHeaders(logContext);
        }

        EnrichRequest(logContext);

        return default;
    }

    public ValueTask OnResponseAsync(HttpLoggingInterceptorContext logContext)
    {
        // Don't enrich if we're not going to log any part of the response
        if (!logContext.IsAnyEnabled(HttpLoggingFields.Response))
        {
            return default;
        }

        if (logContext.TryDisable(HttpLoggingFields.ResponseHeaders))
        {
            RedactResponseHeaders(logContext);
        }

        EnrichResponse(logContext);

        return default;
    }

    private void RedactPath(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter(nameof(logContext.HttpContext.Request.Path), "RedactedPath");
    }

    private void RedactRequestHeaders(HttpLoggingInterceptorContext logContext)
    {
        foreach (var header in logContext.HttpContext.Request.Headers)
        {
            logContext.AddParameter(header.Key, "RedactedHeader");
        }
    }

    private void EnrichRequest(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter("RequestEnrichment", "Stuff");
    }

    private void RedactResponseHeaders(HttpLoggingInterceptorContext logContext)
    {
        foreach (var header in logContext.HttpContext.Response.Headers)
        {
            logContext.AddParameter(header.Key, "RedactedHeader");
        }
    }

    private void EnrichResponse(HttpLoggingInterceptorContext logContext)
    {
        logContext.AddParameter("ResponseEnrichment", "Stuff");
    }
}

このインターセプターにより、HttpLoggingFields.All をログするように HTTP ログが構成されていても、POST 要求によってログが生成されることはありません。 GET 要求では、次の例のようなログが生成されます。

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Path: RedactedPath
      Accept: RedactedHeader
      Host: RedactedHeader
      User-Agent: RedactedHeader
      Accept-Encoding: RedactedHeader
      Accept-Language: RedactedHeader
      Upgrade-Insecure-Requests: RedactedHeader
      sec-ch-ua: RedactedHeader
      sec-ch-ua-mobile: RedactedHeader
      sec-ch-ua-platform: RedactedHeader
      sec-fetch-site: RedactedHeader
      sec-fetch-mode: RedactedHeader
      sec-fetch-user: RedactedHeader
      sec-fetch-dest: RedactedHeader
      RequestEnrichment: Stuff
      Protocol: HTTP/2
      Method: GET
      Scheme: https
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      Content-Type: RedactedHeader
      MyResponseHeader: RedactedHeader
      ResponseEnrichment: Stuff
      StatusCode: 200
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[4]
      ResponseBody: Hello World!
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[8]
      Duration: 2.2778ms

ログ構成の優先順位

次のリストは、ログ構成の優先順位を示しています。

  1. HttpLoggingOptions を呼び出して設定する、AddHttpLogging からのグローバル構成。
  2. WithHttpLogging 拡張メソッドからのエンドポイント固有の構成は、グローバル構成をオーバーライドします。
  3. IHttpLoggingInterceptor は結果と共に呼び出され、要求ごとに構成をさらに変更できます。

HTTP ログは、受信した HTTP 要求と HTTP 応答に関する情報をログに記録するミドルウェアです。 HTTP ログにより、次のログが提供されます。

  • HTTP 要求情報
  • 共通プロパティ
  • ヘッダー
  • 本文
  • HTTP 応答情報

HTTP ログは、複数のシナリオで次のことを行うのに役立ちます。

  • 受信した要求と応答に関する情報を記録する。
  • 要求と応答のどの部分をログに記録するかをフィルター処理する。
  • どのヘッダーをログに記録するかをフィルター処理する。

HTTP ログは、特に要求と応答の本文をログに記録する場合に、 アプリのパフォーマンスを低下させることができます。 ログに記録するフィールドを選択する際には、パフォーマンスへの影響を考慮してください。 選択したログ プロパティがパフォーマンスに及ぼす影響をテストします。

警告

HTTP ログによって、個人を特定できる情報 (PII) がログに記録されるおそれがあります。 リスクを考慮し、機密情報をログに記録しないようにします。

HTTP ログを有効にする

HTTP ログは UseHttpLogging で有効になります。これによって、HTTP ログ ミドルウェアが追加されます。

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Hello World!");

app.Run();

既定では、HTTP ログにより、要求と応答について、パス、状態コード、ヘッダーなどの一般的なプロパティがログに記録されます。 HTTP のログが表示されるように、appsettings.Development.json ファイルの "LogLevel": { レベルに次の行を追加します。

 "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"

出力は、LogLevel.Information の単一のメッセージとしてログに記録されます。

要求出力のサンプル

HTTP ログのオプション

HTTP ログ ミドルウェアを構成するには、AddHttpLoggingProgram.cs を呼び出します。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

前のサンプルと次のサンプルでは、UseHttpLogging の後に UseStaticFiles が呼び出されるため、静的ファイルに対して HTTP ログは有効になりません。 静的ファイル HTTP ログを有効にするには、UseHttpLogging の前に UseStaticFiles を呼び出します。

LoggingFields

HttpLoggingOptions.LoggingFields は、要求と応答の特定の部分をログに記録するよう構成する列挙型のフラグです。 HttpLoggingOptions.LoggingFields の既定値は RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders です。

RequestHeaders

Headers は、ログ記録が許可されている HTTP 要求ヘッダーのセットです。 このコレクションにヘッダー名が含まれているヘッダー値のみがログに記録されます。 次のコードでは、要求ヘッダー "sec-ch-ua" がログに記録されます。 logging.RequestHeaders.Add("sec-ch-ua"); が削除された場合、要求ヘッダー "sec-ch-ua" の値が編集されます。 次の強調されているコードでは、HttpLoggingOptions.RequestHeadersHttpLoggingOptions.ResponseHeaders が呼び出されます。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

MediaTypeOptions

MediaTypeOptions では、特定のメディアの種類に対して使用するエンコードを選択するための構成が提供されます。

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

この方法を使用して、既定でログに記録されないデータのログ記録を有効にすることもできます。 たとえば、application/x-www-form-urlencodedmultipart/form-data などのメディアの種類を含むフォーム データなどです。

MediaTypeOptions メソッド

RequestBodyLogLimit および ResponseBodyLogLimit

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(logging =>
{
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("sec-ch-ua");
    logging.ResponseHeaders.Add("MyResponseHeader");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;

});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}

app.UseStaticFiles();

app.UseHttpLogging(); 

app.Use(async (context, next) =>
{
    context.Response.Headers["MyResponseHeader"] =
        new string[] { "My Response Header Value" };

    await next();
});

app.MapGet("/", () => "Hello World!");

app.Run();

機密データの編集

AddHttpLoggingRedactionを呼び出すことで、マスキングを使用した HTTP ログを有効にすることができます。

詳細については、次を参照してください。NET のデータ編集ライブラリについては、「 .NET のデータの編集」を参照してください。

編集オプションのログ記録

編集を使用してログ記録のオプションを構成するには、ラムダを使用してAddHttpLoggingRedactionProgram.csを呼び出してLoggingRedactionOptionsを構成します。

using Microsoft.Extensions.Compliance.Classification;

namespace HttpLoggingSample
{
    public static class MyTaxonomyClassifications
    {
        public static string Name => "MyTaxonomy";

        public static DataClassification Private => new(Name, nameof(Private));
        public static DataClassification Public => new(Name, nameof(Public));
        public static DataClassification Personal => new(Name, nameof(Personal));
    }
}
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

前の編集構成では、出力は次のようになります。

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[9]
      Request and Response:
      server.address: localhost:61361
      Path: /
      http.request.header.accept:
      Protocol: HTTP/2
      Method: GET
      Scheme: https
      http.response.header.content-type:
      StatusCode: 200
      Duration: 8.4684
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/2 GET https://localhost:61361/ - 200 - text/plain;+charset=utf-8 105.5334ms

要求パス /homeExcludePathStartsWith プロパティに含まれているため、ログに記録されません。 http.request.header.accept http.response.header.content-typeMicrosoft.Extensions.Compliance.Redaction.ErasingRedactorによって編集されました。

RequestPathLoggingMode

RequestPathLoggingModeは、Formattedによって設定される、StructuredまたはIncomingPathLoggingModeに関係なく、要求パスのログ記録方法を決定します。

  • Formatted: パラメーターなしで要求パスをログに記録します。
  • Structured: パラメーターを含む要求パスをログに記録します。
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

RequestPathParameterRedactionMode

RequestPathParameterRedactionModeは、Strictによって設定されたLooseNone、またはHttpRouteParameterRedactionModeに関係なく、要求パス内のルート パラメーターを編集する方法を指定します。

  • Strict: 要求ルート パラメーターは機密性が高いと見なされ、データ分類で明示的な注釈が必要であり、既定で編集されます。
  • Loose: すべてのパラメーターは機密性が高くないものと見なされ、既定で as-is 含まれます。
  • None: ルート パラメーターは、データ分類注釈の有無に関係なく編集されません。
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

RequestHeadersDataClasses

RequestHeadersDataClasses 要求ヘッダーをデータ分類にマップします。これは、編集方法を決定します。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

ResponseHeadersDataClasses

ResponseHeadersDataClassesRequestHeadersDataClassesに似ていますが、応答ヘッダーの場合:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

RouteParameterDataClasses

RouteParameterDataClasses は、ルート パラメーターをデータ分類にマップします。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

ExcludePathStartsWith

ExcludePathStartsWith は、ログから完全に除外する必要があるパスを指定します。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();

IncludeUnmatchedRoutes

IncludeUnmatchedRoutes では、一致しないルートをレポートできます。 trueに設定すると、path 属性の値をログに記録するのではなく、ルーティングによって識別されないルートのパス全体Unknownログに記録されます。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();

builder.Services.AddHttpLoggingRedaction(op =>
{
    op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
    op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
    op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
    op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
    op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
    {
        { "one", MyTaxonomyClassifications.Personal },
    };
    // Add the paths that should be filtered, with a leading '/'.
    op.ExcludePathStartsWith.Add("/home");
    op.IncludeUnmatchedRoutes = true;
});

var app = builder.Build();

app.UseHttpLogging();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();

app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");

app.Run();