Delen via


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 ILoggerFactoryu . 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 unieke ILogger<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 , waar TCategoryName 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 naam LogMessages, zodat static deze kan worden gebruikt om extensiemethoden voor het ILogger type te definiëren.
  • Hiermee wordt een LogProductSaleDetails uitbreidingsmethode ingericht met het kenmerk en Message de LoggerMessage sjabloon.
  • Declareert LogProductSaleDetails, waarmee de ILogger en accepteert a quantity en description.

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: