Quando realizziamo architetture basate su microservizi, riuscire a tracciare una richiesta attraverso tutti i componenti coinvolti può essere un compito piuttosto arduo. Per questa ragione, si sfrutta spesso un cosiddetto CorrelationID, ossia un identificativo assegnato alla richiesta, che viene passato a tutti i servizi invocati.
Se usiamo Azure Application Insights come strumento di monitoring, questa funzionalità è già fornita dall'SDK in automatico, senza che facciamo nulla. Ma se invece stiamo sfruttando un altro sistema, è nostro compito farci carico di
- generare questo identificativo,
- passarlo a tutte le chiamate HTTP coinvolte nella richiesta,
- tracciarlo nei log.
In ASP.NET Core 3.0, fortunatamente, i primi due punti sono gestiti in automatico dal framework, per cui a noi non resta che catturare il Correlation ID nei nostri log. Per farlo, abbiamo a disposizione la classe Activity del namespace System.Diagnostics. Diamo un'occhiata alla action in basso:
[HttpGet] public async Task<IEnumerable<WeatherForecast>> Get() { var activity = Activity.Current; _logger.LogInformation($"Id: {activity.Id}"); _logger.LogInformation($"RootId: {activity.RootId}"); var result = await _client.GetStringAsync("https://localhost:5011/weatherforecast"); return JsonSerializer.Deserialize<IEnumerable<WeatherForecast>>(result); }
Tramite Activity.Current possiamo recuperare l'Activity associata alla richiesta corrente e utilizzarla per mostrarla in un log. Se stessimo utilizzando un logger come Serilog, per esempio, potremmo includerla come proprietà custom del nostro log.
Come possiamo notare, nella action in alto abbiamo effettuato una chiamata a un secondo endpoint. L'aspetto interessante è che l'identificativo della richiesta verrà passato in automatico tramite un header request-id all'API invocata. Nel caso in cui anche questa API sia basata su ASP.NET Core 3.0, il valore verrà immediatamente incorporato nella Activity.Current, così che possiamo utilizzarlo per correlare i log dei due web service.
L'oggetto Activity presenta diverse proprietà, ma due sono di particolare rilievo:
- Id è l'identificativo della richiesta corrente, che ha una radice in comune con il chiamante che l'ha originata.
- RootId è il codice della chiamata iniziale, e viene mantenuto su tutte le chiamate effettuate in cascata.
In buona sostanza, se catturiamo nei nostri log il valore di RootId e successivamente lo utilizziamo come filtro, potremo risalire all'intero flusso di log che una data richiesta ha generato attraverso tutti i microservizi della nostra applicazione.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare gRPC su App Service di Azure
Code scanning e advanced security con Azure DevOps
Supportare lo HierarchyID di Sql Server in Entity Framework 8
Creare un'applicazione React e configurare Tailwind CSS
Utilizzare la versione generica di EntityTypeConfiguration in Entity Framework Core
Gestire liste di tipi semplici con Entity Framework Core
Persistere la ChatHistory di Semantic Kernel in ASP.NET Core Web API per GPT
Aggiungere interattività lato server in Blazor 8
Le novità di Angular: i miglioramenti alla CLI
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Filtrare i dati di una QuickGrid in Blazor con una drop down list