Uso di un logger per aggiungere messaggi di log personalizzati
.NET fornisce API che è possibile usare per registrare dati di telemetria personalizzati. OpenTelemetry può esportare tali dati.
In questa unità si apprenderà come scrivere codice efficiente che invia eventi a log strutturati.
Oggetti ILogger
Gli strumenti di .NET Aspire configurano automaticamente l'API OpenTelemetry quando si crea un progetto in base ai modelli o si aggiunge un progetto esistente all'orchestrazione .NET Aspire. Quando si desidera registrare i dati di telemetria, non è necessario creare oggetti di registrazione, metriche o traccia personalizzati. È invece possibile recuperarli usando l'inserimento delle dipendenze nei microservizi.
Nella classe BasketService
seguente, ad esempio, nella dichiarazione di classe viene incluso un oggetto ILogger
. È possibile usare il logger in qualsiasi punto della classe per scrivere eventi:
public class BasketService(
IBasketRepository repository,
ILogger<BasketService> logger) : Basket.BasketBase
{
[AllowAnonymous]
public override async Task<CustomerBasketResponse> GetBasket(
GetBasketRequest request, ServerCallContext context)
{
var userId = context.GetUserIdentity();
// Use the logger to write events
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("Begin GetBasketById call from method {Method} for basket id {userId}", context.Method, userId);
}
var data = await repository.GetBasketAsync(userId);
return new();
}
}
Registrazione efficiente
La registrazione consente di rendere osservabile il microservizio. Quando l'app viene testata, sottoposta a staging e distribuita nell'ambiente di produzione, un codice di log completo può consentire una diagnosi rapida di errori o colli di bottiglia. È quindi tentata di registrare tutto. Tuttavia, anche se la registrazione è rapida, non ha un costo zero ed è consigliabile prestare attenzione a registrare in modo efficiente.
I fornitori in genere fatturano sistemi di Application Performance Management (APM) in base al volume di dati inseriti. La selezione del livello di log appropriato per i messaggi e i livelli di raccolta predefiniti possono avere un grande effetto sulla fattura mensile. I livelli di raccolta dei log possono essere impostati in base al provider, che in genere è il nome del tipo usato in ILogger<T>
.
Usare le tecniche seguenti ogni volta che si registra:
- Verificare che il livello di registrazione da usare sia abilitato. I livelli disponibili includono informazioni, avvisi, errori e critici. Gli amministratori possono abilitare livelli diversi durante i test, la gestione temporanea e la distribuzione nell'ambiente di produzione. L'output del log viene controllato tramite
IConfiguration
, in genere usandoappsettings.json
o variabili di ambiente. - Evitare l'interpolazione di stringhe nel messaggio registrato. Le stringhe interpolate vengono definite con il simbolo
$
e vengono valutate anche se il livello di registrazione scelto non è abilitato. Usare invece un metodo di log, ad esempioLogInformation()
oLogDebug()
e passare parametri nell'elenco di argomenti. - Usare la generazione dell'origine in fase di compilazione per ottimizzare ulteriormente le prestazioni di registrazione e creare un identificatore univoco per ogni messaggio di log, utile quando si eseguono query per i messaggi di log in un APM.
Generazione dell'origine in fase di compilazione
La generazione dell'origine in fase di compilazione con oggetti ILogger
riduce il costo della registrazione eseguendo l'analisi delle stringhe una sola volta, anziché in ogni richiesta di registrazione. Include anche un ID per ogni tipo di messaggio di log. Per usare questa tecnica, definire metodi di registrazione parziali con i parametri di registrazione e applicarvi LoggerMessageAttribute
. .NET genera automaticamente il metodo di registrazione completo quando il codice viene compilato.
Tenere presente che in .NET Aspire non è necessario creare un ILogger, ma è possibile ottenerlo dall'inserimento delle dipendenze:
public partial class BasketService(
IBasketRepository repository,
ILogger<BasketService> logger) : Basket.BasketBase
{
[LoggerMessage(
EventId = 0,
Level = LogLevel.Information,
Message = "Obtaining a basket from method {Method} for basket {basketId}")]
public partial void LogGetBasket(string Method, int basketId);
}
Altre informazioni
- Indicazioni sulla registrazione per gli autori di librerie .NET
- Generazione dell'origine di registrazione in fase di compilazione