Rejestrowanie na platformie .NET
Platforma .NET obsługuje interfejs API rejestrowania, który współpracuje z różnymi wbudowanymi i zewnętrznymi dostawcami rejestrowania. W tym artykule pokazano, jak używać interfejsu API rejestrowania z wbudowanymi dostawcami. Większość przykładów kodu przedstawionych w tym artykule ma zastosowanie do dowolnej aplikacji platformy .NET korzystającej z hosta ogólnego. W przypadku aplikacji, które nie korzystają z hosta ogólnego, zobacz Aplikacja konsolowa nienależące do hosta.
Porada
Cały przykładowy kod źródłowy rejestrowania jest dostępny w przeglądarce samples do pobrania. Aby uzyskać więcej informacji, zobacz Przeglądanie przykładów kodu: rejestrowanie na platformie .NET.
Ważne
Począwszy od platformy .NET 6, usługi rejestrowania nie rejestrują ILogger już typu. W przypadku korzystania z rejestratora określ alternatywę ILogger<TCategoryName> typu ogólnego lub zarejestruj iniekcjęILogger zależności (DI).
Tworzenie dzienników
Aby utworzyć dzienniki, użyj ILogger<TCategoryName> obiektu z di.
Poniższy przykład:
- Tworzy rejestrator,
ILogger<Worker>, który używa kategorii dziennika w pełni kwalifikowanej nazwy typuWorker. Kategoria dziennika to ciąg skojarzony z każdym dziennikiem. - Wywołuje metodę LogInformation w celu rejestrowania na poziomie
Information. Poziom dziennika wskazuje ważność zarejestrowanego zdarzenia.
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger) =>
_logger = logger;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.UtcNow);
await Task.Delay(1000, stoppingToken);
}
}
}
Poziomy i kategorie zostały szczegółowo wyjaśnione w dalszej części tego artykułu.
Konfigurowanie rejestrowania
Konfiguracja rejestrowania jest często udostępniana przez sekcję Loggingustawień aplikacji.{Environment} Pliki json. Następujące ustawienia aplikacji. Plik Development.json jest generowany przez szablony usługi Proces roboczy platformy .NET:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
W powyższym kodzie JSON:
- Określono kategorie
"Default","Microsoft"i"Microsoft.Hosting.Lifetime". - Kategoria
"Microsoft"dotyczy wszystkich kategorii rozpoczynających się ciągiem"Microsoft". - Kategoria
"Microsoft"dokonuje rejestracji na poziomie dziennikaWarningi wyższym. - Kategoria
"Microsoft.Hosting.Lifetime"jest bardziej określona niż kategoria"Microsoft", więc kategoria"Microsoft.Hosting.Lifetime"rejestruje na poziomie dziennika „Informacje” i wyższym. - Nie określono konkretnego dostawcy dziennika, więc właściwość
LogLeveldotyczy wszystkich włączonych dostawców rejestrowania z wyjątkiem dostawcy Windows EventLog.
Właściwość Logging może mieć wyliczenie LogLevel i właściwości dostawcy dziennika. Wyliczenie LogLevel określa minimalny poziom rejestrowania dla wybranych kategorii. W poprzednim formacie JSON Information i Warning określono poziomy dziennika. Wyliczenie LogLevel określa ważność dziennika i ma wartość z zakresu od 0 do 6:
Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 i None = 6.
Gdy wyliczenie LogLevel jest określone, rejestrowanie jest włączone dla komunikatów na tym i wyższym poziomie. W poprzednim formacie JSON kategoria jest rejestrowana Default i Information wyższa. Rejestrowane są na przykład komunikaty na poziomach Information, Warning, Error i Critical. Jeśli wyliczenie LogLevel nie zostanie określone, dla rejestrowania stosowany jest poziom domyślny Information. Aby uzyskać więcej informacji, zobacz Poziomy dziennika.
Właściwość dostawcy może określać właściwość LogLevel. Właściwość LogLevel w sekcji dostawcy określa poziomy, które mają być rejestrowane dla tego dostawcy, i zastępuje ustawienia dziennika bez określonego dostawcy. Rozważmy następujący plik appsettings.json :
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
Ustawienia w Logging.{ProviderName}.LogLevel zastępują ustawienia w Logging.LogLevel. W poprzednim formacie JSON Debug domyślny poziom dziennika dostawcy ma wartość Information:
Logging:Debug:LogLevel:Default:Information
Poprzednie ustawienie określa poziom dziennika Information dla każdej kategorii Logging:Debug: z wyjątkiem kategorii Microsoft.Hosting. Gdy jest określona konkretna kategoria, zastępuje ona kategorię domyślną. W poprzednim formacie JSON Logging:Debug:LogLevel kategorie "Microsoft.Hosting" i "Default" przesłaniają ustawienia w pliku Logging:LogLevel
Minimalny poziom dziennika można określić dla:
- określonych dostawców, na przykład
Logging:EventSource:LogLevel:Default:Information - określonych kategorii, na przykład:
Logging:LogLevel:Microsoft:Warning - wszystkich dostawców i wszystkich kategorii:
Logging:LogLevel:Default:Warning
Wszystkie dzienniki poniżej minimalnego poziomu nie są:
- przekazywane do dostawcy,
- rejestrowane ani wyświetlane.
Aby pominąć wszystkie dzienniki, określ wartość LogLevel.None. Poziom LogLevel.None ma wartość 6, która jest wyższa niż w przypadku poziomu LogLevel.Critical (5).
Jeśli dostawca obsługuje zakresy dzienników, właściwość IncludeScopes wskazuje, czy są one włączone. Aby uzyskać więcej informacji, zobacz zakresy dzienników
Następujący plik appsettings.json zawiera ustawienia dla wszystkich wbudowanych dostawców:
{
"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"
}
}
}
}
W powyższym przykładzie:
- Kategorie i poziomy nie mają sugerowanych wartości. Przykład ma na celu pokazanie wszystkich dostawców domyślnych.
- Ustawienia w
Logging.{ProviderName}.LogLevelzastępują ustawienia wLogging.LogLevel. Na przykład poziom w sekcjiDebug.LogLevel.Defaultzastępuje poziom w sekcjiLogLevel.Default. - Każdy alias dostawcy jest używany. Każdy dostawca ma zdefiniowany alias, którego można używać w konfiguracji zamiast w pełni kwalifikowanej nazwy typu. Aliasy wbudowanych dostawców to:
- Konsola
- Debugowanie
- EventSource
- EventLog
- AzureAppServicesFile
- AzureAppServicesBlob
- ApplicationInsights
Ustawianie poziomu dziennika za pośrednictwem wiersza polecenia, zmiennych środowiskowych i innej konfiguracji
Poziom dziennika można ustawić za pośrednictwem dowolnego dostawcy konfiguracji. Można na przykład utworzyć utrwałą zmienną środowiskową o nazwie Logging:LogLevel:Microsoft o wartości Information.
- Wiersz polecenia
- Program PowerShell
- Bash
Utwórz i przypisz utrwałą zmienną środowiskową, biorąc pod uwagę wartość poziomu dziennika.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
W nowym wystąpieniu wiersza polecenia odczytaj zmienną środowiskową.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
Poprzednie ustawienie środowiska jest utrwalane w środowisku. Aby przetestować ustawienia podczas korzystania z aplikacji utworzonej przy użyciu szablonów usługi Proces roboczy platformy .NET, użyj dotnet run polecenia w katalogu projektu po przypisaniu zmiennej środowiskowej.
dotnet run
Porada
Po ustawieniu zmiennej środowiskowej uruchom ponownie zintegrowane środowisko projektowe (IDE), aby upewnić się, że nowo dodane zmienne środowiskowe są dostępne.
W usłudze Azure App Service wybierz pozycję Nowe ustawienie aplikacji na stronie Ustawienia > Konfiguracja. Ustawienia aplikacji usługi Azure App Service są:
- szyfrowane podczas przechowywania i przesyłane za pośrednictwem zaszyfrowanego kanału,
- uwidaczniane jako zmienne środowiskowe.
Aby uzyskać więcej informacji na temat ustawiania wartości konfiguracji platformy .NET przy użyciu zmiennych środowiskowych, zobacz zmienne środowiskowe.
Jak są stosowane reguły filtrowania
Po utworzeniu obiektu ILogger<TCategoryName> obiekt ILoggerFactory wybiera jedną regułę dla każdego dostawcy, która ma być stosowana do tego rejestratora. Wszystkie komunikaty zapisywane przez wystąpienie ILogger są filtrowane na podstawie wybranych reguł. Z dostępnych reguł wybierana jest najbardziej konkretna reguła dla każdej pary dostawcy i kategorii.
Następujący algorytm jest używany dla każdego dostawcy podczas tworzenia obiektu ILogger dla danej kategorii:
- Wybierz wszystkie reguły zgodne z dostawcą lub jego aliasem. Jeśli nie zostanie znalezione żadne dopasowanie, wybierz wszystkie reguły z pustym dostawcą.
- Z wyników poprzedniego kroku wybierz reguły z najdłuższym pasującym prefiksem kategorii. Jeśli nie zostanie znalezione żadne dopasowanie, wybierz wszystkie reguły, które nie określają kategorii.
- Jeśli wybrano wiele reguł, użyj ostatniej.
- Jeśli nie wybrano żadnych reguł, użyj polecenia LoggingBuilderExtensions.SetMinimumLevel(ILoggingBuilder, LogLevel) , aby określić minimalny poziom rejestrowania.
Kategoria dziennika
Po utworzeniu obiektu ILogger jest określana kategoria. Ta kategoria jest uwzględniania w każdym komunikacie dziennika utworzonym przez to wystąpienie ILogger. Ciąg kategorii jest dowolny, ale przyjęto konwencję używania nazwy klasy. Na przykład w aplikacji z usługą zdefiniowaną tak jak następujący obiekt kategoria może mieć "Example.DefaultService"wartość :
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
Aby jawnie określić kategorię, wywołaj metodę LoggerFactory.CreateLogger:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("CustomCategory");
// ...
}
}
Wywoływanie CreateLogger przy użyciu stałej nazwy może być przydatne w przypadku użycia w wielu klasach/typach, dzięki czemu zdarzenia mogą być zorganizowane według kategorii.
ILogger<T> jest równoważne wywołaniu metody CreateLogger z w pełni kwalifikowaną nazwą typu T.
Poziom dziennika
Poniższa tabela zawiera wartości LogLevel, wygodną metodę rozszerzenia Log{LogLevel} i sugerowane użycie:
| LogLevel | Wartość | Metoda | Opis |
|---|---|---|---|
| Ślad | 0 | LogTrace | Obejmuje najbardziej szczegółowe komunikaty. Te komunikaty mogą zawierać poufne dane aplikacji. Komunikaty są domyślnie wyłączone i nie powinny być włączane w środowisku produkcyjnym. |
| Debugowanie | 1 | LogDebug | Na potrzeby debugowania i programowania. Należy zachować ostrożność w środowisku produkcyjnym ze względu na dużą pojemność. |
| Informacje | 2 | LogInformation | Śledzi ogólny przepływ aplikacji. Może mieć wartość długoterminową. |
| Ostrzeżenie | 3 | LogWarning | Na potrzeby nietypowych lub nieoczekiwanych zdarzeń. Zazwyczaj obejmuje błędy lub warunki, które nie powodują awarii aplikacji. |
| Błąd | 4 | LogError | Na potrzeby błędów i wyjątków, których nie można obsłużyć. Te komunikaty wskazują na błąd w bieżącej operacji lub żądaniu, a nie awarię całej aplikacji. |
| Krytyczne | 5 | LogCritical | Na potrzeby awarii wymagających natychmiastowej uwagi. Przykłady: scenariusze utraty danych, brak miejsca na dysku. |
| Brak | 6 | Określa, że nie należy zapisywać żadnych komunikatów. |
W powyższej tabeli obiekty LogLevel uporządkowano w kolejności od najniższej do najwyższej ważności.
Pierwszy parametr metody Log, LogLevel, wskazuje ważność dziennika. Zamiast wywoływać metodę Log(LogLevel, ...), większość deweloperów wywołuje metody rozszerzenia Log{LogLevel}. Metody rozszerzenia Log{LogLevel}wywołają metodę Log i określają wartość elementu LogLevel. Na przykład dwa poniższe wywołania rejestrowania działają tak samo i tworzą ten sam dziennik:
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details jest identyfikatorem zdarzenia i jest niejawnie reprezentowany przez wartość stałą Int32 . AppLogEvents jest klasą, która uwidacznia różne nazwane stałe identyfikatora i jest wyświetlana w sekcji Identyfikator zdarzenia dziennika .
Poniższy kod tworzy dzienniki Information i Warning:
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;
}
W powyższym kodzie pierwszym parametrem metody Log{LogLevel}, AppLogEvents.Read, jest identyfikator zdarzenia dziennika. Drugi parametr to szablon komunikatu z symbolami zastępczymi dla wartości argumentów dostarczanych przez pozostałe parametry metody. Parametry metody zostały wyjaśnione w sekcji szablonu komunikatu w dalszej części tego artykułu.
Skonfiguruj odpowiedni poziom dziennika i wywołaj poprawne Log{LogLevel} metody, aby kontrolować ilość danych wyjściowych dziennika zapisywanych na określonym nośniku magazynu. Przykład:
- Podczas produkcji:
- Rejestrowanie na poziomach
TraceiDebuggeneruje dużą ilość szczegółowych komunikatów dziennika. Aby kontrolować koszty i nie przekraczać limitów magazynowania danych, rejestruj komunikaty dziennika na poziomieTraceiDebugw magazynie danych o dużej pojemności i niskiej cenie. Rozważ ograniczenie dziennikówTraceiDebugdo określonych kategorii. - Rejestrowanie na poziomach od
WarningdoCriticalpowinno generować kilka komunikatów dziennika.- Koszty i limity magazynu zwykle nie są tu problemem.
- Niewielka liczba dzienników zapewnia większą swobodę wyboru magazynu danych.
- Rejestrowanie na poziomach
- Podczas programowania:
- Ustaw wartość
Warning. - Dodaj komunikaty
TracelubDebugpodczas rozwiązywania problemów. Aby ograniczyć ilość danych wyjściowych, poziomTracelubDebugustawiaj tylko dla kategorii, które są badane.
- Ustaw wartość
Następujące zestawy Logging:Console:LogLevel:Microsoft:InformationJSON:
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Identyfikator zdarzenia dziennika
Każdy dziennik może określić identyfikator zdarzenia, EventId jest strukturą z opcjonalnymi Name właściwościami Id tylko do odczytu. Przykładowy kod źródłowy używa AppLogEvents klasy do definiowania identyfikatorów zdarzeń:
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal EventId Create = new(1000, "Created");
internal EventId Read = new(1001, "Read");
internal EventId Update = new(1002, "Updated");
internal 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 EventId ReadNotFound = 4000;
internal EventId UpdateNotFound = 4001;
// ...
}
Porada
Aby uzyskać więcej informacji na temat konwertowania int obiektu na element EventId, zobacz EventId.Implicit(Int32 to EventId) Operator.
Identyfikator zdarzenia kojarzy zestaw zdarzeń. Na przykład wszystkie dzienniki związane z odczytywaniem wartości z repozytorium mogą mieć wartość 1001.
Dostawca rejestrowania może rejestrować identyfikator zdarzenia w polu identyfikatora, w komunikacie rejestrowania lub w ogóle nie. Dostawca debugowania nie pokazuje identyfikatorów zdarzeń. Dostawca konsoli wyświetla identyfikatory zdarzeń w nawiasach kwadratowych po kategorii:
info: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) not found
Niektórzy dostawcy rejestrowania przechowują identyfikator zdarzenia w polu, co umożliwia filtrowanie po identyfikatorze.
Szablon komunikatu dziennika
Każdy interfejs API dziennika używa szablonu komunikatu. Szablon komunikatu może zawierać symbole zastępcze, dla których są podawane argumenty. Dla symboli zastępczych należy używać nazw, a nie liczb. Kolejność symboli zastępczych, a nie ich nazwy, określa, które parametry są używane do podawania ich wartości. W poniższym kodzie nazwy parametrów są poza sekwencyjne w szablonie komunikatu:
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Powyższy kod tworzy komunikat dziennika z wartościami parametrów w sekwencji:
Parameter values: param1, param2
Uwaga
Należy pamiętać o używaniu wielu symboli zastępczych w ramach jednego szablonu wiadomości, ponieważ są one oparte na porządkowych elementach. Nazwy nie są używane do wyrównywania argumentów do symboli zastępczych.
Takie podejście umożliwia dostawcom rejestrowania zaimplementowanie rejestrowania semantycznego lub strukturalnego. Same argumenty są przekazywane do systemu rejestrowania, a nie tylko do sformatowanego szablonu komunikatu. Dzięki temu dostawcy rejestrowania mogą przechowywać wartości parametrów jako pola. Rozważmy następującą metodę rejestratora:
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Na przykład podczas rejestrowania w usłudze Azure Table Storage:
- Każda jednostka tabeli platformy Azure może mieć właściwości
IDiRunTime. - Tabele z właściwościami upraszczają wykonywanie zapytań dotyczących zarejestrowanych danych. Na przykład zapytanie może znaleźć wszystkie dzienniki w określonym zakresie
RunTimebez konieczności analizowania czasu z komunikatu tekstowego.
Formatowanie szablonu komunikatu dziennika
Szablony komunikatów dziennika obsługują formatowanie zastępcze. Szablony są bezpłatne do określenia dowolnego prawidłowego formatu dla danego argumentu typu. Rozważmy na przykład następujący Information szablon komunikatu rejestratora:
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
W poprzednim przykładzie DateTimeOffset wystąpienie jest typem odpowiadającym PlaceHolderName szablonowi komunikatu rejestratora. Ta nazwa może być niczym, ponieważ wartości są oparte na porządkowych. Format MMMM dd, yyyy jest prawidłowy dla DateTimeOffset typu.
Aby uzyskać więcej informacji na DateTime temat formatowania i DateTimeOffset formatowania, zobacz Niestandardowe ciągi formatu daty i godziny.
Przykłady formatowania szablonu komunikatu dziennika
Szablony komunikatów dziennika umożliwiają formatowanie symboli zastępczych. W poniższych przykładach pokazano, jak sformatować szablon komunikatu przy użyciu składni symbolu zastępczego {} . Ponadto przykład ucieczki składni symbolu zastępczego {} jest wyświetlany z jego danymi wyjściowymi. Na koniec pokazano również interpolację ciągów z symbolami zastępczymi tworzenia szablonów:
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
Porada
Podczas rejestrowania zawsze należy używać formatowania szablonu komunikatów dziennika. Należy unikać interpolacji ciągów, ponieważ może to powodować problemy z wydajnością.
Rejestrowanie wyjątków
Metody rejestratora mają przeciążenia, które przyjmują parametr wyjątku:
public void Test(string id)
{
try
{
if (id == "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
Rejestrowanie wyjątków jest specyficzne dla dostawcy.
Domyślny poziom dziennika
Jeśli domyślny poziom dziennika nie jest ustawiony, domyślną wartością poziomu dziennika jest Information.
Rozważmy na przykład następującą aplikację usługi procesu roboczego:
- Utworzony za pomocą szablonów procesów roboczych platformy .NET.
- appsettings.json i appsettings. Plik Development.json został usunięty lub zmieniono jego nazwę.
W przypadku poprzedniej konfiguracji przejście do strony prywatności lub strony głównej powoduje wygenerowanie wielu komunikatów Trace, Debug i Information z ciągiem Microsoft w nazwie kategorii.
Poniższy kod ustawia domyślny poziom dziennika, kiedy domyślny poziom dziennika nie jest ustawiony w konfiguracji:
class Program
{
static Task Main(string[] args) =>
CreateHostBuilder(args).Build().RunAsync();
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));
}
Funkcja filtru
Funkcja filtru jest wywoływana dla wszystkich dostawców i kategorii, dla których nie przypisano reguł za pomocą konfiguracji lub kodu:
await Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
}))
.Build()
.RunAsync();
Powyższy kod wyświetla dzienniki konsoli, gdy kategoria zawiera parametr Example lub Microsoft, a poziom dziennika ma wartość Information lub wyższą.
Zakresy dziennika
Zakres może grupować zestaw operacji logicznych. To grupowanie może służyć do dołączania tych samych danych do każdego dziennika utworzonego w ramach zestawu. Na przykład każdy dziennik utworzony w ramach przetwarzania transakcji może zawierać identyfikator transakcji.
Zakres:
- jest typem IDisposable zwracanym przez metodę BeginScope,
- trwa do momentu usunięcia.
Następujący dostawcy obsługują zakresy:
Użyj zakresu, opakowując wywołania rejestratora za pomocą bloku using:
public async Task<T> GetAsync<T>(string id)
{
T result;
using (_logger.BeginScope("using block message"))
{
_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;
}
Poniższy kod JSON włącza zakresy dla dostawcy konsoli:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
Poniższy kod włącza zakresy dla dostawcy konsoli:
await Host.CreateDefaultBuilder(args)
.ConfigureLogging((_, logging) =>
logging.ClearProviders()
.AddConsole(options => options.IncludeScopes = true))
.Build()
.RunAsync();
Aplikacja konsolowa bez hosta
Kod rejestrowania aplikacji bez hosta ogólnego różni się w sposobie dodawania dostawców i tworzenia rejestratorów. W aplikacji konsolowej bez hosta wywołaj metodę rozszerzenia Add{provider name} dostawcy podczas tworzenia elementu LoggerFactory:
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
Obiekt loggerFactory jest używany do tworzenia ILogger wystąpienia.
Tworzenie dzienników w pliku Main
Poniższy kod rejestruje w pliku Main, uzyskując wystąpienie ILogger z DI po utworzeniu hosta:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
IHost host = Host.CreateDefaultBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
Powyższy kod opiera się na dwóch pakietach NuGet:
Plik projektu będzie wyglądać podobnie do następującego:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
</ItemGroup>
</Project>
Brak metod rejestratora asynchronicznego
Rejestrowanie powinno być tak szybkie, że nie jest warte kosztu wydajności kodu asynchronicznego. Jeśli magazyn danych rejestrowania działa wolno, nie zapisuj go bezpośrednio. Rozważ zapisywanie komunikatów dziennika najpierw w szybkim magazynie, a później przenoszenie ich do powolnego magazynu. Na przykład w przypadku rejestrowania w programie SQL Server nie rób tego bezpośrednio w metodzie Log, ponieważ metody Log są synchroniczne. Zamiast tego synchronicznie dodaj komunikaty dziennika do kolejki w pamięci, a następnie za pomocą procesu roboczego w tle ściągaj komunikaty z kolejki, aby wykonać asynchroniczne zadanie wypychania danych do programu SQL Server.
Zmienianie poziomów dziennika w uruchomionej aplikacji
Interfejs API rejestrowania nie obejmuje scenariusza zmieniania poziomów dziennika podczas działania aplikacji. Jednak niektórzy dostawcy konfiguracji mogą ponownie ładować konfigurację, która jest natychmiast stosowna w konfiguracji rejestrowania. Na przykład dostawca konfiguracji plików domyślnie ponownie ładuje konfigurację rejestrowania. Jeśli konfiguracja zostanie zmieniona w kodzie podczas działania aplikacji, aplikacja może wywołać metodę IConfigurationRoot.Reload , aby zaktualizować konfigurację rejestrowania aplikacji.
Pakiety NuGet
Interfejsy ILogger<TCategoryName> i ILoggerFactory i implementacje są uwzględniane w zestawie SDK platformy .NET. Są one również dostępne w następujących pakietach NuGet:
- Interfejsy znajdują się w pliku Microsoft.Extensions.Logging.Abstractions.
- Domyślne implementacje znajdują się w pliku Microsoft.Extensions.Logging.
Stosowanie reguł filtru dziennika w kodzie
Preferowanym podejściem do ustawiania reguł filtrowania dzienników jest użycie konfiguracji.
W poniższym przykładzie pokazano, jak zarejestrować reguły filtrowania w kodzie:
await Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
.Build()
.RunAsync();
logging.AddFilter("System", LogLevel.Debug) określa kategorię System i poziom dziennika Debug. Filtr jest stosowany do wszystkich dostawców, ponieważ nie skonfigurowano żadnego konkretnego dostawcy.
AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) określa następujące elementy:
- Dostawca rejestrowania
Debug. - Poziom dziennika
Informationi wyższy. - Wszystkie kategorie rozpoczynające się od ciągu
"Microsoft".
Zobacz też
- Dostawcy rejestrowania na platformie .NET
- Implementowanie niestandardowego dostawcy rejestrowania na platformie .NET
- Formatowanie dziennika konsoli
- Rejestrowanie o wysokiej wydajności na platformie .NET
- Błędy rejestrowania powinny zostać utworzone w repozytorium github.com/dotnet/runtime