Correlare i log in un'applicazione distribuita con ASP.NET Core

di Marco De Sanctis, in ASP.NET Core,

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

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi