Sdílet prostřednictvím


Protokolování HTTP v ASP.NET Core

Note

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Warning

Tato verze ASP.NET Core již není podporována. Pro více informací se podívejte na Zásady podpory .NET a .NET Core. Aktuální vydání tohoto článku najdete v verzi .NET 9.

Protokolování protokolu HTTP je prostřední vrstva aplikace, která zaznamenává informace o příchozích požadavcích a odpovědích protokolu HTTP. Protokolování HTTP poskytuje záznamy obsahující:

  • Informace o požadavku HTTP
  • Obecné vlastnosti
  • Headers
  • Body
  • Informace o odpovědi HTTP

Protokolování HTTP může:

  • Protokolujte všechny požadavky a odpovědi nebo pouze žádosti a odpovědi, které splňují určitá kritéria.
  • Vyberte, které části požadavku a odpovědi se protokolují.
  • Umožňuje redigovat citlivé informace z protokolů.

Protokolování HTTP může snížit výkon aplikace, zejména při protokolování těla požadavků a odpovědí. Při výběru polí, která se mají protokolovat, zvažte dopad na výkon. Otestujte dopad na výkon vybraných vlastností protokolování.

Warning

Protokolování HTTP může potenciálně protokolovat identifikovatelné osobní údaje (PII). Zvažte riziko a vyhněte se protokolování citlivých informací. Další informace o redigování najdete v redigování citlivých dat.

Povolte protokolování HTTP

Protokolování HTTP je povoleno voláním AddHttpLogging a UseHttpLogging, jak je znázorněno v následujícím příkladu:

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();

Prázdná lambda v předchozím příkladu volání funkce AddHttpLogging přidá middleware s výchozí konfigurací. Protokolování HTTP ve výchozím nastavení protokoluje běžné vlastnosti, jako je cesta, stavový kód a hlavičky pro požadavky a odpovědi.

Přidejte do appsettings.Development.json souboru následující řádek na "LogLevel": { úrovni, aby se zobrazily protokoly HTTP:

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

Ve výchozí konfiguraci se požadavek a odpověď zaprotokolují jako dvojice zpráv podobných následujícímu příkladu:

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

Možnosti protokolování HTTP

Pokud chcete nakonfigurovat globální možnosti pro Middleware protokolování HTTP, zavolejte AddHttpLogging v Program.cs, pomocí lambda ke konfiguraci 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();

Note

V předchozí ukázce a následujících ukázkách se UseHttpLogging volá po UseStaticFiles, takže protokolování HTTP není zapnuté pro statické soubory. Chcete-li povolit protokolování statických souborů HTTP, zavolejte UseHttpLogging před UseStaticFiles.

LoggingFields

HttpLoggingOptions.LoggingFields je příznak výčtu, který konfiguruje konkrétní části požadavku a odpovědi na protokol. LoggingFields výchozí hodnota RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.

RequestHeaders a ResponseHeaders

RequestHeaders a ResponseHeaders jsou sady hlaviček HTTP, které jsou protokolovány. Hodnoty hlaviček se protokolují jenom pro názvy hlaviček, které jsou v těchto kolekcích. Následující kód přidá sec-ch-ua do RequestHeaders, takže hodnota záhlaví sec-ch-ua je zaznamenána. Přidá MyResponseHeader k ResponseHeaders, takže hodnota hlavičky MyResponseHeader je zaznamenána. Pokud jsou tyto řádky odebrány, hodnoty těchto záhlaví jsou [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 poskytuje konfiguraci pro výběr kódování, které se má použít pro určitý typ média.

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();

Tento přístup lze použít také k povolení protokolování dat, která nejsou ve výchozím nastavení protokolována (například data formuláře, která můžou mít typ média, například application/x-www-form-urlencoded ).multipart/form-data

Metody MediaTypeOptions

RequestBodyLogLimit a 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

Nastavení CombineLogs na true konfiguruje middleware ke konsolidaci všech jeho povolených záznamů pro požadavek a odpověď do jednoho záznamu na konci. To zahrnuje požadavek, text požadavku, odpověď, text odpovědi a dobu trvání.

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();

Konfigurace specifická pro koncový bod

Pro konfiguraci specifickou pro koncový bod v minimálních aplikacích WithHttpLogging API je k dispozici metoda rozšíření. Následující příklad ukazuje, jak nakonfigurovat protokolování HTTP pro jeden koncový bod:

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

Pro konfiguraci specifickou pro koncový bod v aplikacích, které používají kontrolery, [HttpLogging] je atribut k dispozici. Atribut lze použít také v minimálních aplikacích API, jak je znázorněno v následujícím příkladu:

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

IHttpLoggingInterceptor

IHttpLoggingInterceptor je rozhraní pro službu, která se dá implementovat za účelem zpracování zpětného volání na požadavek a odpověď pro přizpůsobení podrobností, které se zaprotokolují. Nejprve se použijí všechna nastavení protokolu specifická pro koncový bod a pak je možné je v těchto zpětných voláních přepsat. Implementace může:

  • Zkontrolujte požadavek nebo odpověď.
  • Povolte nebo zakažte libovolný HttpLoggingFields.
  • Upravte, kolik textu požadavku nebo odpovědi se protokoluje.
  • Přidejte do protokolů vlastní pole.

Zaregistrujte implementaci IHttpLoggingInterceptor voláním AddHttpLoggingInterceptor v Program.cs. Pokud je zaregistrovaných více IHttpLoggingInterceptor instancí, spustí se v pořadí, v jakém byly zaregistrovány.

Následující příklad ukazuje, jak zaregistrovat implementaci IHttpLoggingInterceptor :

var builder = WebApplication.CreateBuilder(args);

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

Následující příklad je IHttpLoggingInterceptor implementace, která:

  • Zkontroluje metodu požadavku a zakáže protokolování požadavků POST.
  • Pro požadavky kromě POST:
    • Rediguje cestu žádosti, hlavičky žádosti a hlavičky odpovědi.
    • Přidá do protokolů požadavků a odpovědí vlastní pole a hodnoty polí.
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");
    }
}

Při použití tohoto zachytávače požadavek POST nevytváří žádné záznamy, ani když je protokolování HTTP nakonfigurováno k záznamu HttpLoggingFields.All. Požadavek GET generuje protokoly podobné následujícímu příkladu:

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

Pořadí priority konfigurace protokolování

Následující seznam ukazuje pořadí priorit konfigurace protokolování:

  1. Globální konfigurace z HttpLoggingOptions, nastavená voláním AddHttpLogging.
  2. Konfigurace specifická pro koncový bod, vycházející z atributu [HttpLogging] nebo rozšiřující metody WithHttpLogging, přepisují globální konfiguraci.
  3. IHttpLoggingInterceptor se volá s výsledky a může dále upravit konfiguraci na požadavek.

Protokolování HTTP je middleware, který protokoluje informace o příchozích požadavcích HTTP a odpovědích HTTP. Protokolování HTTP poskytuje záznamy obsahující:

  • Informace o požadavku HTTP
  • Obecné vlastnosti
  • Headers
  • Body
  • Informace o odpovědi HTTP

Protokolování HTTP je užitečné v několika scénářích:

  • Zaznamenává informace o příchozích požadavcích a odpovědích.
  • Vyfiltrujte, které části požadavku a odpovědi se protokolují.
  • Filtrování hlaviček, které se mají protokolovat.

Protokolování HTTP může snížit výkon aplikace, zejména při protokolování těla požadavků a odpovědí. Při výběru polí, která se mají protokolovat, zvažte dopad na výkon. Otestujte dopad na výkon vybraných vlastností protokolování.

Warning

Protokolování HTTP může zaznamenávat potenciálně osobně identifikovatelné údaje (PII). Zvažte riziko a vyhněte se protokolování citlivých informací.

Povolení protokolování HTTP

Protokolování HTTP je povoleno pomocí UseHttpLogging, které přidává middleware pro protokolování 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();

Protokolování HTTP ve výchozím nastavení protokoluje běžné vlastnosti, jako je cesta, stavový kód a hlavičky pro požadavky a odpovědi. Přidejte do appsettings.Development.json souboru následující řádek na "LogLevel": { úrovni, aby se zobrazily protokoly HTTP:

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

Výstup je protokolován jako jedna zpráva na LogLevel.Informationadrese .

Ukázkový výstup požadavku

Možnosti protokolování HTTP

Chcete-li nakonfigurovat middleware protokolování HTTP, zavolejte AddHttpLogging v Program.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();

Note

V předchozí i následujících ukázkách se UseHttpLogging volá po UseStaticFiles, takže protokolování HTTP není povoleno pro statické soubory. Chcete-li povolit protokolování statických souborů HTTP, zavolejte UseHttpLogging před UseStaticFiles.

LoggingFields

HttpLoggingOptions.LoggingFields je příznak výčtu, který konfiguruje konkrétní části požadavku a odpovědi na protokol. HttpLoggingOptions.LoggingFields výchozí hodnota RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.

RequestHeaders

Headers jsou sadou hlaviček požadavků HTTP, které mohou být protokolovány. Hodnoty hlaviček jsou protokolovány pouze pro názvy hlaviček, které jsou v této kolekci. Následující kód zaznamená hlavičku "sec-ch-ua"požadavku . Pokud je logging.RequestHeaders.Add("sec-ch-ua"); odebrán, hodnota hlavičky požadavku "sec-ch-ua" je upravena. Zvýrazněný kód volá HttpLoggingOptions.RequestHeaders a HttpLoggingOptions.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 poskytuje konfiguraci pro výběr kódování, které se má použít pro určitý typ média.

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();

Tento přístup lze použít také k povolení protokolování dat, která nejsou ve výchozím nastavení protokolována. Například data formuláře, která mohou mít typ média, například application/x-www-form-urlencoded nebo multipart/form-data.

Metody MediaTypeOptions

RequestBodyLogLimit a 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();

Redigování citlivých údajů

Protokolování HTTP s redukcí je možné povolit voláním AddHttpLoggingRedaction:

var builder = WebApplication.CreateBuilder(args);

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

builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op => { });

Další informace o knihovně pro redakci dat v .NET najdete v Redakce dat v .NET.

Možnosti úpravy protokolování

Pokud chcete nakonfigurovat možnosti protokolování s využitím redakce, zavolejte AddHttpLoggingRedaction v Program.cs s využitím lambda pro konfiguraci 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();

S předchozí konfigurací redakce je výstup podobný následujícímu:

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

Note

Cesta /home požadavku není zaprotokolována, protože je součástí ExcludePathStartsWith vlastnosti. http.request.header.accept a http.response.header.content-type byly redigovány Microsoft.Extensions.Compliance.Redaction.ErasingRedactor.

RequestPathLoggingMode

RequestPathLoggingMode určuje, jak je cesta požadavku protokolována, zda Formatted nebo Structured, nastavena pomocí IncomingPathLoggingMode:

  • Formatted: Zaznamená cestu požadavku bez parametrů.
  • Structured: Zaznamená cestu požadavku s zahrnutými parametry.
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 určuje, jak mají být parametry trasy v cestě požadavku redigovány, zda Strict, Loose nebo None, nastaveny pomocí HttpRouteParameterRedactionMode:

  • Strict: Parametry trasy požadavku jsou považovány za citlivé, vyžadují explicitní anotace s klasifikací dat a jsou ve výchozím nastavení upraveny.
  • Loose: Všechny parametry jsou ve výchozím nastavení považovány za nerozlišivé a zahrnuté as-is.
  • None: Parametry trasy nejsou skryty bez ohledu na to, zda jsou přítomny poznámky ke klasifikaci dat.
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 mapuje hlavičky požadavků na jejich klasifikaci dat, která určuje, jak jsou upraveny:

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

ResponseHeadersDataClasses, podobně jako RequestHeadersDataClasses', ale pro hlavičky odpovědi:

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 mapuje parametry trasování na jejich klasifikaci dat:

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 určuje cesty, které by měly být vyloučeny z protokolování zcela:

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 umožňuje hlásit chybějící trasy. Pokud je nastaveno true, zapisuje celou cestu tras, které nejsou identifikovány užitím Směrování, místo zapisování Unknown hodnoty atributu cesty.

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();