Protokolování HTTP v ASP.NET Core
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete ve verzi .NET 8 tohoto článku.
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 protokoly obsahující:
- Informace o požadavku HTTP
- Obecné vlastnosti
- Hlavičky
- Text
- 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í.
Upozorňující
Protokolování HTTP může potenciálně protokolovat identifikovatelné osobní údaje (PII). Vezměte riziko do úvahy a vyhněte se protokolování citlivých informací.
Povolení 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í 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.
Aby se zobrazily protokoly HTTP, přidejte do souboru appsettings.Development.json
na úrovni "LogLevel": {
následující řádek:
"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 middlewaru protokolování HTTP, zavolejte ho AddHttpLogging 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();
Poznámka:
V předchozí ukázce a následujících ukázkách se volá po UseStaticFiles
, UseHttpLogging
takže protokolování HTTP není povolené pro statické soubory. Chcete-li povolit protokolování HTTP statického souboru, zavolejte UseHttpLogging
před UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
je příznak výčtu, který konfiguruje konkrétní protokolované části požadavku a odpovědi. Výchozí hodnotou HttpLoggingOptions.LoggingFields
je 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 se přidá sec-ch-ua
do RequestHeaders, takže hodnota sec-ch-ua
hlavičky je zaznamenána. A přidá MyResponseHeader
do něj ResponseHeadershodnotu hlavičky, takže MyResponseHeader
se zaprotokoluje. 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 konkrétní 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
true
Nastavení CombineLogs pro konfiguraci middlewaru ke konsolidaci všech jeho povolených protokolů pro požadavek a odpověď do jednoho protokolu 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 libovolnou HttpLoggingFieldsmožnost .
- Upravte, kolik textu požadavku nebo odpovědi se protokoluje.
- Přidejte do protokolů vlastní pole.
Zaregistrujte implementaci IHttpLoggingInterceptor
voláním AddHttpLoggingInterceptor<T>
.Program.cs
Pokud je zaregistrovaných více IHttpLoggingInterceptor
instancí, spustí se v zaregistrované objednávce.
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 jiného než POST:
- Redacts request path, request headers, and response headers.
- 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 průsečíku požadavek POST negeneruje žádné protokoly, ani když je protokolování HTTP nakonfigurované pro protokolování 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í konfigurace protokolování priority
Následující seznam ukazuje pořadí priorit konfigurace protokolování:
- Globální konfigurace ze HttpLoggingOptionssady , nastavená voláním AddHttpLogging.
- Konfigurace specifická pro koncový bod z atributu
[HttpLogging]
WithHttpLogging nebo metody rozšíření přepíše globální konfiguraci. 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 protokoly obsahující:
- Informace o požadavku HTTP
- Obecné vlastnosti
- Hlavičky
- Text
- Informace o odpovědi HTTP
Protokolování HTTP je velmi účinné v několika scénářích, kdy provádí následující:
- Záznam informací o příchozích požadavcích a odpovědích
- Filtrování, které části požadavku a odpovědi se protokolují
- Filtrování záhlaví, která se mají protokolovat
Protokolování HTTP může snížit výkon aplikace, zejména při protokolování těl 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í.
Upozorňující
Protokolování HTTP může potenciálně protokolovat identifikovatelné osobní údaje (PII). Vezměte riziko do úvahy a vyhněte se protokolování citlivých informací.
Povolení protokolování HTTP
Protokolování HTTP se povoluje pomocí UseHttpLogging, čímž se přidá middleware 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 požadavků a odpovědí. Aby se zobrazily protokoly HTTP, přidejte do souboru appsettings.Development.json
na úrovni "LogLevel": {
následující řádek:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Výstup se protokoluje jako jedna zpráva v umístění LogLevel.Information
.
Možnosti protokolování HTTP
Chcete-li nakonfigurovat middleware protokolování HTTP, zavolejte AddHttpLogging v souboru 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();
Poznámka:
V předchozí ukázce a následujících ukázkách se volá po UseStaticFiles
, UseHttpLogging
takže protokolování HTTP není povolené pro statický soubor. Chcete-li povolit protokolování HTTP statického souboru, zavolejte UseHttpLogging
před UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
je příznak výčtu, který konfiguruje konkrétní protokolované části požadavku a odpovědi. Výchozí hodnotou HttpLoggingOptions.LoggingFields
je RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
Headers je sada hlaviček požadavků HTTP, které je možné protokolovat. Hodnoty hlaviček se protokolují pouze pro názvy hlaviček, které jsou v této kolekci. Následující kód zaznamená hlavičku požadavku "sec-ch-ua"
. Pokud se logging.RequestHeaders.Add("sec-ch-ua");
odebere, hodnota hlavičky požadavku "sec-ch-ua"
se rediguje. Následující 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 konkrétní 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();