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 un service principal per accedere a Azure Container Registry
Migliora le tue soluzioni ASP.NET Core con Azure OpenAI
Sfruttare al massimo i topic space di Event Grid MQTT
Modificare i metadati nell'head dell'HTML di una Blazor Web App
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
Eseguire script pre e post esecuzione di un workflow di GitHub
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
Utilizzare il nuovo modello GPT-4o con Azure OpenAI
Utilizzare QuickGrid di Blazor con Entity Framework
Proteggere le risorse Azure con private link e private endpoints
Creare gruppi di client per Event Grid MQTT