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 il metodo ExceptBy per eseguire operazione di sottrazione tra liste
Recuperare l'ultima versione di una release di GitHub
Fornire parametri ad un Web component HTML
Cancellare una run di un workflow di GitHub
.NET Aspire per applicazioni distribuite
Gestire gli accessi con Token su Azure Container Registry
Gestione file Javascript in Blazor con .NET 9
Configurare il nome della run di un workflow di GitHub in base al contesto di esecuzione
Ordinare randomicamente una lista in C#
Configurare lo startup di applicazioni server e client con .NET Aspire
Ottimizzare le performance usando Span<T> e il metodo Split
Migliorare i tempi di risposta di GPT tramite lo streaming endpoint in ASP.NET Core