Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A .NET támogatja a nagy teljesítményű, strukturált naplózást az API-n keresztül az ILogger alkalmazások viselkedésének monitorozásához és a problémák diagnosztizálásához. Konfiguráljon különböző naplózási szolgáltatókat a naplók különböző célhelyekre való írásához. Az alapszintű naplózási szolgáltatók beépítettek, és számos külső szolgáltató érhető el.
Első lépések
Ez az első példa az alapokat mutatja be, de csak triviális konzolalkalmazásokhoz alkalmas. Ez a minta konzolalkalmazás a következő NuGet-csomagokra támaszkodik:
A következő szakaszban láthatja, hogyan javíthatja a kódot a skálázás, a teljesítmény, a konfiguráció és a tipikus programozási minták figyelembevételével.
using Microsoft.Extensions.Logging;
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Az előző példa:
- Létrehoz egy ILoggerFactory. A
ILoggerFactoryrendszer tárolja az összes konfigurációt, amely meghatározza a naplóüzenetek küldésének helyét. Ebben az esetben konfigurálja a konzol naplózási szolgáltatóját úgy, hogy a rendszer a naplóüzeneteket a konzolra írja. - Létrehoz egy ILogger "Program" nevű kategóriát. A kategória az
stringobjektum általILoggernaplózott összes üzenethez társított kategória. Egy osztályból (vagy kategóriából) származó naplóüzeneteket csoportosít a naplók keresésekor vagy szűrésekor. - Felhívja a LogInformation függvényt egy üzenet naplózására a
Informationszinten. A naplószint a naplózott esemény súlyosságát jelzi, és kiszűri a kevésbé fontos naplóüzeneteket. A naplóbejegyzés tartalmaz egy üzenetsablont"Hello World! Logging is {Description}."és egy kulcs-érték párotDescription = funis. A kulcs neve (vagy helyőrzője) a sablon kapcsos zárójeleiben lévő szóból származik, az érték pedig a fennmaradó metódusargumentumból származik.
A példához tartozó projektfájl két NuGet-csomagot tartalmaz:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
</ItemGroup>
</Project>
Tipp.
Az összes naplózási példa forráskódja letölthető a Mintaböngészőben . További információ: Kódminták tallózása: Naplózás a .NET-ben.
Bejelentkezés nem triviális alkalmazásba
Fontolja meg ezeket a módosításokat az előző példában, ha kevésbé triviális forgatókönyvben jelentkezik be:
Ha az alkalmazás függőséginjektálást (DI) vagy gazdagépet, például az ASP.NET WebApplication vagy Generikus gazdagép használ, akkor a
ILoggerFactoryésILoggerobjektumokat a saját DI-tárolóikból vegye igénybe, ahelyett, hogy őket közvetlenül hozná létre. További információért lásd: Integráció a DI-val és a hosztokkal.A fordítási időben történő forráskód-generálás általában jobb alternatíva az olyan
ILoggerkiterjesztési metódusok helyett, mint aLogInformation. A naplózási forrás létrehozása jobb teljesítményt, erősebb gépelést biztosít, és elkerüli az állandók terjesztésétstringa metódusokban. A kompromisszum az, hogy ennek a technikának a használata egy kicsit több kódot igényel.
using Microsoft.Extensions.Logging;
internal partial class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
LogStartupMessage(logger, "fun");
}
[LoggerMessage(Level = LogLevel.Information, Message = "Hello World! Logging is {Description}.")]
static partial void LogStartupMessage(ILogger logger, string description);
}
- A naplókategória-nevek ajánlott módszere, hogy a naplóüzenetet létrehozó osztály teljes nevét használjuk. Ez segít visszakonfigurálni a naplóüzeneteket az őket előállító kódhoz, és jó szintű ellenőrzést biztosít a naplók szűrése során.
CreateLogger elfogad egy
Type, hogy megkönnyítse az elnevezést.
using Microsoft.Extensions.Logging;
internal class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger<Program>();
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
}
}
- Ha nem a konzolnaplókat használja egyedüli éles környezetbeli monitorozó megoldásként, adja hozzá a használni kívánt naplózási szolgáltatókat. Például az OpenTelemetry használatával küldjön naplókat OTLP-n keresztül (OpenTelemetry protocol):
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter();
});
});
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Integráció szerverekkel és függőséginjektálással
Ha az alkalmazás függőséginjektálást (DI) vagy gazdagépkörnyezetet, például az ASP.NET WebApplication vagy a Generic Host használ, akkor ILoggerFactory és ILogger objektumokat használjon a DI tárolóból ahelyett, hogy ezeket közvetlenül hozná létre.
ILogger lekérése a DI-ből
Ez a példa megmutatja, hogyan lehet egy ILogger-objektumot lekérni egy üzemeltetett alkalmazásban az ASP.NET Minimal APIs segítségével.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
var handler = app.Services.GetRequiredService<ExampleHandler>();
app.MapGet("/", handler.HandleRequest);
app.Run();
partial class ExampleHandler(ILogger<ExampleHandler> logger)
{
public string HandleRequest()
{
LogHandleRequest(logger);
return "Hello World";
}
[LoggerMessage(LogLevel.Information, "ExampleHandler.HandleRequest was called")]
public static partial void LogHandleRequest(ILogger logger);
}
Az előző példa:
- Egy singleton szolgáltatást hozott létre
ExampleHandlernéven, és a bejövő webes kéréseket aExampleHandler.HandleRequestfüggvény futtatásához társította. - A 12. sor egy elsődleges konstruktort definiál a C# 12-ben hozzáadott ExampleHandlerhez. A régebbi stílusú C# konstruktor ugyanúgy működik, de egy kicsit részletesebb.
- A konstruktor egy típusparamétert
ILogger<ExampleHandler>határoz meg. ILogger<TCategoryName> származik ILogger-ből és jelzi, hogy az adott objektum melyik kategóriába tartozik. A DI-tároló megkeres egyILoggermegfelelő kategóriát, és konstruktor argumentumként adja meg. Ha nincs még ilyen kategóriájúILogger, a DI-tároló automatikusan létrehozza azt a szolgáltatón belüliILoggerFactoryalapján. - A
loggerkonstruktorban kapott paramétert a függvényben való naplózáshoz használja aHandleRequestrendszer.
Kiszolgáló által biztosított ILoggerFactory
A gazdagépkészítők inicializálják az alapértelmezett konfigurációt, majd a gazdagép létrehozásakor hozzáadnak egy konfigurált ILoggerFactory objektumot a gazdagép DI-tárolójába. A gazdagép létrehozása előtt módosítsa a naplózási konfigurációt más gazdagépeken lévő , HostApplicationBuilder.Loggingvagy hasonló API-k használatávalWebApplicationBuilder.Logging. Gazdagépek is alkalmaznak naplózási konfigurációt az alapértelmezett konfigurációs forrásokból, például appsettings.json és környezeti változókból. További információ: Konfiguráció a .NET-ben.
Ez a példa az előző példát továbbfejleszti, hogy testre szabja a ILoggerFactory által megadott WebApplicationBuilder. OpenTelemetryt ad hozzá naplózási szolgáltatóként, amely a naplókat otLP-n (OpenTelemetry protokollon) keresztül továbbítja:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(logging => logging.AddOtlpExporter());
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
ILoggerFactory létrehozása diával
Ha gazdagép nélküli DI-tárolót használ, konfigurálhatja AddLogging és hozzáadhatja ILoggerFactory a tárolót.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Add services to the container including logging
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<ExampleService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Get the ExampleService object from the container
ExampleService service = serviceProvider.GetRequiredService<ExampleService>();
// Do some pretend work
service.DoSomeWork(10, 20);
class ExampleService(ILogger<ExampleService> logger)
{
public void DoSomeWork(int x, int y)
{
logger.LogInformation("DoSomeWork was called. x={X}, y={Y}", x, y);
}
}
Az előző példa:
- Létrehoztam egy DI-szolgáltatáskonténert, amely a konzolra történő írásra van konfigurálva.
- Egy singleton
ExampleServicekerült hozzáadásra a tárolóhoz - Létrehozott egy példányt a
ExampleServiceDI konténerből, amely automatikusan létrehozott egyILogger<ExampleService>példányt a konstruktor argumentumként való használatra. - Meghívta a
ExampleService.DoSomeWork-t, amely aILogger<ExampleService>-t használta, hogy üzenetet naplózzon a konzolra.
Naplózás konfigurálása
Adja meg a naplózási konfigurációt kódban vagy külső forrásokon, például konfigurációs fájlokon és környezeti változókon keresztül. A külső konfiguráció használata akkor előnyös, ha lehetséges, mert az alkalmazás újraépítése nélkül is módosíthatja. Egyes feladatok, például a naplózási szolgáltatók beállítása azonban csak kódból konfigurálhatók.
Naplózás konfigurálása kód nélkül
Gazdagépet használó alkalmazások esetében az "Logging"appsettings.{Environment}.json fájlok szakasza általában naplózási konfigurációt biztosít. A hosztot nem használó alkalmazások esetében állítson be explicit módon külső konfigurációs forrásokat, vagy konfigurálja őket kódban.
Az alábbi appsettings. Development.json fájlt a .NET-feldolgozó szolgáltatássablonjai generálják:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
A fenti JSON-ban:
- A
"Default","Microsoft"és"Microsoft.Hosting.Lifetime"a naplószintű kategóriák meg vannak adva. - Az
"Default"érték minden olyan kategóriára vonatkozik, amely egyébként nincs megadva, így gyakorlatilag az összes alapértelmezett érték az összes kategóriára"Information"érvényes. A viselkedés felülbírálása egy kategória értékének megadásával. - A
"Microsoft"kategória az összes olyan kategóriára vonatkozik, amely a következővel"Microsoft"kezdődik: . - A
"Microsoft"kategória naplózási szintje aWarningés magasabb szinten történik. - A
"Microsoft.Hosting.Lifetime"kategória pontosabb, mint a"Microsoft"kategória, ezért a"Microsoft.Hosting.Lifetime"kategória"Information"és magasabb szinten naplóz. - Nincs megadva egy adott naplószolgáltató, ezért
LogLevela Windows EventLog kivételével az összes engedélyezett naplózási szolgáltatóra vonatkozik.
A Logging tulajdonság rendelkezhet LogLevel és naplózás szolgáltatói tulajdonságaival. A LogLevel megadott kategóriák naplózásának minimális szintjét adja meg. Az előző JSON-ban meg vannak adva a Information és Warning naplószintek.
LogLevel A napló súlyosságát jelzi, és 0 és 6 közötti tartományt jelöl:
Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 és None = 6.
A(z) LogLevel megadásakor a naplózás engedélyezve van a megadott szinten és a magasabb szinten lévő üzenetekhez. Az előző JSON-ban a Default kategória és a magasabbak naplózása történik Information. A rendszer például naplózza az InformationWarningErrorCritical üzeneteket. Ha nincs LogLevel megadva, a naplózás alapértelmezés szerint a Information szintre kerül. További információkért tekintse meg a Naplószintek részt.
A szolgáltatói tulajdonság megadhat egy tulajdonságot LogLevel .
LogLevel egy szolgáltatónál megadja az adott szolgáltatóhoz naplózni kívánt szinteket, és felülbírálja a nem szolgáltatói naplóbeállításokat. Vegye figyelembe a következő appsettings.json fájlt:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
A Logging.{ProviderName}.LogLevel beállításai felülbírálják a Logging.LogLevel beállításait. Az előző JSON-ban a Debug szolgáltató alapértelmezett naplószintje a következőre Informationvan állítva:
Logging:Debug:LogLevel:Default:Information
Az előző beállítás minden Information kategória naplószintjét meghatározza, kivéve Logging:Debug:. Ha egy adott kategória szerepel a listában, az adott kategória felülírja az alapértelmezett kategóriát. Az előző JSON-ban a Logging:Debug:LogLevel kategóriák "Microsoft.Hosting" és "Default" felülbírálják a Logging:LogLevelbeállításait.
Adja meg az alábbiak közül bármelyik minimális naplószintjét:
- Konkrét szolgáltatók: Például:
Logging:EventSource:LogLevel:Default:Information - Konkrét kategóriák: Például:
Logging:LogLevel:Microsoft:Warning - Minden szolgáltató és minden kategória:
Logging:LogLevel:Default:Warning
A minimális szint alatti naplók nem:
- Átadva a szolgáltatónak.
- Naplózott vagy megjelenített.
Az összes napló letiltásához adja meg a LogLevel.None értéket.
LogLevel.None értéke 6, ami magasabb, mint LogLevel.Critical (5).
Ha egy szolgáltató támogatja a napló hatóköreit, jelzi, IncludeScopes hogy engedélyezve vannak-e. További információért lásd: naplószkópok.
Az alábbi appsettings.json fájl az összes beépített szolgáltató beállításait tartalmazza:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.Extensions.Hosting": "Warning",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
Az előző példában:
- A kategóriák és szintek nem javasolt értékek. A minta az összes alapértelmezett szolgáltatót megjeleníti.
- A
Logging.{ProviderName}.LogLevelbeállításai felülbírálják aLogging.LogLevelbeállításait.Debug.LogLevel.Defaultszintje például felülbírálja aLogLevel.Defaultszintjét. - A rendszer minden szolgáltató aliasát használja. Minden szolgáltató meghatároz egy aliast , amelyet a konfigurációban használhat a teljes típusnév helyett. A beépített szolgáltatók aliasai a következők:
ConsoleDebugEventSourceEventLogAzureAppServicesFileAzureAppServicesBlobApplicationInsights
Naplószint beállítása parancssor, környezeti változók és egyéb konfiguráció szerint
Állítsa be a naplószintet bármelyik konfigurációszolgáltatóval. Hozzon létre például egy megőrzött környezeti változót Logging:LogLevel:Microsoft , amelynek értéke a következő Information.
Hozzon létre és rendeljen hozzá egy állandó környezeti változót a naplószintű érték alapján.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
Egy újParancssor példányában olvassa el a környezeti változót.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
Az előző környezeti beállítás megmarad a környezetben. A .NET Worker szolgáltatássablonjaival létrehozott alkalmazás használatakor a beállítások teszteléséhez használja a dotnet run projektkönyvtárban található parancsot a környezeti változó hozzárendelése után.
dotnet run
Tipp.
Egy környezeti változó beállítása után indítsa újra az integrált fejlesztési környezetet (IDE), hogy az újonnan hozzáadott környezeti változók elérhetők legyenek.
A Azure-alkalmazás Szolgáltatásban válassza az Új alkalmazás beállítást a Beállítások > konfiguráció lapján. Az Azure App Service alkalmazás beállításai a következők:
- Inaktív állapotban titkosítva és titkosított csatornán keresztül továbbítva.
- Környezeti változókként van hozzáférhetővé téve.
A .NET-konfigurációs értékek környezeti változók használatával történő beállításáról további információt a környezeti változókban talál.
Naplózás konfigurálása kóddal
A naplózás kódbeli konfigurálásához használja az ILoggingBuilder API-t. A következő helyekről érheti el:
- A
ILoggerFactoryközvetlen létrehozásakor konfigurálja a LoggerFactory.Create beállításait. - Ha a DI-t host nélkül használja, itt konfigurálja: LoggingServiceCollectionExtensions.AddLogging.
- Gazdagép használata esetén konfiguráljon HostApplicationBuilder.Logging, WebApplicationBuilder.Logging vagy más gazdagépspecifikus API-kat.
Ez a példa a konzolnaplózási szolgáltató és több szűrő beállítását mutatja be.
using Microsoft.Extensions.Logging;
using var loggerFactory = LoggerFactory.Create(static builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogDebug("Hello {Target}", "Everyone");
Az előző példában AddFilter a különböző kategóriákhoz engedélyezett naplószintet állítja be.
AddConsole hozzáadja a konzolnaplózási szolgáltatót. Alapértelmezés szerint a súlyosságú Debug naplók nincsenek engedélyezve, de mivel a konfiguráció módosította a szűrőket, a "Hello Mindenki" hibakeresési üzenet jelenik meg a konzolon.
A szűrési szabályok alkalmazása
Amikor létrehoz egy ILogger<TCategoryName> objektumot, az ILoggerFactory objektum szolgáltatónként egyetlen szabályt választ ki, amelyet az adott naplózóra alkalmazni szeretne. A ILogger példány a kijelölt szabályok alapján szűri az általa írt összes üzenetet. Az elérhető szabályok közül az egyes szolgáltatók és kategóriapárok legspecifikusabb szabálya van kiválasztva.
A rendszer az alábbi algoritmust használja minden szolgáltatóhoz, amikor létrehoz egy ILogger adott kategóriát:
- Válassza ki a szolgáltatónak vagy aliasának megfelelő összes szabályt. Ha nem található egyezés, válassza ki az összes szabályt, ahol nincs szolgáltató.
- Az előző lépés eredményéből válassza ki a leghosszabb egyező kategóriaelőtaggal rendelkező szabályokat. Ha nem található egyezés, jelölje ki az összes olyan szabályt, amely nem ad meg kategóriát.
- Ha több szabály van kijelölve, az utolsót vegye figyelembe.
- Ha nincs kiválasztva szabály, a LoggingBuilderExtensions.SetMinimumLevel(ILoggingBuilder, LogLevel) minimális naplózási szintet adja meg.
Naplókategória
ILogger Objektum létrehozásakor egy kategória van megadva. Az a kategória szerepel minden, a ILogger példánya által létrehozott naplóüzenetben. A kategória string tetszőleges, de a konvenció a teljesen kvalifikált osztálynév használata. Például az alábbi objektumhoz hasonló szolgáltatással rendelkező alkalmazásokban a kategória a következő lehet "Example.DefaultService":
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
Ha további kategorizálásra van szükség, a konvenció egy hierarchikus nevet használ egy alkategóriának a teljes osztálynévhez való hozzáfűzésével, és explicit módon adja meg a kategóriát a következő használatával LoggerFactory.CreateLogger:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("Example.DefaultService.CustomCategory");
// ...
}
}
A rögzített névvel történő hívás CreateLogger akkor hasznos, ha több osztályban/típusban használják, így az események kategóriák szerint rendszerezhetők.
ILogger<T> egyenértékű azzal, amikor a CreateLogger van meghívva a T teljes típusnevét használva.
Naplózási szint
Az alábbi táblázat az LogLevel értékeket, a kényelmi Log{LogLevel} bővítménymetódust és a javasolt használatot sorolja fel:
| Naplózási szint | Érték | Metódus | Leírás |
|---|---|---|---|
| Nyomkövetés | 0 | LogTrace | A legrészletesebb üzeneteket tartalmazza. Ezek az üzenetek bizalmas alkalmazásadatokat tartalmazhatnak. Ezek az üzenetek alapértelmezés szerint le vannak tiltva, és éles környezetben nem engedélyezettek. |
| Debug | 1 | LogDebug | Hibakereséshez és fejlesztéshez. A nagy mennyiség miatt óvatosan alkalmazandó üzemben. |
| Tájékoztatás | 2 | LogInformation | Nyomon követi az alkalmazás általános folyamatát. Lehet, hogy hosszú távú értéke van. |
| Figyelmeztetés | 3 | LogWarning | Rendellenes vagy váratlan események esetén. Általában olyan hibákat vagy feltételeket tartalmaznak, amelyek nem okozzák az alkalmazás meghibásodását. |
| Hiba | 4 | LogError | Olyan hibák és kivételek esetén, amelyeket nem lehet kezelni. Ezek az üzenetek az aktuális művelet vagy kérés hibáját jelzik, nem pedig alkalmazásszintű hibát. |
| Kritikus | 5 | LogCritical | Azonnali figyelmet igénylő hibák esetén. Példák: adatvesztési forgatókönyvek, lemezterületen kívül. |
| Egyik sem | 6 | Azt határozza meg, hogy ne kelljen üzeneteket írni. |
Az előző táblázatban a LogLevel legalacsonyabbtól a legmagasabb súlyosságig soroljuk fel a listában.
A Napló metódus első paramétere LogLevela napló súlyosságát jelzi. Ahelyett, hogy a Log(LogLevel, ...)-t hívná, a legtöbb fejlesztő a Log{LogLevel} bővítési metódusokat használja. A Log{LogLevel} bővítménymetódusok meghívják a metódust Log , és megadják a LogLevel. A következő két naplózási hívás például funkcionálisan egyenértékű, és ugyanazt a naplót hozza létre:
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details az eseményazonosító, amelyet implicit módon egy állandó Int32 érték jelöl.
AppLogEvents egy olyan osztály, amely különböző elnevezett azonosítóállandókat tesz elérhetővé, és a Napló eseményazonosító szakaszában jelenik meg.
A következő kód létrehoz Information és Warning naplóbejegyzéseket:
public async Task<T> GetAsync<T>(string id)
{
_logger.LogInformation(AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
return result;
}
Az előző kódban az első Log{LogLevel} paraméter AppLogEvents.Reada naplóesemény azonosítója. A második paraméter egy üzenetsablon, amely a fennmaradó metódusparaméterek által biztosított argumentumértékek helyőrzőit tartalmazza. A metódusparamétereket a cikk későbbi, üzenetsablon szakaszában ismertetjük.
Konfigurálja a megfelelő naplószintet, és hívja meg a megfelelő Log{LogLevel} metódusokat annak szabályozásához, hogy egy adott tárolóeszközön mennyi naplókimenet legyen megírva. Példa:
- Gyártásban
- A
TracevagyDebugszinteken történő naplózás nagy mennyiségű részletes naplóüzenetet eredményez. A költségek szabályozása és az adattárolási korlátok túllépésének elkerülése érdekében naplózza azTraceésDebugszintű üzeneteket egy nagymennyiségű, alacsony költségű adattárba. Fontolja meg, hogyTraceésDebugkorlátozása bizonyos kategóriákra terjedjen ki. - Kevés naplóüzenetnek kell létrejönnie a
WarningésCriticalszinteken való naplózás során.- A költségek és a tárolási korlátok általában nem jelentenek problémát.
- A kevés napló nagyobb rugalmasságot biztosít az adattárak választásában.
- A
- Fejlesztés alatt:
- Állítsa
Warningértékre. - Hozzáadás
TracevagyDebugüzenetek hibaelhárításkor. A kimenet korlátozásához állítsa beTracevagyDebugcsak a vizsgált kategóriákra.
- Állítsa
A következő JSON-készletek Logging:Console:LogLevel:Microsoft:Information:
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Eseménynapló azonosító
Minden napló megadhat egy eseményazonosítót, amely egy struktúra EventId opcionális Id írásvédett tulajdonságokkalName. A minta forráskódja az osztály használatával határozza meg az AppLogEvents eseményazonosítókat:
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal static EventId Create = new(1000, "Created");
internal static EventId Read = new(1001, "Read");
internal static EventId Update = new(1002, "Updated");
internal static EventId Delete = new(1003, "Deleted");
// These are also valid EventId instances, as there's
// an implicit conversion from int to an EventId
internal const int Details = 3000;
internal const int Error = 3001;
internal static EventId ReadNotFound = 4000;
internal static EventId UpdateNotFound = 4001;
// ...
}
Tipp.
További információ az int átalakításáról EventId-re: EventId.Implicit(Int32 to EventId) operátor.
Az eseményazonosító események egy készletét társítja. Például az adattárból való értékbeolvasással kapcsolatos összes napló esetében előfordulhat, hogy 1001.
A naplózási szolgáltató naplózhatja az eseményazonosítót egy azonosító mezőben, a naplózási üzenetben, vagy egyáltalán nem. A hibakeresési szolgáltató nem jeleníti meg az eseményazonosítókat. A konzolszolgáltató zárójelben jeleníti meg az eseményazonosítókat a kategória után:
info: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) not found
Egyes naplózási szolgáltatók egy mezőben tárolják az eseményazonosítót, amely lehetővé teszi az azonosítóra való szűrést.
Naplóüzenet-sablon
Minden napló API egy üzenetsablont használ. Az üzenetsablon tartalmazhat helyőrzőket, amelyek argumentumai meg vannak adva. Használja a helyőrzők nevét, és ne a számokat. A helyőrzők sorrendje, nem a nevük határozza meg, hogy a rendszer mely paramétereket használja az értékek megadásához. Az alábbi kódban a paraméternevek sorrenden kívül vannak az üzenetsablonban:
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Az előző kód létrehoz egy naplóüzenetet a paraméterértékekkel sorrendben:
Parameter values: param1, param2
Feljegyzés
Ügyeljen arra, hogy több helyőrzőt használjon egyetlen üzenetsablonon belül, mivel azok sorszámalapúak. A nevek nem használhatók az argumentumok helyőrzőkhöz való igazítására.
Ez a megközelítés lehetővé teszi, hogy a naplózási szolgáltatók szemantikai vagy strukturált naplózást hajtsanak végre. Maguk az argumentumok a naplózási rendszernek lesznek átadva, nem csak a formázott üzenetsablonnak. Ez lehetővé teszi, hogy a naplózási szolgáltatók mezőként tárolják a paraméterértékeket. Fontolja meg a következő naplózó metódust:
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Például az Azure Table Storage-ba való naplózáskor:
- Minden Azure Table entitás rendelkezhet
IDésRunTimetulajdonságokkal. - A tulajdonságokkal rendelkező táblák leegyszerűsítik a naplózott adatok lekérdezését. Egy lekérdezés például az összes naplót megkeresheti egy adott
RunTimetartományon belül anélkül, hogy elemeznie kellene a szöveges üzenetből eltelt időt.
Naplóüzenetsablon formázása
A naplóüzenetsablonok támogatják a helykitöltő formázást. A sablonok bármilyen érvényes formátumot megadhatnak a megadott típusargumentumhoz. Vegyük például a következő Information naplózó üzenetsablont:
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
Az előző példában a DateTimeOffset példány az a típus, amely megfelel a naplózó üzenetsablonban lévő PlaceHolderName elemnek. Ez a név bármi lehet, mivel az értékek sorszámalapúak. A MMMM dd, yyyy formátum érvényes a DateTimeOffset típusra.
További információ a DateTime és DateTimeOffset formázásról, lásd: Egyéni dátum- és időformátum-sztringek.
Példák
Az alábbi példák bemutatják, hogyan formázhat egy üzenetsablont a {} helyőrző szintaxis használatával. Emellett egy példa is megjelenik a {} helyőrző szintaxis kiiktatására és annak kimenetére. Végül a sztring interpolációja a sablon helyőrzőkkel is megjelenik.
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
Tipp.
- A legtöbb esetben a naplóüzenet-sablon formázását kell használnia naplózáskor. A sztringinterpoláció használata teljesítményproblémákat okozhat.
- Ca2254 kódelemzési szabály : A sablonnak statikus kifejezésnek kell lennie, amely figyelmezteti azokra a helyekre, ahol a naplóüzenetek nem használják a megfelelő formázást.
Naplózási kivételek
A naplózó metódusok túlterheléssel rendelkeznek, amelyek kivételparamétert vesznek fel:
public void Test(string id)
{
try
{
if (id is "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
A kivételnaplózás szolgáltatóspecifikus.
Alapértelmezett naplószint
Ha az alapértelmezett naplószint nincs beállítva, az alapértelmezett naplószint értéke .Information
Vegyük például a következő feldolgozói szolgáltatásalkalmazást:
- A .NET-feldolgozósablonokkal létrehozva.
- appsettings.json és appsettings.Development.json törölve vagy átnevezve.
Az előző beállítással az adatvédelemre vagy a kezdőlapra való navigálás sok Trace, Debugés Information a kategórianévvel ellátott Microsoft üzeneteket eredményez.
Az alábbi kód állítja be az alapértelmezett naplószintet, ha az alapértelmezett naplószint nincs beállítva a konfigurációban:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
await host.RunAsync();
Szűrőfüggvény
A rendszer meghív egy szűrőfüggvényt minden olyan szolgáltatóhoz és kategóriához, amely nem rendelkezik hozzájuk konfiguráció vagy kód alapján hozzárendelt szabályokkal:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
});
using IHost host = builder.Build();
await host.RunAsync();
A fenti kód akkor jeleníti meg a konzolnaplókat, ha a kategória tartalmazza a Example vagy Microsoft, és a naplószint Information vagy magasabb.
Naplózási hatókörök
A hatókörök logikai műveletek halmazát csoportosítják. Ez a csoportosítás ugyanazokat az adatokat csatolhatja a készlet részeként létrehozott naplókhoz. A tranzakció feldolgozása során létrehozott naplók például tartalmazhatják a tranzakcióazonosítót.
Hatókör:
- Egy IDisposable típus, amelyet a BeginScope metódus ad vissza.
- Addig tart, amíg el nem távolítják.
A következő szolgáltatók támogatják a hatóköröket:
A naplózó hívásokat egy using blokkba helyezve használjon hatókört.
public async Task<T> GetAsync<T>(string id)
{
T result;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(
AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(
AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
}
return result;
}
A következő JSON engedélyezi a konzolszolgáltató hatóköreit:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
A következő kód lehetővé teszi a konzolszolgáltató hatóköreit:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddSimpleConsole(options => options.IncludeScopes = true);
using IHost host = builder.Build();
await host.RunAsync();
Naplók létrehozása a Mainban
A következő kód a gazdagép létrehozása után egy Main példány lekérésével jelentkezik be ILogger a DI-ből:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
Az előző kód két NuGet-csomagra támaszkodik:
A projektfájl a következőhöz hasonlóan néz ki:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
</Project>
Nincs aszinkron naplózó metódus
A naplózásnak olyan gyorsnak kell lennie, hogy nem éri meg az aszinkron kód teljesítményköltségét. Ha egy naplózási adattár lassú, ne írjon közvetlenül hozzá. Érdemes lehet először egy gyorstárolóba írni a naplóüzeneteket, majd később áthelyezni őket a lassú tárolóba. Ha például az SQL Serverre jelentkezik be, ne tegye ezt közvetlenül egy Log metódusban, mivel a Log metódusok szinkronban vannak. Ehelyett szinkronizálva adjon hozzá naplóüzeneteket egy memórián belüli üzenetsorhoz, és egy háttérmunkás húzza ki az üzeneteket az üzenetsorból, hogy elvégezhesse az adatok SQL Serverbe való leküldésének aszinkron munkáját.
Naplószintek módosítása futó alkalmazásokban
A Naplózási API nem tartalmaz olyan forgatókönyvet, amely megváltoztathatja a naplószinteket egy alkalmazás futtatása közben. Egyes konfigurációszolgáltatók azonban újra betölthetik a konfigurációt, ami azonnali hatással van a naplózási konfigurációra. A fájlkonfigurációs szolgáltató például alapértelmezés szerint újra betölti a naplózási konfigurációt. Ha egy alkalmazás futtatása közben módosítja a konfigurációt a kódban, az alkalmazás meghívhatja az IConfigurationRoot.Reload parancsot az alkalmazás naplózási konfigurációjának frissítéséhez.
NuGet csomagok
A ILogger<TCategoryName> és ILoggerFactory interfészeket és implementációkat a .NET SDK-k többsége implicit csomaghivatkozásként tartalmazza. Kifejezetten elérhetők a következő NuGet-csomagokban is, ha egyébként nem implicit módon hivatkoznak rájuk:
- A felületek a Microsoft.Extensions.Logging.Abstractions fájlban találhatók.
- Az alapértelmezett implementációk a Microsoft.Extensions.Logging fájlban találhatók.
További információ arról, hogy a .NET SDK mely implicit csomaghivatkozásokat tartalmaz, olvassa el a .NET SDK: table to implicit namespace című témakört.