Richtlijnen voor logboekregistratie voor auteurs van .NET-bibliotheken
Als auteur van een bibliotheek is het beschikbaar maken van logboekregistratie een uitstekende manier om gebruikers inzicht te geven in de interne werking van uw bibliotheek. Deze richtlijnen helpen u logboekregistratie beschikbaar te maken op een manier die consistent is met andere .NET-bibliotheken en frameworks. Het helpt u ook veelvoorkomende prestatieknelpunten te voorkomen die anders niet duidelijk zijn.
Wanneer moet u de ILoggerFactory
interface gebruiken
Wanneer u een bibliotheek schrijft waarmee logboeken worden verzonden, hebt u een ILogger object nodig om de logboeken vast te leggen. Als u dat object wilt ophalen, kan uw API een ILogger<TCategoryName> parameter accepteren of een parameter accepteren waarna u een ILoggerFactory aanroept ILoggerFactory.CreateLogger. Welke benadering moet de voorkeur hebben?
Wanneer u een logboekregistratieobject nodig hebt dat kan worden doorgegeven aan meerdere klassen, zodat ze allemaal logboeken kunnen verzenden, gebruikt
ILoggerFactory
u . Het is raadzaam dat elke klasse logboeken met een afzonderlijke categorie maakt, met dezelfde naam als de klasse. Hiervoor hebt u de fabriek nodig om uniekeILogger<TCategoryName>
objecten te maken voor elke klasse die logboeken verzendt. Veelvoorkomende voorbeelden zijn api's voor openbare toegangspunten voor een bibliotheek of openbare constructors van typen die intern helperklassen kunnen maken.Wanneer u een logboekregistratieobject nodig hebt dat alleen in één klasse wordt gebruikt en nooit wordt gedeeld, gebruikt
ILogger<TCategoryName>
u , waarTCategoryName
is het type dat de logboeken produceert. Een veelvoorkomend voorbeeld hiervan is een constructor voor een klasse die is gemaakt door afhankelijkheidsinjectie.
Als u een openbare API ontwerpt die in de loop van de tijd stabiel moet blijven, moet u er rekening mee houden dat u uw interne implementatie in de toekomst mogelijk wilt herstructureren. Zelfs als een klasse in eerste instantie geen interne helpertypen maakt, kan dit veranderen naarmate de code zich ontwikkelt. Het gebruik maakt ILoggerFactory
plaats voor het maken van nieuwe ILogger<TCategoryName>
objecten voor nieuwe klassen zonder de openbare API te wijzigen.
Zie Hoe filterregels worden toegepast voor meer informatie.
De voorkeur geven aan door de bron gegenereerde logboekregistratie
De ILogger
API ondersteunt twee benaderingen voor het gebruik van de API. U kunt methoden aanroepen zoals LoggerExtensions.LogError en LoggerExtensions.LogInformation, of u kunt de generator voor logboekregistratie gebruiken om sterk getypte logboekregistratiemethoden te definiëren. Voor de meeste situaties wordt de brongenerator aanbevolen omdat deze superieure prestaties en sterkere typen biedt. Het isoleert ook logboekspecifieke problemen, zoals berichtsjablonen, id's en logboekniveaus van de aanroepende code. De niet-brongegenereerde benadering is voornamelijk handig voor scenario's waarin u deze voordelen wilt opgeven om de code beknopter te maken.
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);
}
Met de voorgaande code wordt:
- Hiermee definieert u een
partial class
benoemde naamLogMessages
, zodatstatic
deze kan worden gebruikt om extensiemethoden voor hetILogger
type te definiëren. - Hiermee wordt een
LogProductSaleDetails
uitbreidingsmethode ingericht met het kenmerk enMessage
deLoggerMessage
sjabloon. - Declareert
LogProductSaleDetails
, waarmee deILogger
en accepteert aquantity
endescription
.
Tip
U kunt tijdens foutopsporing stap in de door de broncode gegenereerde code invoeren, omdat deze deel uitmaakt van dezelfde assembly als de code die deze aanroept.
Gebruiken IsEnabled
om dure parameterevaluatie te voorkomen
Er kunnen situaties zijn waarin het evalueren van parameters duur is. Als u het vorige voorbeeld uitbreidt, stelt u zich eens voor dat de description
parameter duur string
is om te berekenen. Misschien krijgt het product dat wordt verkocht een beschrijvende productbeschrijving en is het afhankelijk van een databasequery of het lezen uit een bestand. In deze situaties kunt u de brongenerator instrueren om de IsEnabled
bewaker over te slaan en de IsEnabled
bewaker handmatig toe te voegen op de oproepsite. Hierdoor kan de gebruiker bepalen waar de guard wordt aangeroepen en ervoor zorgt dat parameters die mogelijk duur zijn voor berekening alleen worden geëvalueerd wanneer ze echt nodig zijn. Kijk eens naar de volgende code:
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);
}
Wanneer de LogProductSaleDetails
extensiemethode wordt aangeroepen, wordt de IsEnabled
guard handmatig aangeroepen en is de dure parameterevaluatie beperkt tot wanneer deze nodig is. Kijk eens naar de volgende code:
if (_logger.IsEnabled(LogLevel.Information))
{
// Expensive parameter evaluation
var description = product.GetFriendlyProductDescription();
_logger.LogProductSaleDetails(
quantity,
description);
}
Zie Compile-time logging source generation and High-performance logging in .NET voor meer informatie.
Tekenreeksinterpolatie voorkomen in logboekregistratie
Een veelvoorkomende fout is het gebruik van tekenreeksinterpolatie om logboekberichten te maken. Tekenreeksinterpolatie in logboekregistratie is problematisch voor prestaties, omdat de tekenreeks wordt geëvalueerd, zelfs als de bijbehorende LogLevel
niet is ingeschakeld. Gebruik in plaats van tekenreeksinterpolatie de logboekberichtsjabloon, opmaak en argumentlijst. Zie Logboekregistratie in .NET: Sjabloon voor logboekberichten voor meer informatie.
Standaardinstellingen voor logboekregistratie zonder op gebruiken
Er kunnen momenten zijn wanneer u een bibliotheek gebruikt die logboekregistratie-API's beschikbaar maakt die een ILogger
of ILoggerFactory
, verwachten, dat u geen logboekregistratie wilt opgeven. In deze gevallen biedt het NuGet-pakket Microsoft.Extensions.Logging.Abstractions standaardinstellingen voor logboekregistratie zonder op.
Bibliotheekgebruikers kunnen standaard null-logboekregistratie instellen als er geen ILoggerFactory
logboekregistratie is opgegeven. Het gebruik van null-logboekregistratie verschilt van het definiëren van typen als nullable (ILoggerFactory?
), omdat de typen niet null zijn. Deze op het gemak gebaseerde typen registreren niets en zijn in wezen no-ops. Overweeg indien van toepassing een van de beschikbare abstractietypen te gebruiken: