Naplózási útmutató .NET-kódtár-szerzőknek
Könyvtárszerzőként a naplózás felfedése nagyszerű módja annak, hogy a felhasználók betekintést nyerjenek a könyvtár belső működésébe. Ez az útmutató segít a naplózás más .NET-kódtárakkal és keretrendszerekkel összhangban történő felfedésében. Emellett segít elkerülni a teljesítmény olyan gyakori szűk keresztmetszeteit is, amelyek egyébként nem feltétlenül nyilvánvalóak.
Mikor érdemes használni a felületet?ILoggerFactory
Naplókat kibocsátó kódtár írásakor a naplók rögzítéséhez objektumra ILogger van szükség. Az objektum lekéréséhez az API elfogadhat egy paramétert ILogger<TCategoryName> , vagy elfogadhat egy olyan paramétert ILoggerFactory , amelyet meghív ILoggerFactory.CreateLogger. Melyik megközelítést érdemes előnyben részesíteni?
Ha olyan naplózási objektumra van szüksége, amely több osztálynak is átadható, hogy mindegyik képes legyen naplókat kibocsátani, használja a következőt
ILoggerFactory
: Javasoljuk, hogy minden osztály külön kategóriával rendelkező naplókat hoz létre, amelyek neve megegyezik az osztályéval. Ehhez a gyárnak egyediILogger<TCategoryName>
objektumokat kell létrehoznia minden naplót kibocsátó osztályhoz. Ilyenek például a nyilvános belépési pont API-k egy könyvtárhoz vagy olyan típusú nyilvános konstruktorokhoz, amelyek belsőleg hozhatnak létre segédosztályokat.Ha olyan naplózási objektumra van szüksége, amelyet csak egy osztályon belül használnak, és soha nem osztják meg, használja
ILogger<TCategoryName>
azt a típust, amelyTCategoryName
a naplókat hozza létre. Erre gyakori példa a függőséginjektálás által létrehozott osztály konstruktora.
Ha olyan nyilvános API-t tervez, amelyeknek az idő múlásával stabilnak kell maradniuk, vegye figyelembe, hogy a belső implementációt a jövőben újra kell dolgoznia. Még akkor is, ha egy osztály kezdetben nem hoz létre belső segédtípusokat, ez a kód fejlődése során változhat. A nyilvános ILoggerFactory
API módosítása nélkül új objektumokat hozhat létre ILogger<TCategoryName>
minden új osztályhoz.
További információ: A szűrési szabályok alkalmazása.
A forrás által generált naplózás előnyben részesítve
Az ILogger
API két módszert támogat az API használatára. Meghívhat például LoggerExtensions.LogError és LoggerExtensions.LogInformation, vagy a naplózási forrásgenerátor használatával definiálhat erősen gépelt naplózási módszereket. A legtöbb esetben a forrásgenerátor használata ajánlott, mert kiváló teljesítményt és erősebb gépelést biztosít. Emellett elkülöníti a naplózással kapcsolatos problémákat, például az üzenetsablonokat, az azonosítókat és a naplószinteket a hívókódtól. A nem forrásként létrehozott megközelítés elsősorban olyan helyzetekben hasznos, ahol hajlandó lemondani ezekről az előnyökről, hogy tömörebbé tegye a kódot.
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);
}
A fenti kód a következőket végzi el:
- Egy elnevezett
LogMessages
metódustpartial class
határoz meg, amelystatic
lehetővé teszi a típushoz tartozó bővítménymetelyekILogger
definiálására. - A bővítménymetódusokat
LogProductSaleDetails
az attribútummal ésMessage
aLoggerMessage
sablonnal díszíti. - Deklarálja
LogProductSaleDetails
, amely kiterjeszti a és elfogadjaquantity
aILogger
ésdescription
.
Tipp.
A hibakeresés során beléphet a forrás által létrehozott kódba, mert az ugyanahhoz a szerelvényhez tartozik, mint a kódot meghívó kód.
A drága paraméterek kiértékelésének elkerülésére használható IsEnabled
Lehetnek olyan helyzetek, amikor a paraméterek kiértékelése költséges. Az előző példára bontva tegyük fel, hogy a description
paraméter string
számítása költséges. Lehet, hogy az értékesített termék rövid termékleírást kap, és adatbázis-lekérdezésre vagy fájlból való olvasásra támaszkodik. Ilyen helyzetekben utasíthatja a forrásgenerátort, hogy hagyja ki az őrt IsEnabled
, és manuálisan adja hozzá az IsEnabled
őrt a hívási helyen. Ez lehetővé teszi a felhasználó számára, hogy meghatározza az őr meghívásának helyét, és biztosítsa, hogy a számításhoz költséges paraméterek csak akkor legyenek kiértékelve, ha valóban szükség van rá. Tekintse meg az alábbi kódot:
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);
}
A bővítménymetódus meghívásakor a LogProductSaleDetails
IsEnabled
biztonsági őr manuálisan lesz meghívva, és a drága paraméter-kiértékelés csak akkor lesz elérhető, amikor szükség van rá. Tekintse meg az alábbi kódot:
if (_logger.IsEnabled(LogLevel.Information))
{
// Expensive parameter evaluation
var description = product.GetFriendlyProductDescription();
_logger.LogProductSaleDetails(
quantity,
description);
}
További információ: Fordítási idő naplózási forrás létrehozása és nagy teljesítményű naplózás a .NET-ben.
Sztring interpoláció elkerülése naplózáskor
Gyakori hiba, hogy sztring interpolációt használ a naplóüzenetek létrehozásához. A naplózás sztringinterpolációja problémás a teljesítmény szempontjából, mivel a sztring akkor is kiértékelésre kerül, ha a megfelelő LogLevel
nincs engedélyezve. Sztring-interpoláció helyett használja a naplóüzenet-sablont, a formázást és az argumentumlistát. További információ: Naplózás a .NET-ben: Naplóüzenet sablon.
Művelet nélküli naplózás alapértelmezett beállítása
Előfordulhatnak olyan időszakok, amikor olyan kódtárat használ, amely olyan naplózási API-kat tesz elérhetővé, amelyek egy ILogger
vagy ILoggerFactory
több olyan api-t várnak el, amelyet nem szeretne naplózóként megadni. Ezekben az esetekben a Microsoft.Extensions.Logging.Absztrakciók NuGet-csomag nem műveleti naplózási alapértelmezett beállításokat biztosít.
A kódtár felhasználói alapértelmezés szerint null értékű naplózást végezhetnek, ha nincs ILoggerFactory
megadva. A null naplózás használata eltér attól, hogy a típusokat null értékűként (ILoggerFactory?
null értékűként) definiálja, mivel a típusok nem null értékűek. Ezek a kényelmi alapú típusok nem naplóznak semmit, és lényegében nem használhatók. Szükség esetén fontolja meg a rendelkezésre álló absztrakciós típusok bármelyikének használatát: