Registrazione HTTP in ASP.NET Core
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 8 di questo articolo.
La registrazione HTTP è un middleware che registra informazioni sulle richieste HTTP in ingresso e sulle risposte HTTP. La registrazione HTTP fornisce log per:
- Informazioni sulle richieste HTTP
- Proprietà comuni
- Intestazioni
- Testo
- Informazioni sulle risposte HTTP
La registrazione HTTP può:
- Registra tutte le richieste e le risposte o solo richieste e risposte che soddisfano determinati criteri.
- Selezionare le parti della richiesta e della risposta registrate.
- Consente di redigire le informazioni riservate dai log.
La registrazione HTTP può ridurre le prestazioni di un'app, soprattutto quando si registrano i corpi di richiesta e risposta. Prendere in considerazione l'impatto sulle prestazioni durante la selezione dei campi da registrare. Testare l'impatto sulle prestazioni delle proprietà di registrazione selezionate.
Avviso
La registrazione HTTP può registrare potenzialmente informazioni personali. Tenere conto di questo rischio ed evitare la registrazione di informazioni sensibili.
Abilitare la registrazione HTTP
La registrazione HTTP è abilitata chiamando AddHttpLogging e UseHttpLogging, come illustrato nell'esempio seguente:
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();
L'espressione lambda vuota nell'esempio precedente di chiamata AddHttpLogging
aggiunge il middleware con la configurazione predefinita. Per impostazione predefinita, la registrazione HTTP registra proprietà comuni, ad esempio percorso, codice di stato e intestazioni per richieste e risposte.
Aggiungere la riga seguente al file appsettings.Development.json
al livello "LogLevel": {
in modo da visualizzare i log HTTP:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Con la configurazione predefinita, una richiesta e una risposta vengono registrate come coppia di messaggi simili all'esempio seguente:
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
Opzioni di registrazione HTTP
Per configurare le opzioni globali per il middleware di registrazione HTTP, chiamare AddHttpLogging in Program.cs
usando l'espressione lambda per configurare 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();
Nota
Nell'esempio precedente e negli esempi seguenti viene UseHttpLogging
chiamato dopo UseStaticFiles
, quindi la registrazione HTTP non è abilitata per i file statici. Per abilitare la registrazione HTTP dei file statici, chiamare UseHttpLogging
prima UseStaticFiles
di .
LoggingFields
HttpLoggingOptions.LoggingFields
è un flag di enumerazione che configura parti specifiche della richiesta e della risposta da registrare. Il valore predefinito di HttpLoggingOptions.LoggingFields
è RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
e ResponseHeaders
RequestHeaders e ResponseHeaders sono set di intestazioni HTTP registrate. I valori di intestazione vengono registrati solo per i nomi di intestazione presenti in queste raccolte. Il codice seguente aggiunge sec-ch-ua
a RequestHeaders, in modo che il valore dell'intestazione sec-ch-ua
venga registrato. E aggiunge MyResponseHeader
a ResponseHeaders, in modo che il valore dell'intestazione MyResponseHeader
venga registrato. Se queste righe vengono rimosse, i valori di queste intestazioni sono [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 fornisce la configurazione per la selezione della codifica da usare per un tipo di supporto specifico.
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();
Questo approccio può essere usato anche per abilitare la registrazione per i dati non registrati per impostazione predefinita, ad esempio i dati del modulo, che potrebbero avere un tipo di supporto, application/x-www-form-urlencoded
ad esempio o multipart/form-data
.
Metodi MediaTypeOptions
RequestBodyLogLimit
e 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
L'impostazione CombineLogs di per true
configurare il middleware per consolidare tutti i log abilitati per una richiesta e una risposta in un unico log alla fine. Sono inclusi la richiesta, il corpo della richiesta, la risposta, il corpo della risposta e la durata.
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();
Configurazione specifica dell'endpoint
Per la configurazione specifica dell'endpoint in app per le API minime, è disponibile un WithHttpLogging metodo di estensione. L'esempio seguente illustra come configurare la registrazione HTTP per un endpoint:
app.MapGet("/response", () => "Hello World! (logging response)")
.WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);
Per la configurazione specifica dell'endpoint nelle app che usano controller, l'attributo [HttpLogging]
è disponibile. L'attributo può essere usato anche nelle app per le API minime, come illustrato nell'esempio seguente:
app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
() => "Hello World! (logging duration)");
IHttpLoggingInterceptor
IHttpLoggingInterceptor è l'interfaccia per un servizio che può essere implementato per gestire i callback per richiesta e risposta per personalizzare i dettagli registrati. Tutte le impostazioni di log specifiche dell'endpoint vengono applicate per prime e possono quindi essere sottoposte a override in questi callback. Un'implementazione può:
- Esaminare una richiesta o una risposta.
- Abilitare o disabilitare qualsiasi oggetto HttpLoggingFields.
- Regolare la quantità di corpo della richiesta o della risposta registrata.
- Aggiungere campi personalizzati ai log.
Registrare un'implementazione IHttpLoggingInterceptor
chiamando AddHttpLoggingInterceptor<T>
in Program.cs
. Se vengono registrate più IHttpLoggingInterceptor
istanze, vengono eseguite nell'ordine registrato.
L'esempio seguente illustra come registrare un'implementazione IHttpLoggingInterceptor
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();
L'esempio seguente è un'implementazione IHttpLoggingInterceptor
che:
- Controlla il metodo di richiesta e disabilita la registrazione per le richieste POST.
- Per le richieste non POST:
- Redacts request path, request headers e response headers .Redacts request path, request headers, and response headers.
- Aggiunge campi e valori di campo personalizzati ai log delle richieste e delle risposte.
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");
}
}
Con questo intercettore, una richiesta POST non genera alcun log anche se la registrazione HTTP è configurata per registrare HttpLoggingFields.All
. Una richiesta GET genera log simili all'esempio seguente:
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
Ordine di configurazione della registrazione della precedenza
L'elenco seguente mostra l'ordine di precedenza per la configurazione della registrazione:
- Configurazione globale da HttpLoggingOptions, impostata chiamando AddHttpLogging.
- La configurazione specifica dell'endpoint dall'attributo o il metodo di estensione esegue l'override
[HttpLogging]
WithHttpLogging della configurazione globale. IHttpLoggingInterceptor
viene chiamato con i risultati e può modificare ulteriormente la configurazione per richiesta.
La registrazione HTTP è un middleware che registra informazioni sulle richieste HTTP in ingresso e sulle risposte HTTP. La registrazione HTTP fornisce log per:
- Informazioni sulle richieste HTTP
- Proprietà comuni
- Intestazioni
- Testo
- Informazioni sulle risposte HTTP
La registrazione HTTP risulta utile in diversi scenari per:
- Registrare informazioni sulle richieste e le risposte in ingresso.
- Filtrare le parti della richiesta e della risposta registrate.
- Filtrare le intestazioni da registrare.
La registrazione HTTP può ridurre le prestazioni di un'app, soprattutto quando si registrano i corpi delle richieste e delle risposte. Prendere in considerazione l'impatto sulle prestazioni durante la selezione dei campi da registrare. Testare l'impatto sulle prestazioni delle proprietà di registrazione selezionate.
Avviso
La registrazione HTTP può registrare potenzialmente informazioni personali. Tenere conto di questo rischio ed evitare la registrazione di informazioni sensibili.
Abilitazione della registrazione HTTP
La registrazione HTTP viene abilitata con UseHttpLogging, che aggiunge il middleware di registrazione 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();
Per impostazione predefinita, la registrazione HTTP registra proprietà comuni, come percorso, codice di stato e intestazioni per le richieste e le risposte. Aggiungere la riga seguente al file appsettings.Development.json
al livello "LogLevel": {
in modo da visualizzare i log HTTP:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
L'output viene registrato come singolo messaggio in LogLevel.Information
.
Opzioni di registrazione HTTP
Per configurare il middleware di registrazione HTTP, chiamare AddHttpLogging in 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();
Nota
Nell'esempio precedente e negli esempi seguenti viene UseHttpLogging
chiamato dopo UseStaticFiles
, quindi la registrazione HTTP non è abilitata per il file statico. Per abilitare la registrazione HTTP dei file statici, chiamare UseHttpLogging
prima UseStaticFiles
di .
LoggingFields
HttpLoggingOptions.LoggingFields
è un flag di enumerazione che configura parti specifiche della richiesta e della risposta da registrare. Il valore predefinito di HttpLoggingOptions.LoggingFields
è RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
Headers sono un set di intestazioni di richiesta HTTP che possono essere registrate. I valori di intestazione vengono registrati solo per i nomi di intestazione presenti in questa raccolta. Il codice seguente registra l'intestazione della richiesta "sec-ch-ua"
. Se si rimuove logging.RequestHeaders.Add("sec-ch-ua");
, il valore dell'intestazione della richiesta "sec-ch-ua"
viene corretto. Il codice evidenziato seguente chiama HttpLoggingOptions.RequestHeaders
e 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 fornisce la configurazione per la selezione della codifica da usare per un tipo di supporto specifico.
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();
Questo approccio può essere usato anche per abilitare la registrazione per i dati non registrati per impostazione predefinita. Ad esempio, i dati del modulo, che potrebbero avere un tipo di supporto, application/x-www-form-urlencoded
ad esempio o multipart/form-data
.
Metodi MediaTypeOptions
RequestBodyLogLimit
e 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();