Naplózás C# és .NET nyelven

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. A naplók különböző célhelyekre írhatók különböző naplózási szolgáltatók konfigurálásával. Az alapszintű naplózási szolgáltatók beépítettek, és számos külső szolgáltató is elérhető.

Első lépések

Ez az első példa az alapokat mutatja be, de csak triviális konzolalkalmazásokhoz alkalmas. 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 figyelembe vé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 ILoggerFactory rendszer tárolja az összes konfigurációt, amely meghatározza a naplóüzenetek küldésének helyét. Ebben az esetben úgy konfigurálja a konzol naplózási szolgáltatóját , hogy a rendszer a naplóüzeneteket a konzolra írja.
  • Létrehoz egy ILogger "Program" nevű kategóriát. A kategória az string objektum által ILogger naplózott összes üzenethez társított kategória. A naplók keresésekor vagy szűrésekor egy osztályból (vagy kategóriából) származó naplóüzenetek csoportosítására szolgál.
  • Az üzenet naplózására vonatkozó hívások LogInformation a Information szinten. A naplószint a naplózott esemény súlyosságát jelzi, és a kevésbé fontos naplóüzenetek kiszűrésére szolgál. A naplóbejegyzés tartalmaz egy üzenetsablont "Hello World! Logging is {Description}." és egy kulcs-érték párot Description = 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>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
  </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

Az előző példában több módosítást is érdemes megfontolni, ha kevésbé triviális forgatókönyvben jelentkezik be:

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 eljárása a naplóüzenetet létrehozó osztály teljes neve. Ez segít visszakonfigurálni a naplóüzeneteket a létrehozott kódhoz, és jó szintű ellenőrzést biztosít a naplók szűrése során. CreateLogger elfogadja a Type , hogy ez az elnevezés könnyen elvégezhető.
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");
    }
}
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ó gazdagépekkel és függőséginjektálással

Ha az alkalmazás függőséginjektálást (DI) vagy gazdagépet, például ASP-t használ. A NET WebApplication-jét vagy az Általános gazdagépet ezután a DI-tárolóban kell használnia ILoggerFactory és ILogger objektumokat használnia ahelyett, hogy közvetlenül létrehozta volna őket.

ILogger lekérése a DI-ből

Ez a példa lekéri egy ILogger-objektumot egy üzemeltetett alkalmazásban ASP.NET Minimális API-k használatával:

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:

  • Létrehozott egy singleton szolgáltatást, amely meghívta ExampleHandler és leképezte a bejövő webes kéréseket a ExampleHandler.HandleRequest függvény futtatásához.
  • A 8. sor meghatározza az ExampleHandler elsődleges konstruktorát , amely a C# 12-ben hozzáadott funkció. A régebbi stílusú C# konstruktor ugyanolyan jól működik, de egy kicsit részletesebb.
  • A konstruktor egy típusparamétert ILogger<ExampleHandler>határoz meg. ILogger<TCategoryName> származik ILogger , és jelzi, hogy az objektum melyik kategóriával ILogger rendelkezik. A DI-tároló megkeres egy ILogger megfelelő kategóriát, és konstruktor argumentumként adja meg. Ha még nincs ILogger ilyen kategória, a DI-tároló automatikusan létrehozza azt a ILoggerFactory szolgáltatóból.
  • A logger konstruktorban kapott paramétert a függvényben HandleRequest való naplózáshoz használtuk.

Gazdagép á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íthatja a naplózási konfigurációt más WebApplicationBuilder.Logginggazdagépeken, vagy hasonló API-k használatávalHostApplicationBuilder.Logging. A gazdagépek az alapértelmezett konfigurációs forrásokból származó naplózási konfigurációt is alkalmazzák appsettings.json és környezeti változókként. További információ: Konfiguráció a .NET-ben.

Ez a példa az előzőre bontva testre szabja a ILoggerFactory megadottt 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étrehozott egy di-szolgáltatástárolót ILoggerFactory , amely a konzolra való írásra van konfigurálva
  • Egyetlentonnát ExampleService adott hozzá a tárolóhoz
  • Létrehozott egy példányt a ExampleService DI-tárolóból, amely automatikusan létrehozott egy ILogger<ExampleService> konstruktor argumentumként használandó példányt is.
  • Meghívva ExampleService.DoSomeWork , amely az ILogger<ExampleService> üzenet konzolra való naplózására szolgál.

Naplózás konfigurálása

A naplózási konfiguráció kódban vagy külső forrásokon, például konfigurációs fájlokon és környezeti változókon keresztül van beállítva. A külső konfiguráció használata előnyös, ha lehetséges, mert az alkalmazás újraépítése nélkül módosítható. 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 a naplózási konfigurációt általában az "Logging" appsettings.{Environment}.json fájlok szakasza biztosítja. A gazdagépet nem használó alkalmazások esetében a külső konfigurációs források explicit módon vannak beállítva, vagy kódban vannak konfigurálva.

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 érvényes "Information". Ezt a viselkedést felülbírálhatja 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órianaplók naplózási Warning szintje magasabb és magasabb.
  • A "Microsoft.Hosting.Lifetime" kategória pontosabb, mint a "Microsoft" kategória, ezért a "Microsoft.Hosting.Lifetime" kategória naplók szintjén és magasabb szinten "Information" naplóz.
  • Nincs megadva egy adott naplószolgáltató, ezért LogLevel a Windows EventLog kivételével az összes engedélyezett naplózási szolgáltatóra vonatkozik.

A Logging tulajdonság rendelkezhet LogLevel és naplózhatja a szolgáltató tulajdonságait. A LogLevel megadott kategóriák naplózásának minimális szintjét adja meg. Az előző JSON-ban Information és Warning a naplószintek meg vannak adva. 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.

Ha meg van adva, LogLevel a naplózás engedélyezve van a megadott szinten és magasabb szinten lévő üzenetekhez. Az előző JSON-ban a Default kategória naplózása és magasabb szintű naplózása Information történik. 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ó: Naplószintek.

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"
            }
        }
    }
}

Gépház felülbírálási beállítások között a következőben Logging.{ProviderName}.LogLevelLogging.LogLevel: . 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ószintét Logging:Debug: adja meg, kivéve Microsoft.Hosting. 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" a beállítások felülbírálása a következő helyen: Logging:LogLevel

A minimális naplószint az alábbiak bármelyikéhez megadható:

  • 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ó: naplóhatókörök

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ó megjelenítésére szolgál.
  • Gépház felülbírálási beállítások között a következőben Logging.{ProviderName}.LogLevelLogging.LogLevel: . A benne lévő Debug.LogLevel.Default szint például felülbírálja a szintet a következőben LogLevel.Default: .
  • A rendszer minden szolgáltató aliasát használja. Minden szolgáltató meghatároz egy aliast, amely a konfigurációban használható a teljes típusnév helyett. A beépített szolgáltatók aliasai a következők:
    • Console
    • Debug
    • EventSource
    • EventLog
    • AzureAppServicesFile
    • AzureAppServicesBlob
    • ApplicationInsights

Naplószint beállítása parancssor, környezeti változók és egyéb konfiguráció szerint

A naplószintet bármelyik konfigurációszolgáltató beállíthatja. Létrehozhat 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

A parancssor újpé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 Gépház > Konfiguráció lapon. Azure-alkalmazás szolgáltatásalkalmazá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 közzé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 kódba való naplózás konfigurálásához használja az API-t ILoggingBuilder . Ez különböző helyekről érhető el:

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 kell módosítani. AddConsole a konzol naplózási szolgáltatójának hozzáadására szolgál. 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 rendszer a kijelölt szabályok alapján szűri a példányok által ILogger í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, jelölje ki az összes szabályt egy üres szolgáltatóval.
  • 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. Ez a kategória szerepel a példány által létrehozott minden egyes naplóüzenetben ILogger. A kategóriasztring tetszőleges, de a konvenció a teljes 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 lehet 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ű a hívással CreateLogger a teljes típusnévvel T.

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 0 LogDebug Hibakereséshez és fejlesztéshez. A nagy mennyiség miatt óvatosan használja éles környezetben.
Tájékoztatás 2 LogInformation Nyomon követi az alkalmazás általános folyamatát. Hosszú távú érték is lehet.
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 Nem kezelhető hibák és kivételek esetén. 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 hívna Log(LogLevel, ...), a legtöbb fejlesztő a Log{LogLevel} bővítménymetszeteket hívja meg. 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 hozza létre Information és Warning naplózza:

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éterAppLogEvents.Read a 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:

  • Éles környezetben:
    • A naplózás vagy szintek TraceDebug nagy mennyiségű részletes naplóüzenetet eredményeznek. A költségek szabályozása és az adattárolási korlátok túllépése érdekében naplózza Trace és Debug szintelje az üzeneteket egy nagy mennyiségű, alacsony költségű adattárba. Fontolja meg a korlátozást Trace és Debug az adott kategóriákat.
    • A szinteken Warning való Critical naplózásnak kevés naplóüzenetet kell létrehoznia.
      • 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.
  • Fejlesztés alatt:
    • Állítsa Warning értékre.
    • Hozzáadás Trace vagy Debug üzenetek hibaelhárításkor. A kimenet korlátozásához állítsa be Trace vagy Debug csak a vizsgált kategóriákra.

A következő JSON-készletek Logging:Console:LogLevel:Microsoft:Information:

{
    "Logging": {
        "LogLevel": {
            "Microsoft": "Warning"
        },
        "Console": {
            "LogLevel": {
                "Microsoft": "Information"
            }
        }
    }
}

Naplóesemény azonosítója

Minden napló megadhat egy eseményazonosítót, amely EventId egy olyan struktúra, amely írásvédett Name tulajdonságokkal rendelkezikId. 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 esemény intEventIdkonvertálásáról: EventId.Implicit(Int32 to EventId) operátor.

Az eseményazonosító események egy készletét társítja. Előfordulhat például, hogy az adattár értékeinek 1001beolvasásával kapcsolatos összes napló.

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, nem 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 a naplózási szolgáltatók számára a szemantikai vagy strukturált naplózás implementálását. 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 és RunTime rendelkezhet tulajdonsá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 RunTime tartomá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 helyőrző formázást. A sablonok szabadon megadhatnak bármilyen érvényes formátumot 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 a naplózó üzenetsablonjának megfelelő PlaceHolderName típus. 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ó és DateTimeDateTimeOffset formázás: 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 a helyőrző szintaxist {} a kimenettel együtt is megjelenítheti. Végül a sztring interpolációja a csábító 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 alkalmazásbeállításokat. 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();

Az előző kód akkor jeleníti meg a konzolnaplókat, ha a kategória tartalmaz Example vagy Microsoft a naplószint magasabb Information vagy magasabb.

Naplóhatókörök

A hatókörök logikai műveletek halmazát csoportosítják. Ezzel a csoportosítással ugyanazokat az adatokat csatolhatja a csoport 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:

A következő szolgáltatók támogatják a hatóköröket:

Hatókör használata a naplózóhívások blokkban using való körbefuttatásával:

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.AddConsole(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 ILogger példány lekérésével jelentkezik be Main 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ézne 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 képesek újra betölteni 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 a konfiguráció kódban módosul, 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

ILoggerFactory A ILogger<TCategoryName> .NET SDK-k többsége implicit csomaghivatkozásként tartalmazza az interfészeket és az implementációkat. 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.

Lásd még