Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Jako autor biblioteki, ujawnianie logów to doskonały sposób, aby zapewnić konsumentom wgląd w wewnętrzne działanie twojej biblioteki. Te wskazówki ułatwiają uwidacznianie rejestrowania w sposób zgodny z innymi bibliotekami i strukturami .NET. Pomaga również uniknąć typowych wąskich gardeł wydajności.
Kiedy używać interfejsu ILoggerFactory
Podczas pisania biblioteki, która emituje dzienniki, potrzebny jest ILogger obiekt do rejestrowania dzienników. Aby uzyskać ten obiekt, interfejs API może zaakceptować parametr ILogger<TCategoryName> albo zaakceptować ILoggerFactory, po czym wywołasz ILoggerFactory.CreateLogger. Które podejście powinno być preferowane?
- Jeśli potrzebujesz obiektu rejestrowania, który można przekazać do wielu klas, aby wszystkie z nich mogły emitować dzienniki, użyj polecenia
ILoggerFactory. Zaleca się, aby każda klasa tworzy dzienniki z oddzielną kategorią o takiej samej nazwie jak klasa. Aby to zrobić, potrzebujesz fabryki do tworzenia unikatowychILogger<TCategoryName>obiektów dla każdej klasy, która emituje logi. Typowe przykłady to publiczne interfejsy API jako punkt wejścia do biblioteki lub publiczne konstruktory typów, które mogą wewnętrznie tworzyć klasy pomocnicze. - Jeśli potrzebujesz obiektu rejestrowania, który jest używany tylko w jednej klasie i nigdy nie jest udostępniany, użyj ,
ILogger<TCategoryName>gdzieTCategoryNamejest typem, który generuje dzienniki. Typowym przykładem jest konstruktor klasy utworzonej przez iniekcję zależności.
Jeśli projektujesz publiczny interfejs API, który musi pozostawać stabilny w czasie, pamiętaj, że możesz chcieć refaktoryzować wewnętrzną implementację w przyszłości. Nawet jeśli klasa początkowo nie tworzy żadnych wewnętrznych typów pomocników, może to ulec zmianie w miarę rozwoju kodu. Wykorzystanie ILoggerFactory umożliwia tworzenie nowych obiektów ILogger<TCategoryName> dla dowolnych nowych klas bez zmieniania publicznego interfejsu API.
Aby uzyskać więcej informacji, zobacz Jak są stosowane reguły filtrowania.
Preferuj rejestrowanie generowane przez źródło
Interfejs ILogger API obsługuje dwa podejścia do korzystania z interfejsu API. Możesz wywołać metody, takie jak LoggerExtensions.LogError i LoggerExtensions.LogInformation, lub użyć generatora źródła logowania do zdefiniowania silnie typizowanych metod logowania. W większości sytuacji zaleca się generator źródła, ponieważ oferuje lepszą wydajność i silniejsze typowanie. Izoluje również problemy specyficzne dla rejestrowania, takie jak szablony komunikatów, identyfikatory i poziomy logów od kodu wywołującego. Podejście niezwiązane ze źródłem jest przydatne przede wszystkim w scenariuszach, w których chcesz zrezygnować z tych zalet, aby kod był bardziej zwięzły.
using Microsoft.Extensions.Logging;
namespace Logging.LibraryAuthors;
internal static partial class LogMessages
{
[LoggerMessage(
Message = "Sold {Quantity} of {Description}",
Level = LogLevel.Information)]
internal static partial void LogProductSaleDetails(
this ILogger logger,
int quantity,
string description);
}
Poprzedni kod:
- Definiuje element nazwany
partial classLogMessages, który jeststatic, aby umożliwić definiowanie metod rozszerzeń w typieILogger. - Dekoruje metodę rozszerzenia
LogProductSaleDetailsz atrybutemLoggerMessagei szablonemMessage. - Deklaruje
LogProductSaleDetails, który rozszerzaILoggeri akceptujequantityorazdescription.
Wskazówka
Możesz przejść do kodu wygenerowanego przez źródło podczas debugowania, ponieważ jest on częścią tego samego zestawu co kod, który go wywołuje.
Użyj IsEnabled, aby uniknąć kosztownej oceny parametrów
Mogą wystąpić sytuacje, w których ocena parametrów jest kosztowna. Rozwijając poprzedni przykład, wyobraź sobie description , że parametr jest kosztowny string do obliczenia. Być może sprzedawany produkt otrzymuje szczegółowy opis i działa na podstawie zapytania do bazy danych lub odczytu z pliku. W takich sytuacjach możesz poinstruować generator kodu źródłowego, aby pominąć IsEnabled blokadę i ręcznie dodać IsEnabled blokadę w miejscu wywołania. Dzięki temu użytkownik może określić, gdzie jest wywoływana ochrona, i gwarantuje, że parametry, które mogą być kosztowne do obliczenia, są oceniane tylko wtedy, gdy jest to naprawdę potrzebne. Spójrzmy na poniższy kod:
using Microsoft.Extensions.Logging;
namespace Logging.LibraryAuthors;
internal static partial class LogMessages
{
[LoggerMessage(
Message = "Sold {Quantity} of {Description}",
Level = LogLevel.Information,
SkipEnabledCheck = true)]
internal static partial void LogProductSaleDetails(
this ILogger logger,
int quantity,
string description);
}
Gdy metoda rozszerzenia LogProductSaleDetails jest wywoływana, zabezpieczenie IsEnabled jest uruchamiane ręcznie, a kosztowna ewaluacja parametrów odbywa się tylko wtedy, gdy jest to konieczne. Spójrzmy na poniższy kod:
if (_logger.IsEnabled(LogLevel.Information))
{
// Expensive parameter evaluation
var description = product.GetFriendlyProductDescription();
_logger.LogProductSaleDetails(
quantity,
description);
}
Aby uzyskać więcej informacji, zobacz Generowanie źródła rejestrowania w czasie kompilacji i Rejestrowanie o wysokiej wydajności na platformie .NET.
Unikaj interpolacji ciągów w rejestrowaniu
Typowym błędem jest użycie interpolacji ciągów do tworzenia komunikatów dziennika. Interpolacja ciągów w rejestrowaniu jest problematyczna dla wydajności, ponieważ ciąg jest przetwarzany nawet wtedy, gdy odpowiadający LogLevel nie jest włączony. Zamiast interpolacji ciągów użyj szablonu komunikatu dziennika, formatowania i listy argumentów. Aby uzyskać więcej informacji, zobacz Rejestrowanie na platformie .NET: szablon komunikatu dziennika.
Użyj domyślnych ustawień rejestrowania no-op
Gdy korzystasz z biblioteki, która udostępnia interfejsy API rejestrowania oczekujące wartości ILogger lub ILoggerFactory, zdarza się, że czasami nie chcesz udostępniać rejestratora. W takich przypadkach pakiet NuGet Microsoft.Extensions.Logging.Abstractions udostępnia ustawienia domyślne rejestrowania no-op.
Użytkownicy biblioteki mogą domyślnie używać null logging, jeśli nie zostanie podana ILoggerFactory. Użycie logowania null różni się od definiowania typów jako dopuszczających wartości null (ILoggerFactory?), ponieważ typy te są nienulli. Te typy oparte na wygodach nie rejestrują niczego i w zasadzie nie są ops. Rozważ użycie dowolnego z dostępnych typów abstrakcji, jeśli ma to zastosowanie: