Dodawanie niestandardowych komunikatów dziennika przy użyciu rejestratora

Ukończone

Platforma .NET udostępnia interfejsy API, których można użyć do rejestrowania dostosowanych danych telemetrycznych. Funkcja OpenTelemetry może eksportować te dane.

W tej lekcji dowiesz się, jak napisać wydajny kod, który wysyła zdarzenia do dzienników strukturalnych.

Obiekty ILogger

Narzędzia .NET Aspire konfigurują interfejs API OpenTelemetry automatycznie podczas tworzenia projektu na podstawie szablonów lub dodawania istniejącego projektu do orkiestracji platformy .NET Aspire. Jeśli chcesz rejestrować dane telemetryczne, nie musisz tworzyć własnych obiektów rejestrowania, metryk ani obiektów śledzenia. Zamiast tego można je pobrać przy użyciu wstrzykiwania zależności w mikrousługach.

Na przykład w poniższej BasketService klasie ILogger obiekt jest uwzględniony w deklaracji klasy. Możesz użyć tego rejestratora w dowolnym miejscu w klasie, aby zapisywać zdarzenia:

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();
    }
}

Wydajne rejestrowanie

Rejestrowanie pomaga obserwować mikrousługę. Po przetestowaniu, przeprowadzeniu i wdrożeniu aplikacji w środowisku produkcyjnym dokładny kod dziennika może umożliwić szybką diagnostykę błędów lub wąskich gardeł. Dlatego kuszące jest rejestrowanie wszystkiego. Jednak mimo że rejestrowanie jest szybkie, nie ma zerowych kosztów i należy zachować ostrożność, aby rejestrować wydajnie.

Dostawcy często rozliczają systemy zarządzania wydajnością aplikacji (APMs) na podstawie ilości pozyskiwanych danych. Wybranie odpowiedniego poziomu dziennika dla komunikatów i domyślnych poziomów kolekcji może mieć duży wpływ na miesięczny rachunek. Poziomy zbierania dzienników można ustawić dla poszczególnych dostawców, czyli zazwyczaj nazwę typu używaną w programie ILogger<T>.

Użyj następujących technik za każdym razem, gdy logujesz się:

  • Sprawdź, czy poziom rejestrowania, którego chcesz użyć, jest włączony. Dostępne poziomy obejmują informacje, ostrzeżenie, błąd i krytyczne. Administratorzy mogą włączać różne poziomy podczas testowania, przemieszczania i wdrażania w środowisku produkcyjnym. Dane wyjściowe dziennika są kontrolowane za pomocą IConfigurationmetody , zwykle przy użyciu appsettings.json zmiennych środowiskowych lub .
  • Unikaj interpolacji ciągów w zarejestrowanej wiadomości. Ciągi interpolowane są definiowane za pomocą symbolu $ i są oceniane nawet wtedy, gdy wybrany poziom rejestrowania nie jest włączony. Zamiast tego użyj metody dziennika, takiej jak LogInformation() lub LogDebug() i przekaż parametry na liście argumentów.
  • Użyj generowania źródła czasu kompilacji, aby jeszcze bardziej zoptymalizować wydajność rejestrowania i utworzyć unikatowy identyfikator dla każdego komunikatu dziennika, co jest przydatne podczas wykonywania zapytań dotyczących komunikatów dziennika w APM.

Generowanie źródła czasu kompilacji

Generowanie źródła czasu kompilacji z ILogger obiektami zmniejsza koszt rejestrowania, wykonując analizę ciągu raz, a nie na każdym żądaniu rejestrowania. Zawiera również identyfikator każdego typu komunikatu dziennika. Aby użyć tej techniki, zdefiniuj metody rejestrowania częściowego za pomocą parametrów rejestrowania LoggerMessageAttribute i zastosuj je do nich. Platforma .NET automatycznie generuje pełną metodę rejestrowania podczas kompilowania kodu.

Pamiętaj, że w programie .NET Aspire nie musisz tworzyć rejestru ILogger, ale zamiast tego możesz uzyskać go z iniekcji zależności:

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);
}

Dowiedz się więcej