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
Evitare il flickering dei componenti nel prerender di Blazor 8
Semplificare il deployment di siti statici con Azure Static Web App
Creazione di componenti personalizzati in React.js con Tailwind CSS
Effettuare il deploy di immagini solo da container registry approvati in Kubernetes
Gestire undefined e partial nelle reactive forms di Angular
Disabilitare automaticamente un workflow di GitHub (parte 2)
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Ottenere il contenuto di una cartella FTP con la libreria FluentFTP
Sfruttare MQTT in cloud e in edge con Azure Event Grid
Utilizzare un service principal per accedere a Azure Container Registry
Creare alias per tipi generici e tuple in C#
Usare le collection expression per inizializzare una lista di oggetti in C#