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
Gestire i dati con Azure Cosmos DB Data Explorer
Miglioramenti nelle performance di Angular 16
Utilizzare gRPC su App Service di Azure
Code scanning e advanced security con Azure DevOps
Bloccare l'esecuzione di un pod in mancanza di un'artifact attestation di GitHub
Creare gruppi di client per Event Grid MQTT
Utilizzare Azure AI Studio per testare i modelli AI
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
Eseguire query manipolando liste di tipi semplici con Entity Framework Core
Utilizzare un service principal per accedere a Azure Container Registry
Come EF 8 ha ottimizzato le query che usano il metodo Contains