Quando vogliamo sapere cosa succede nel nostro applicativo web, possiamo far ricorso ad Application Insights. Installando l'SDK otteniamo il tracciamento di tutte le richieste, gli errori e ci vengono fornite metriche utili.
Tra le richieste ci ritroviamo anche il relativo esito e può sicuramente capitare di restituire uno status code fallito, come il 400 (bad request). In queste situazioni non troviamo molti dettagli, perché non si è verificato un errore e non vediamo alcun messaggio, ma comunque la richiesta da un punto di vista web è fallita.
Per ovviare a questo problema possiamo pensare di arricchire le informazioni memorizzate. La tecnica migliore per farlo consiste nel creare una classe di tipo ITelemetryInitializer, ma purtroppo lavora in sincrono e non ci permette di accedere a tutte le informazioni necessarie. In questo script quindi proponiamo l'uso di un middleware che si ponga all'inizio e alla fine delle richieste, arricchendo la telemetria.
Partiamo quindi dal preparare lo scheletro del middleware, con costruttore e metodo Invoke.
public class BadRequestMiddleware { private readonly RequestDelegate _next; public BadRequestMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { } }
All'interno di Invoke dobbiamo decidere per quali operazioni tracciare maggiori dettagli. Nel nostro esempio identifichiamo richieste in JSON per le quali dobbiamo abilitare il buffering della richiesta. Questa funzionalità è normalmente spenta, per rendere il più leggero possibile l'esecuzione delle richieste, ma abilitandola ci permette, in caso di esito negativo nella nostra risposta, di leggere l'intero body e aggiungerlo alla telemetria, come mostrato nel codice seguente.
bool isJson = httpContext.Request.ContentType == "application/json"; // Solo per le richieste di tipo JSON if (isJson) { httpContext.Request.EnableBuffering(); } // Chiamo il resto della pipeline await _next(httpContext); // In caso di 400 if (isJson && httpContext.Response.StatusCode == 400 && httpContext.Features.Get<RequestTelemetry>() is RequestTelemetry requestTelemetry) { // Rileggo il body httpContext.Request.Body.Position = 0; string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); // Imposto la proprietà requestTelemetry.Properties["Request"] = body; }
Dopo aver attivato il buffering proseguiamo con l'invocazione classica del resto della pipeline. Successivamente, in caso di richiesta JSON, con risposta 400 e con la telemetria presente, andiamo a rileggere il body come stringa e lo aggiungiamo alle proprietà. In background il motore di Application Insights si occuperà della registrazione della richiesta comprensivo della nostra proprietà.
Non ci resta che attivare il middleware nello Startup attraverso la registrazione seguente:
app.UseMiddleware<BadRequestMiddleware>();
Fatto questo nel portale ogni volta che troviamo una risposta di tipo 400 troviamo tra le custom properties anche il JSON.
Bisogna prestare attenzione a questa funzionalità, perché l'utilizzo del buffering va ad appesantire il nostro applicativo. E' fondamentale quindi cercare di attivarlo solo al minor numero di richieste possibili.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare la session affinity con Azure Container Apps
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
Migliora la resilienza delle applicazioni con .NET e Azure Container Apps
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Accesso sicuro ai secrets attraverso i file in Azure Container Apps
Utilizzare il trigger SQL con le Azure Function
Eseguire attività pianificate con Azure Container Jobs
Utilizzare gli snapshot con Azure File shares
Eseguire operazioni sui blob con Azure Storage Actions
Trasformare qualsiasi backend in un servizio GraphQL con Azure API Management
Usare lo spread operator con i collection initializer in C#
Creare gruppi di client per Event Grid MQTT