Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Die HTTP-Protokollierung ist eine Middleware, die Informationen zu eingehenden HTTP-Anforderungen und HTTP-Antworten protokolliert. Die HTTP-Protokollierung enthält Protokolle zu:
- HTTP-Anforderungsinformationen
- Allgemeine Eigenschaften
- Header
- Körper
- HTTP-Antwortinformationen
Die HTTP-Protokollierung kann:
- alle Anforderungen und Antworten oder nur Anforderungen und Antworten protokollieren, die bestimmten Kriterien entsprechen
- auswählen, welche Teile der Anforderung und Antwort protokolliert werden
- Ermöglichen Sie das Entfernen vertraulicher Informationen aus den Protokollen.
Die HTTP-Protokollierung kann die Leistung einer App verringern, insbesondere beim Protokollieren der Anforderungs- und Antworttexte. Berücksichtigen Sie die Auswirkungen auf die Leistung, wenn Sie die zu protokollierenden Felder auswählen. Testen Sie die Auswirkungen der ausgewählten Protokollierungseigenschaften auf die Leistung.
Warnung
Die HTTP-Protokollierung kann potenziell personenbezogene Informationen (Personally Identifiable Information, PII) protokollieren. Berücksichtigen Sie das Risiko, und vermeiden Sie die Protokollierung vertraulicher Informationen. Weitere Informationen zur Schwärzung finden Sie unter Schwärzen vertraulicher Daten.
Aktivieren der HTTP-Protokollierung
Die HTTP-Protokollierung wird durch Aufrufen von AddHttpLogging und UseHttpLogging aktiviert, wie im folgenden Beispiel gezeigt:
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();
Der leere Lambda im vorherigen Beispiel des Aufrufs AddHttpLogging
fügt die Middleware mit der Standardkonfiguration hinzu. Standardmäßig protokolliert die HTTP-Protokollierung allgemeine Eigenschaften wie Pfad, Statuscode und Header für Anforderungen und Antworten.
Fügen Sie der Datei appsettings.Development.json
auf der Ebene "LogLevel": {
die folgende Zeile hinzu, damit die HTTP-Protokolle angezeigt werden:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Bei der Standardkonfiguration werden eine Anforderung und eine Antwort als Nachrichtenpaar protokolliert, das dem folgenden Beispiel ähnelt:
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-Protokollierungsoptionen
Um globale Optionen für die HTTP-Protokollierungsmiddleware zu konfigurieren, rufen Sie AddHttpLogging in Program.cs
auf, indem Sie den Lambdaausdruck verwenden, um HttpLoggingOptions zu konfigurieren.
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();
Hinweis
Im vorherigen Beispiel und in den folgenden Beispielen wird UseHttpLogging
nach UseStaticFiles
ausgeführt, sodass die HTTP-Protokollierung für statische Dateien nicht aktiviert ist. Um die HTTP-Protokollierung für statische Dateien zu aktivieren, rufen Sie UseHttpLogging
vor UseStaticFiles
auf.
LoggingFields
HttpLoggingOptions.LoggingFields
ist ein Enumerationsflag, das bestimmte Teile der zu protokollierenden Anforderung und Antwort konfiguriert.
LoggingFields
ist standardmäßig RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
und ResponseHeaders
RequestHeaders und ResponseHeaders sind die HTTP-Header, die protokolliert werden. Headerwerte werden nur für Headernamen protokolliert, die in diesen Sammlungen enthalten sind. Der folgende Code fügt sec-ch-ua
zu RequestHeaders hinzu, sodass der Wert des sec-ch-ua
-Headers protokolliert wird. Außerdem wird MyResponseHeader
zu ResponseHeaders hinzugefügt, sodass der Wert des MyResponseHeader
-Headers protokolliert wird. Wenn diese Zeilen entfernt werden, lauten die Werte dieser Header [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 stellt die Konfiguration für die Auswahl der für einen bestimmten Medientyp zu verwendenden Codierung bereit.
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();
Dieser Ansatz kann auch verwendet werden, um die Protokollierung für Daten zu ermöglichen, die standardmäßig nicht protokolliert werden (z. B. Formulardaten, deren Medientyp application/x-www-form-urlencoded
oder multipart/form-data
lauten kann).
MediaTypeOptions
Methoden
RequestBodyLogLimit
und 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
Wenn Sie CombineLogs auf true
festlegen, wird die Middleware so konfiguriert, dass alle aktivierten Protokolle für eine Anforderung und Antwort in einem Protokoll am Ende konsolidiert werden. Das umfasst die Anforderung, den Anforderungstext, die Antwort, den Antworttext und die Dauer.
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();
Endpunktspezifische Konfiguration
Für endpunktspezifische Konfigurationen in minimalen API-Apps ist eine WithHttpLogging-Erweiterungsmethode verfügbar. Das folgende Beispiel zeigt, wie die HTTP-Protokollierung für einen Endpunkt konfiguriert wird:
app.MapGet("/response", () => "Hello World! (logging response)")
.WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);
Für endpunktspezifische Konfigurationen in Apps, die Controller verwenden, ist das [HttpLogging]
Attribut verfügbar. Das Attribut kann auch in minimalen API-Apps verwendet werden, wie im folgenden Beispiel gezeigt:
app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
() => "Hello World! (logging duration)");
IHttpLoggingInterceptor
IHttpLoggingInterceptor ist die Schnittstelle für einen Dienst, der implementiert werden kann, um Rückrufe pro Anforderung und Antwort zu verarbeiten und anzupassen, welche Details protokolliert werden. Alle endpunktspezifischen Protokolleinstellungen werden zuerst angewendet und können dann in diesen Rückrufen überschrieben werden. Eine Implementierung kann:
- Untersuchen Sie eine Anforderung oder Antwort.
- beliebige HttpLoggingFields aktivieren oder deaktivieren
- anpassen, welcher Anteil des Anforderungs- oder Antworttexts protokolliert wird
- benutzerdefinierte Felder zu Protokollen hinzufügen
Registrieren Sie eine IHttpLoggingInterceptor-Implementierung, indem Sie AddHttpLoggingInterceptor in Program.cs
aufrufen. Wenn mehrere IHttpLoggingInterceptor-Instanzen registriert sind, werden sie in der registrierten Reihenfolge ausgeführt.
Das folgende Beispiel zeigt, wie Sie eine IHttpLoggingInterceptor-Implementierung registrieren:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();
Das folgende Beispiel ist eine IHttpLoggingInterceptor-Implementierung, die:
- die Anforderungsmethode untersucht und die Protokollierung für POST-Anforderungen deaktiviert
- Für Nicht-POST-Anforderungen:
- Redigiert den Anforderungspfad, die Anforderungsheader und die Antwortheader.
- den Anforderungs- und Antwortprotokollen benutzerdefinierte Felder und Feldwerte hinzufügt
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");
}
}
Mit diesem Interceptor generiert eine POST-Anforderung keine Protokolle, auch wenn die HTTP-Protokollierung so konfiguriert ist, dass HttpLoggingFields.All
protokolliert wird. Eine GET-Anforderung generiert Protokolle, die dem folgenden Beispiel ähneln:
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
Rangfolge der Protokollierungskonfiguration
Die folgende Liste zeigt die Rangfolge für die Protokollierungskonfiguration:
- Die globale Konfiguration von HttpLoggingOptions wird durch Aufrufen von AddHttpLogging festgelegt.
- Endpunktspezifische Konfiguration aus dem
[HttpLogging]
Attribut oder der WithHttpLogging Erweiterungsmethode setzt globale Konfiguration außer Kraft. -
IHttpLoggingInterceptor
wird mit den Ergebnissen aufgerufen und kann die Konfiguration pro Anforderung weiter ändern.
HTTP-Protokollierung ist eine Middleware, die Informationen zu eingehenden HTTP-Anforderungen und HTTP-Antworten protokolliert. Die HTTP-Protokollierung enthält Protokolle zu:
- HTTP-Anforderungsinformationen
- Allgemeine Eigenschaften
- Header
- Körper
- HTTP-Antwortinformationen
Die HTTP-Protokollierung ist hilfreich in verschiedenen Szenarios wie:
- Aufzeichnen von Informationen zu eingehenden Anforderungen und Antworten.
- Filtern, welche Teile der Anforderung und Antwort protokolliert werden.
- Filtern, welche Header protokolliert werden sollen.
Die HTTP-Protokollierung kann die Leistung einer App verringern, insbesondere beim Protokollieren der Anforderungs- und Antworttexte. Berücksichtigen Sie die Auswirkungen auf die Leistung, wenn Sie die zu protokollierenden Felder auswählen. Testen Sie die Auswirkungen der ausgewählten Protokollierungseigenschaften auf die Leistung.
Warnung
Die HTTP-Protokollierung kann potenziell personenbezogene Informationen (Personally Identifiable Information, PII) protokollieren. Berücksichtigen Sie das Risiko, und vermeiden Sie die Protokollierung vertraulicher Informationen.
Aktivieren der HTTP-Protokollierung
Die HTTP-Protokollierung wird mit UseHttpLogging aktiviert, wodurch Middleware für die HTTP-Protokollierung hinzufügt wird.
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();
Standardmäßig protokolliert die HTTP-Protokollierung allgemeine Eigenschaften wie Pfad, Statuscode und Header für Anforderungen und Antworten. Fügen Sie der Datei appsettings.Development.json
auf der Ebene "LogLevel": {
die folgende Zeile hinzu, damit die HTTP-Protokolle angezeigt werden:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Die Ausgabe wird als einzelne Nachricht unter LogLevel.Information
protokolliert.
HTTP-Protokollierungsoptionen
Um die Middleware für die HTTP-Protokollierung zu konfigurieren, rufen Sie AddHttpLogging in Program.cs
auf.
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();
Hinweis
Im vorherigen Beispiel und den folgenden Beispielen wird UseHttpLogging
nach UseStaticFiles
aufgerufen. Die HTTP-Protokollierung ist also für statische Dateien nicht aktiviert. Um die HTTP-Protokollierung für statische Dateien zu aktivieren, rufen Sie UseHttpLogging
vor UseStaticFiles
auf.
LoggingFields
HttpLoggingOptions.LoggingFields
ist ein Enumerationsflag, das bestimmte Teile der zu protokollierenden Anforderung und Antwort konfiguriert.
HttpLoggingOptions.LoggingFields
ist standardmäßig RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
Headers ist eine Gruppe von HTTP-Anforderungsheadern, die protokolliert werden dürfen. Headerwerte werden nur für Headernamen protokolliert, die in dieser Sammlung enthalten sind. Der folgende Code protokolliert den Anforderungsheader "sec-ch-ua"
. Beim Entfernen von logging.RequestHeaders.Add("sec-ch-ua");
wird der Wert des Anforderungsheaders "sec-ch-ua"
entfernt. Der folgende hervorgehobene Code ruft HttpLoggingOptions.RequestHeaders
und HttpLoggingOptions.ResponseHeaders
auf:
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 stellt die Konfiguration für die Auswahl der für einen bestimmten Medientyp zu verwendenden Codierung bereit.
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();
Dieser Ansatz kann auch verwendet werden, um die Protokollierung für Daten zu ermöglichen, die standardmäßig nicht protokolliert werden. Zum Beispiel Formulardaten, die einen Medientyp wie application/x-www-form-urlencoded
oder multipart/form-data
aufweisen können.
MediaTypeOptions
Methoden
RequestBodyLogLimit
und 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();
Maskieren vertraulicher Daten
Http-Protokollierung mit Redaction kann durch Aufrufen AddHttpLoggingRedactionaktiviert werden:
Weitere Informationen zur Daten-Schwärzungs-Bibliothek von .NET finden Sie unter "Daten-Schwärzung in .NET".
Maskierungsoptionen für die Protokollierung
Um Optionen für die Protokollierung mit Redaction zu konfigurieren, rufen Sie AddHttpLoggingRedaction in Program.cs
mithilfe der Lambda-Funktion auf, um LoggingRedactionOptions zu konfigurieren:
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();
Mit der vorherigen Redaktionskonfiguration ähnelt die Ausgabe dem Folgenden:
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
Hinweis
Der Anforderungspfad /home
wird nicht protokolliert, da er in der ExcludePathStartsWith
Eigenschaft enthalten ist.
http.request.header.accept
und http.response.header.content-type
wurden von Microsoft.Extensions.Compliance.Redaction.ErasingRedactor redigiert.
RequestPathLoggingMode
RequestPathLoggingMode bestimmt, wie der Anforderungspfad protokolliert wird, ob Formatted
oder Structured
, festgelegt von IncomingPathLoggingMode:
-
Formatted
: Protokolliert den Anforderungspfad ohne Parameter. -
Structured
: Protokolliert den Anforderungspfad mit eingeschlossenen Parametern.
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
RequestPathParameterRedactionModeGibt an, wie Routenparameter im Anforderungspfad redigiert werden sollen, ob Strict
, Loose
oder None
, festgelegt durch HttpRouteParameterRedactionMode:
-
Strict
: Anforderungsroutenparameter werden als vertraulich betrachtet, erfordern explizite Anmerkungen mit einer Datenklassifizierung und sind standardmäßig redigiert. -
Loose
: Alle Parameter werden standardmäßig als nicht vertraulich betrachtet und enthalten as-is. -
None
: Routenparameter werden unabhängig vom Vorhandensein von Datenklassifizierungsanmerkungen nicht redigiert.
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 ordnet Anforderungsheader ihrer Datenklassifizierung zu, die bestimmt, wie sie redigiert werden:
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, ähnlich wie RequestHeadersDataClasses', aber für Antwortheader:
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 ordnet Routenparameter ihrer Datenklassifizierung zu:
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 Gibt Pfade an, die vollständig von der Protokollierung ausgeschlossen werden sollen:
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 ermöglicht das Melden nicht übereinstimmender Routen. Wenn auf true
festgelegt, wird der gesamte Pfad der Routen protokolliert, die nicht durch Routing identifiziert werden, anstatt den Wert von Unknown
für das Pfadattribut zu protokollieren.
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();