Rejestrowanie na platformie .NET Core i ASP.NET Core

Autorzy: Kirk Larkin, Juergen Gutsch i Rick Anderson

W tym artykule opisano rejestrowanie na platformie .NET, ponieważ ma zastosowanie do aplikacji platformy ASP.NET Core. Aby uzyskać szczegółowe informacje na temat rejestrowania na platformie .NET, zobacz Rejestrowanie na platformie .NET. Aby uzyskać więcej informacji na temat rejestrowania w aplikacjach Blazor, zobacz Rejestrowanie aplikacji Blazor platformy ASP.NET Core.

Dostawcy rejestrowania

Dostawcy rejestrowania przechowują dzienniki, z wyjątkiem dostawcy Console, który wyświetla dzienniki. Na przykład dostawca usługi Azure Application Insights przechowuje dzienniki w usłudze Azure Application Insights. Można włączyć wielu dostawców.

Domyślne szablony aplikacji internetowych ASP.NET Core wywołają metodę WebApplication.CreateBuilder, która dodaje następujących dostawców rejestrowania:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Powyższy kod przedstawia plik Program.cs utworzony przy użyciu szablonów aplikacji internetowych platformy ASP.NET Core. W następnych kilku sekcjach znajdują się przykłady oparte na szablonach aplikacji internetowych platformy ASP.NET Core.

Poniższy kod zastępuje domyślny zestaw dostawców rejestrowania dodanych przez metodę WebApplication.CreateBuilder:

var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

Alternatywnie powyższy kod rejestrowania można napisać w następujący sposób:

var builder = WebApplication.CreateBuilder();
builder.Host.ConfigureLogging(logging =>
{
    logging.ClearProviders();
    logging.AddConsole();
});

Aby uzyskać informacje o dodatkowych dostawcach, zobacz:

Tworzenie dzienników

Aby utworzyć dzienniki, użyj obiektu ILogger<TCategoryName> z wstrzykiwania zależności (DI).

Poniższy przykład:

  • Tworzy rejestrator, ILogger<AboutModel>, który używa kategorii dziennika w pełni kwalifikowanej nazwy typu AboutModel. 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 AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("About page visited at {DT}", 
            DateTime.UtcNow.ToLongTimeString());
    }
}

Poziomy i kategorie zostały omówione bardziej szczegółowo w dalszej części tego dokumentu.

Aby uzyskać informacje na temat struktury Blazor, zobacz Rejestrowanie aplikacji Blazor platformy ASP.NET Core.

Konfigurowanie rejestrowania

Konfiguracja rejestrowania jest na ogół udostępniana przez sekcję Logging plików appsettings.{ENVIRONMENT}.json, gdzie symbol zastępczy {ENVIRONMENT} oznacza środowisko. Poniższy plik appsettings.Development.json jest generowany przez szablony aplikacji internetowych platformy ASP.NET Core:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  }
}

W powyższym pliku JSON:

  • Określono kategorie "Default" i "Microsoft.AspNetCore".
  • Kategoria "Microsoft.AspNetCore" dotyczy wszystkich kategorii rozpoczynających się ciągiem "Microsoft.AspNetCore". To ustawienie na przykład dotyczy kategorii "Microsoft.AspNetCore.Routing.EndpointMiddleware".
  • Kategoria "Microsoft.AspNetCore" dokonuje rejestracji na poziomie dziennika Warning i wyższym.
  • Nie określono konkretnego dostawcy dziennika, więc właściwość LogLevel dotyczy 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 pliku JSON określono poziomy dziennika Information i Warning. 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 pliku JSON kategoria Default jest rejestrowana na poziomie Information i wyższym. 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ż użycie następującego pliku appsettings.json:

{
  "Logging": {
    "LogLevel": { // All providers, LogLevel applies to all the enabled providers.
      "Default": "Error", // Default logging, Error and higher.
      "Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information", // Overrides preceding LogLevel:Default setting.
        "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
      }
    },
    "EventSource": { // EventSource provider
      "LogLevel": {
        "Default": "Warning" // All categories of EventSource provider.
      }
    }
  }
}

Ustawienia w sekcji Logging.{PROVIDER NAME}.LogLevel zastępują ustawienia w sekcji Logging.LogLevel, gdzie symbol zastępczy {PROVIDER NAME} jest nazwą dostawcy. W powyższym pliku JSON domyślny poziom dziennika dostawcy Debug jest ustawiony na 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 powyższym pliku JSON kategorie "Microsoft.Hosting" i "Default" w sekcji Logging:Debug:LogLevel zastępują ustawienia w sekcji 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 poziom 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.

W poniższym pliku appsettings.json wszyscy dostawcy są domyślnie włączeni:

{
  "Logging": {
    "LogLevel": { // No provider, LogLevel applies to all the enabled providers.
      "Default": "Error",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information" // Overrides preceding LogLevel:Default setting.
      }
    },
    "Console": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "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 są sugerowane wartości. Przykład jest udostępniany w celu wyświetlenia wszystkich domyślnych dostawców.
  • Ustawienia w sekcji Logging.{PROVIDER NAME}.LogLevel zastępują ustawienia w sekcji Logging.LogLevel, gdzie symbol zastępczy {PROVIDER NAME} jest nazwą dostawcy. Na przykład poziom w sekcji Debug.LogLevel.Default zastępuje poziom w sekcji LogLevel.Default.
  • Dla każdego dostawcy domyślnego użyto aliasu. Każdy dostawca ma zdefiniowany alias, którego można używać w konfiguracji zamiast w pełni kwalifikowanej nazwy typu. Wbudowane aliasy dostawców to:
    • Console
    • Debug
    • EventSource
    • EventLog
    • AzureAppServicesFile
    • AzureAppServicesBlob
    • ApplicationInsights

Rejestrowanie w pliku Program.cs

Poniższy przykład wywołuje metodę Builder.WebApplication.Logger w pliku Program.cs i rejestruje komunikaty informacyjne:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogInformation("Adding Routes");
app.MapGet("/", () => "Hello World!");
app.Logger.LogInformation("Starting the app");
app.Run();

Poniższy przykład wywołuje metodę AddConsole w pliku Program.cs i rejestruje punkt końcowy /Test:

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddConsole();

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
    logger.LogInformation("Testing logging in Program.cs");
    await response.WriteAsync("Testing");
});

app.Run();

Poniższy przykład wywołuje metodę AddSimpleConsole w pliku Program.cs, wyłącza kolory dla danych wyjściowych i rejestruje punkt końcowy /Test:

using Microsoft.Extensions.Logging.Console;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddSimpleConsole(i => i.ColorBehavior = LoggerColorBehavior.Disabled);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
    logger.LogInformation("Testing logging in Program.cs");
    await response.WriteAsync("Testing");
});

app.Run();

Ustawianie poziomu dziennika za pośrednictwem wiersza polecenia, zmiennych środowiskowych i innej konfiguracji

Poziom dziennika można ustawić za pośrednictwem dowolnego dostawcy konfiguracji.

Separator : nie współdziała z kluczami hierarchicznymi zmiennych środowiskowych na wszystkich platformach. Symbol __ (podwójne podkreślenie):

  • Jest obsługiwany przez wszystkie platformy. Na przykład separator : nie jest obsługiwany przez powłokę Bash, a separator __ jest.
  • Jest automatycznie zastępowany przez :

Poniższe polecenia:

  • Ustawiają klucz środowiska Logging:LogLevel:Microsoft na wartość Information w systemie Windows.
  • Testują ustawienia w przypadku używania aplikacji utworzonej przy użyciu szablonów aplikacji internetowych platformy ASP.NET Core. Polecenie dotnet run należy uruchomić w katalogu projektu po użyciu polecenia set.
set Logging__LogLevel__Microsoft=Information
dotnet run

Poprzednie ustawienia środowiska:

  • są ustawiane tylko w procesach uruchamianych z poziomu okna poleceń, w którym zostały ustawione;
  • nie są odczytywane przez przeglądarki uruchamiane za pomocą programu Visual Studio.

Poniższe polecenie setx również ustawia klucz środowiska i wartość w systemie Windows. W przeciwieństwie do polecenia set, ustawienia polecenia setx są trwałe. Przełącznik /M ustawia zmienną w środowisku systemowym. Jeśli przełącznik /M nie jest używany, ustawiana jest zmienna środowiskowa użytkownika.

setx Logging__LogLevel__Microsoft Information /M

Rozważ użycie następującego pliku appsettings.json:

"Logging": {
  "Console": {
    "LogLevel": {
      "Microsoft.Hosting.Lifetime": "Trace"
    }
  }
}

Poniższe polecenie ustawia powyższą konfigurację w środowisku:

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

Uwaga

Podczas konfigurowania zmiennych środowiskowych z nazwami zawierającymi . (kropki) w systemach macOS i Linux należy rozważyć "Eksportowanie zmiennej z kropką (.) w nim" pytanie w witrynie Stack Exchange i odpowiadające jej zaakceptowanej odpowiedzi.

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, zobacz aplikacja systemu Azure: Zastępowanie konfiguracji aplikacji przy użyciu witryny Azure Portal.

Aby uzyskać więcej informacji na temat ustawiania wartości konfiguracji platformy ASP.NET Core przy użyciu zmiennych środowiskowych, zobacz zmienne środowiskowe. Aby uzyskać informacje na temat korzystania z innych źródeł konfiguracji, w tym wiersza polecenia, usługi Azure Key Vault, usługi Azure App Configuration, innych formatów plików i nie tylko, zobacz Konfiguracja na platformie ASP.NET Core.

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 MinimumLevel.

Rejestrowanie danych wyjściowych z polecenia dotnet run i programu Visual Studio

Zostaną wyświetlone dzienniki utworzone przy użyciu domyślnych dostawców rejestrowania:

  • W programie Visual Studio
    • W oknie danych wyjściowych debugowania podczas debugowania.
    • W oknie serwera internetowego platformy ASP.NET Core.
  • W oknie konsoli w przypadku uruchomieniu aplikacji za pomocą polecenia dotnet run.

Dzienniki rozpoczynające się od kategorii „Microsoft” pochodzą z kodu platformy ASP.NET Core. Platforma ASP.NET Core i kod aplikacji używają tego samego interfejsu API rejestrowania i tych samych dostawców.

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 konwencja polega na użyciu w pełni kwalifikowanej nazwy klasy. Na przykład w kontrolerze nazwa może mieć postać "TodoApi.Controllers.TodoController". Aplikacje internetowe platformy ASP.NET Core używają ILogger<T>, aby automatycznie pobierać wystąpienie ILogger, które używa w pełni kwalifikowanej nazwy typu T jako kategorii:

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.PrivacyModel called.");
    }
}

Jeśli wymagana jest dalsza kategoryzacja, konwencja polega na użyciu nazwy hierarchicznej przez dołączenie podkategorii do w pełni kwalifikowanej nazwy klasy i jawne określenie kategorii przy użyciu polecenia ILoggerFactory.CreateLogger:

public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.ContactModel called.");
    }

Wywoływanie metody CreateLogger ze stałą nazwą może być przydatne w przypadku użycia w wielu metodach, 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:

PoziomRejestrowania Wartość Metoda opis
Trace 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.
Debug 1 LogDebug Na potrzeby debugowania i programowania. Należy zachować ostrożność w środowisku produkcyjnym ze względu na dużą pojemność.
Information 2 LogInformation Śledzi ogólny przepływ aplikacji. Może mieć wartość długoterminową.
Warning 3 LogWarning Na potrzeby nietypowych lub nieoczekiwanych zdarzeń. Zazwyczaj obejmuje błędy lub warunki, które nie powodują awarii aplikacji.
Error 100 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.
Critical 5 LogCritical Na potrzeby awarii wymagających natychmiastowej uwagi. Przykłady: scenariusze utraty danych, brak miejsca na dysku.
None 6 Określa, że kategoria rejestrowania nie powinna zapisywać 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{LOG LEVEL}, gdzie symbol zastępczy {LOG LEVEL} jest poziomem dziennika. Na przykład dwa poniższe wywołania rejestrowania działają tak samo i tworzą ten sam dziennik:

[HttpGet]
public IActionResult Test1(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);

    _logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    return ControllerContext.MyDisplayRouteInfo();
}

MyLogEvents.TestItem to identyfikator zdarzenia. MyLogEvents jest częścią przykładowej aplikacji i jest wyświetlany w sekcji Identyfikator zdarzenia dziennika.

Metody MyDisplayRouteInfo i ToCtxString są dostarczane przez pakiet NuGet Rick.Docs.Samples.RouteInfo. Metody te wyświetlają informacje o trasie Controller i Razor Page.

Poniższy kod tworzy dzienniki Information i Warning:

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

W powyższym kodzie pierwszym parametrem metody Log{LOG LEVEL}, MyLogEvents.GetItem, 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 omówione w sekcji dotyczące szablonu komunikatu w dalszej części tego dokumentu.

Wywołaj odpowiednią metodę Log{LOG LEVEL}, aby kontrolować ilość danych wyjściowych dziennika zapisywanych na określonym nośniku magazynu. Na przykład:

  • W środowisku produkcyjnym:
    • Rejestrowanie na poziomach Trace, Debuglub Information generuje dużą ilość szczegółowych komunikatów dziennika. Aby kontrolować koszty i nie przekraczać limitów magazynu danych, dzienników Trace, Debuglub Information komunikatów na poziomie do magazynu danych o wysokim poziomie. Rozważ ograniczenie Tracewartości , Debuglub Information do określonych kategorii.
    • Rejestrowanie na poziomach od Warning do Critical powinno 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.
  • W programowania:
    • Ustaw wartość Warning.
    • Dodaj Tracekomunikaty , Debuglub Information podczas rozwiązywania problemów. Aby ograniczyć dane wyjściowe, ustaw Tracewartości , Debuglub Information tylko dla kategorii objętych badaniem.

Platforma ASP.NET Core zapisuje dzienniki dla zdarzeń struktury. Rozważmy na przykład dane wyjściowe dziennika dla:

  • Aplikacji Razor Pages utworzonej przy użyciu szablonów platformy ASP.NET Core.
  • Dla rejestrowania ustawiono wartość Logging:Console:LogLevel:Microsoft:Information.
  • Nawigacja do strony Privacy:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 149.3023ms 200 text/html; charset=utf-8

Poniższy plik JSON ustawia Logging:Console:LogLevel:Microsoft:Information:

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

Identyfikator zdarzenia dziennika

Każdy dziennik może określać identyfikator zdarzenia. Przykładowa aplikacja używa klasy MyLogEvents, aby definiować identyfikatory zdarzeń:

public class MyLogEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems     = 1001;
    public const int GetItem       = 1002;
    public const int InsertItem    = 1003;
    public const int UpdateItem    = 1004;
    public const int DeleteItem    = 1005;

    public const int TestItem      = 3000;

    public const int GetItemNotFound    = 4000;
    public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Identyfikator zdarzenia kojarzy zestaw zdarzeń. Na przykład wszystkie dzienniki związane z wyświetlaniem listy elementów na stronie mogą mieć wartość 1001.

Dostawca rejestrowania może przechowywać identyfikator zdarzenia w polu identyfikatora, w komunikacie rejestrowania lub wcale. Dostawca debugowania nie pokazuje identyfikatorów zdarzeń. Dostawca konsoli wyświetla identyfikatory zdarzeń w nawiasach kwadratowych po kategorii:

info: TodoApi.Controllers.TodoItemsController[1002]
      Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
      Get(1) 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.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

To, które parametry są używane w celu podania wartości symboli zastępczych w komunikatach dziennika jest określane przez kolejność parametrów, a nie nazwy ich symboli zastępczych. W poniższym kodzie nazwy parametrów w symbolach zastępczych szablonu komunikatu są niezgodne z kolejnością:

var apples = 1;
var pears = 2;
var bananas = 3;

_logger.LogInformation("Parameters: {Pears}, {Bananas}, {Apples}", apples, pears, bananas);

Parametry są jednak przypisywane do symboli zastępczych w kolejności: apples, pears, bananas. Komunikat dziennika odzwierciedla kolejność parametrów:

Parameters: 1, 2, 3

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 na przykład następującą metodę rejestratora:

_logger.LogInformation("Getting item {Id} at {RequestTime}", 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 ID i RequestTime.
  • 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 RequestTime bez konieczności analizowania czasu z komunikatu tekstowego.

Wyjątki dzienników

Metody rejestratora mają przeciążenia, które przyjmują parametr wyjątku:

[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    try
    {
        if (id == 3)
        {
            throw new Exception("Test exception");
        }
    }
    catch (Exception ex)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
        return NotFound();
    }

    return ControllerContext.MyDisplayRouteInfo();
}

Metody MyDisplayRouteInfo i ToCtxString są dostarczane przez pakiet NuGet Rick.Docs.Samples.RouteInfo. Metody te wyświetlają informacje o trasie Controller i Razor Page.

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ę internetową:

  • Utworzona przy użyciu szablonów aplikacji internetowej platformy ASP.NET.
  • Pliki appsettings.json i appsettings.Development.json zostały usunięte lub zmienione.

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:

var builder = WebApplication.CreateBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);

Ogólnie rzecz biorąc, poziomy dziennika powinny być określane w konfiguracji, a nie w kodzie.

Funkcja filtru

Funkcja filtru jest wywoływana dla wszystkich dostawców i kategorii, dla których nie przypisano reguł za pomocą konfiguracji lub kodu:

var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter((provider, category, logLevel) =>
{
    if (provider.Contains("ConsoleLoggerProvider")
        && category.Contains("Controller")
        && logLevel >= LogLevel.Information)
    {
        return true;
    }
    else if (provider.Contains("ConsoleLoggerProvider")
        && category.Contains("Microsoft")
        && logLevel >= LogLevel.Information)
    {
        return true;
    }
    else
    {
        return false;
    }
});

Powyższy kod wyświetla dzienniki konsoli, gdy kategoria zawiera parametr Controller lub Microsoft, a poziom dziennika ma wartość Information lub wyższą.

Ogólnie rzecz biorąc, poziomy dziennika powinny być określane w konfiguracji, a nie w kodzie.

ASP.NET Core i EF Core kategorie

Poniższa tabela zawiera niektóre kategorie używane przez platformy ASP.NET Core i Entity Framework Core wraz z uwagami dotyczącymi dzienników:

Kategoria Uwagi
Microsoft.AspNetCore Ogólna diagnostyka platformy ASP.NET Core.
Microsoft.AspNetCore.DataProtection Które klucze były rozważane, znalezione i użyte.
Microsoft.AspNetCore.HostFiltering Dozwolone hosty.
Microsoft.AspNetCore.Hosting Jak długo trwało wykonywanie żądań HTTP oraz czas ich rozpoczęcia. Które zestawy startowe hostingu zostały załadowane.
Microsoft.AspNetCore.Mvc Diagnostyka MVC i Razor. Powiązanie modelu, wykonywanie filtru, kompilacja widoku, wybór akcji.
Microsoft.AspNetCore.Routing Kierowanie zgodnych informacji.
Microsoft.AspNetCore.Server Odpowiedzi dotyczące uruchomienia i zatrzymania połączenia oraz utrzymania aktywności. Informacje o certyfikacie HTTPS.
Microsoft.AspNetCore.StaticFiles Obsłużone pliki.
Microsoft.EntityFrameworkCore Ogólna diagnostyka platformy Entity Framework Core. Aktywność i konfiguracja bazy danych, wykrywanie zmian, migracje.

Aby wyświetlić więcej kategorii w oknie konsoli, w pliku appsettings.Development.json wprowadź następujące ustawienia:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Trace",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

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:

Następujący dostawcy obsługują zakresy:

Użyj zakresu, opakowując wywołania rejestratora za pomocą bloku using:

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    TodoItem todoItem;
    var transactionId = Guid.NewGuid().ToString();
    using (_logger.BeginScope(new List<KeyValuePair<string, object>>
        {
            new KeyValuePair<string, object>("TransactionId", transactionId),
        }))
    {
        _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

        todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            _logger.LogWarning(MyLogEvents.GetItemNotFound, 
                "Get({Id}) NOT FOUND", id);
            return NotFound();
        }
    }

    return ItemToDTO(todoItem);
}

Wbudowani dostawcy rejestrowania

Platforma ASP.NET Core obejmuje następujących dostawców rejestrowania w ramach struktury udostępnionej:

Następujący dostawcy rejestrowania są dostarczani przez firmę Microsoft, ale nie w ramach struktury udostępnionej. Należy ich zainstalować jako dodatkowe pakiety nuget.

Platforma ASP.NET Core nie zawiera dostawcy rejestrowania na potrzeby zapisywania dzienników w plikach. Aby zapisywać dzienniki w plikach z aplikacji platformy ASP.NET Core, rozważ użycie dostawcy rejestrowania innej firmy.

Aby uzyskać informacje na temat właściwości stdout i rejestrowania debugowania przy użyciu modułu ASP.NET Core Module, zobacz Rozwiązywanie problemów z platformą ASP.NET Core w usługach Azure App Service oraz IIS, a także Moduł ASP.NET Core Module (ANCM) dla usług IIS.

Konsola

Dostawca Console rejestruje dane wyjściowe w konsoli. Aby uzyskać więcej informacji na temat wyświetlania dzienników dostawcy Console w środowisku programistycznym, zobacz Rejestrowanie danych wyjściowych z polecenia dotnet run i programu Visual Studio.

Debugowanie

Dostawca Debug zapisuje dane wyjściowe dziennika przy użyciu klasy System.Diagnostics.Debug. Wywołania metody System.Diagnostics.Debug.WriteLine zapisują do dostawcy Debug.

W systemie Linux lokalizacja dziennika dostawcy Debug jest zależna od dystrybucji i może być jedną z następujących:

  • /var/log/message
  • /var/log/syslog

Źródło zdarzenia

Dostawca EventSource zapisuje w międzyplatformowym źródle zdarzeń o nazwie Microsoft-Extensions-Logging. W systemie Windows dostawca używa funkcji ETW.

dotnet-trace tooling

Narzędzie dotnet-trace jest międzyplatformowym globalnym narzędziem interfejsu wiersza polecenia, które umożliwia zbieranie śladów platformy .NET Core uruchomionego procesu. Narzędzie to zbiera dane dostawcy Microsoft.Extensions.Logging.EventSource przy użyciu klasy LoggingEventSource.

Aby uzyskać instrukcje instalacji, zobacz dotnet-trace.

Użyj narzędzi dotnet-trace, aby zebrać ślad z aplikacji:

  1. Uruchom aplikację za pomocą polecenia dotnet run.

  2. Określ identyfikator procesu (PID) aplikacji platformy .NET Core:

    dotnet-trace ps
    

    Znajdź identyfikator PID dla procesu, który ma taką samą nazwę, jak zestaw aplikacji.

  3. Wykonaj polecenie dotnet-trace.

    Ogólna składnia polecenia:

    dotnet-trace collect -p {PID} 
        --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"
    

    W przypadku korzystania z powłoki poleceń programu PowerShell należy ująć wartość --providers w apostrofy ('):

    dotnet-trace collect -p {PID} 
        --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"'
    

    W przypadku platform innych niż system Windows dodaj opcję -f speedscope, aby zmienić format wyjściowego pliku śledzenia na speedscope.

    W poniższej tabeli zdefiniowano słowo kluczowe:

    Słowo kluczowe opis
    1 Rejestruje zdarzenia meta dotyczące obiektu LoggingEventSource. Nie rejestruje zdarzeń z ILogger.
    2 Włącza zdarzenie Message po wywołaniu metody ILogger.Log(). Dostarcza informacje w sposób programowy (nie sformatowany).
    100 Włącza zdarzenie FormatMessage po wywołaniu metody ILogger.Log(). Dostarcza sformatowaną wersję ciągu informacji.
    8 Włącza zdarzenie MessageJson po wywołaniu metody ILogger.Log(). Dostarcza reprezentację JSON argumentów.

    W poniższej tabeli wymieniono poziomy dostawcy:

    Poziom dostawcy opis
    0 LogAlways
    1 Critical
    2 Error
    3 Warning
    4 Informational
    5 Verbose

    Analizowanie poziomu kategorii może być ciągiem lub liczbą:

    Nazwana wartość kategorii Wartość liczbowa
    Trace 0
    Debug 1
    Information 2
    Warning 3
    Error 4
    Critical 5

    Poziom dostawcy i poziom kategorii:

    • Są w odwrotnej kolejności.
    • Stałe ciągu nie są identyczne.

    Jeśli nie zostaną określone żadne elementy FilterSpecs, implementacja EventSourceLogger podejmie próbę przekonwertowania poziomu dostawcy na poziom kategorii i zastosuje to do wszystkich kategorii.

    Poziom dostawcy Poziom kategorii
    Verbose(5) Debug(1)
    Informational(4) Information(2)
    Warning(3) Warning(3)
    Error(2) Error(4)
    Critical(1) Critical(5)

    Jeśli FilterSpecs zostaną określone, każda kategoria, która znajduje się na liście, będzie używać zakodowanego tam poziomu kategorii, a wszystkie inne kategorie zostaną odfiltrowane.

    W poniższych przykładach przyjęto następujące założenia:

    • Aplikacja jest uruchomiona i wywołuje metodę logger.LogDebug("12345").
    • Identyfikator procesu (PID) został ustawiony za pośrednictwem polecenia set PID=12345, gdzie 12345 jest rzeczywistym identyfikatorem PID.

    Spójrzmy na następujące polecenie:

    dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
    

    Poprzednie polecenie:

    • Przechwytuje komunikaty debugowania.
    • Nie stosuje elementów FilterSpecs.
    • Określa poziom 5, który mapuje kategorię Debug.

    Spójrzmy na następujące polecenie:

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
    

    Poprzednie polecenie:

    • Nie przechwytuje komunikatów debugowania, ponieważ poziom kategorii 5 ma wartość Critical.
    • Dostarcza elementy FilterSpecs.

    Następujące polecenie przechwytuje komunikaty debugowania, ponieważ poziom kategorii 1 określa element Debug.

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
    

    Następujące polecenie przechwytuje komunikaty debugowania, ponieważ kategoria określa element Debug.

    dotnet-trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
    

    Wpisy FilterSpecs dla {Logger Category} i {Category Level} reprezentują dodatkowe warunki filtrowania dzienników. Oddziel wpisy FilterSpecs znakiem średnika ;.

    Przykład użycia powłoki poleceń systemu Windows:

    dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
    

    Powyższe polecenie aktywuje:

    • Rejestrator źródła zdarzenia w celu utworzenia sformatowanych ciągów (4) dla błędów (2).
    • Rejestrowanie Microsoft.AspNetCore.Hosting na poziomie rejestrowania Informational (4).
  4. Zatrzymaj dotnet-trace narzędzia, naciskając klawisz Enter lub Ctrl+C.

    Ślad jest zapisywany z nazwą trace.nettrace w folderze, w którym jest wykonywane polecenie dotnet-trace.

  5. Otwórz ślad za pomocą narzędzia Perfview. Otwórz plik trace.nettrace i zapoznaj się ze zdarzeniami śledzenia.

Jeśli aplikacja nie skompiluje hosta za pomocą metody WebApplication.CreateBuilder, dodaj dostawcę źródła zdarzeń do konfiguracji rejestrowania aplikacji.

Aby uzyskać więcej informacji, zobacz:

Perfview

Przy użyciu narzędzia PerfView można zbierać i wyświetlać dzienniki. Istnieją inne narzędzia do wyświetlania dzienników ETW, ale narzędzie PerfView zapewnia najlepsze środowisko do pracy ze zdarzeniami ETW emitowanymi przez platformę ASP.NET Core.

Aby skonfigurować narzędzie PerfView do zbierania zdarzeń rejestrowanych przez tego dostawcę, dodaj ciąg *Microsoft-Extensions-Logging do listy Dodatkowi dostawcy. Nie zapomnij o znaku * na początku ciągu.

Windows EventLog

Dostawca EventLog wysyła dane wyjściowe dziennika do dziennika zdarzeń systemu Windows. W przeciwieństwie do innych dostawców dostawca EventLognie dziedziczy domyślnych ustawień innych niż dostawcy. Jeśli ustawienia dziennika EventLog nie są określone, przyjmowana jest wartość domyślna LogLevel.Warning.

Aby rejestrować zdarzenia o poziomie niższym niż LogLevel.Warning należy jawnie ustawić poziom dziennika. W poniższym przykładzie domyślny poziom dziennika dla dziennika zdarzeń jest ustawiony na LogLevel.Information:

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Przeciążenia metody AddEventLog mogą przekazywać klasę EventLogSettings. Jeśli wartość wynosi null lub nie jest określona, używane są następujące ustawienia domyślne:

  • LogName: „Application”
  • SourceName: „.NET Runtime”
  • MachineName: używana jest nazwa komputera lokalnego.

Poniższy kod zmienia wartość parametru SourceName z wartości domyślnej ".NET Runtime" na wartość MyLogs:


var builder = WebApplication.CreateBuilder();
builder.Logging.AddEventLog(eventLogSettings =>
{
    eventLogSettings.SourceName = "MyLogs";
});

Azure App Service

Pakiet dostawcy Microsoft.Extensions.Logging.AzureAppServices zapisuje dzienniki w plikach tekstowych w systemie plików aplikacji usługi Azure App Service i w magazynie obiektów blob na koncie usługi Azure Storage.

Pakiet dostawcy nie jest uwzględniony w strukturze udostępnionej. Aby użyć tego dostawcy, należy dodać pakiet dostawcy do projektu.

Aby skonfigurować ustawienia dostawcy, użyj klas AzureFileLoggerOptions i AzureBlobLoggerOptions, jak pokazano w poniższym przykładzie:

using Microsoft.Extensions.Logging.AzureAppServices;

var builder = WebApplication.CreateBuilder();
builder.Logging.AddAzureWebAppDiagnostics();
builder.Services.Configure<AzureFileLoggerOptions>(options =>
{
    options.FileName = "azure-diagnostics-";
    options.FileSizeLimit = 50 * 1024;
    options.RetainedFileCountLimit = 5;
});
builder.Services.Configure<AzureBlobLoggerOptions>(options =>
{
    options.BlobName = "log.txt";
});

Po wdrożeniu w usłudze Azure App Service aplikacja używa ustawień z sekcji Dzienniki usługi App Service na stronie usługi App Service w witrynie Azure Portal. Po zaktualizowaniu następujących ustawień zmiany są stosowane natychmiast bez konieczności ponownego uruchamiania lub ponownego wdrażania aplikacji.

  • Rejestrowanie aplikacji (system plików)
  • Rejestrowanie aplikacji (blob)

Domyślną lokalizacją plików dziennika jest folder D:\\home\\LogFiles\\Application, a domyślna nazwa pliku to diagnostics-yyyymmdd.txt. Domyślny limit rozmiaru pliku wynosi 10 MB, a domyślna maksymalna liczba zachowywanych plików to 2. Domyślna nazwa obiektu blob to {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt.

Ten dostawca rejestruje tylko wtedy, gdy projekt jest uruchomiony w środowisku platformy Azure.

Przesyłanie strumieniowe dzienników platformy Azure

Przesyłanie strumieniowe dzienników platformy Azure obsługuje wyświetlanie aktywności dziennika w czasie rzeczywistym z:

  • serwera aplikacji
  • serwera internetowego
  • śledzenia żądań zakończonego niepowodzeniem

Aby skonfigurować przesyłanie strumieniowe dzienników platformy Azure:

  • Przejdź do strony Dzienniki usługi App Service na stronie portalu aplikacji.
  • Dla opcji Rejestrowanie aplikacji (system plików) ustaw wartość Włączone.
  • Wybierz poziom dziennika. To ustawienie dotyczy tylko przesyłania strumieniowego dzienników platformy Azure.

Przejdź do strony Strumień dziennika, aby wyświetlić dzienniki. Komunikaty są rejestrowane za pomocą interfejsu ILogger.

Azure Application Insights

Pakiet dostawcy Microsoft.Extensions.Logging.ApplicationInsights zapisuje dzienniki w usłudze Azure Application Insights. Application Insights to usługa, która monitoruje aplikację internetową i udostępnia narzędzia do wykonywania zapytań i analizowania danych telemetrycznych. Jeśli używasz tego dostawcy, możesz wykonywać zapytania i analizować dzienniki przy użyciu narzędzi usługi Application Insights.

Dostawca rejestrowania jest dołączany jako zależność Microsoft.ApplicationInsights.AspNetCore, czyli pakietu, który zapewnia wszystkie dostępne dane telemetryczne dla platformy ASP.NET Core. Jeśli używasz tego pakietu, nie musisz instalować pakietu dostawcy.

Pakiet Microsoft.ApplicationInsights.Web jest przeznaczony dla platformy ASP.NET 4.x, a nie ASP.NET Core.

Aby uzyskać więcej informacji, zobacz następujące zasoby:

Zewnętrzni dostawcy rejestrowania

Struktury rejestrowania innych firm, które współpracują z platformą ASP.NET Core:

Niektóre struktury innych firm mogą wykonywać rejestrowanie semantyczne, znane również jako rejestrowanie strukturalne.

Korzystanie ze struktury innej firmy jest podobne do korzystania z jednego z wbudowanych dostawców:

  1. Dodaj pakiet NuGet do projektu.
  2. Wywołaj metodę rozszerzenia ILoggerFactory dostarczaną przez strukturę rejestrowania.

Aby uzyskać więcej informacji, zapoznaj się z dokumentacją każdego z dostawców. Zewnętrzni dostawcy rejestrowania nie są obsługiwani przez firmę Microsoft.

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 do niego 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. Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące rejestrowania w kolejce komunikatów dla powolnych magazynów danych (dotnet/AspNetCore.Docs #11801).

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 w celu zaktualizowania konfiguracji rejestrowania aplikacji.

ILogger i ILoggerFactory

Interfejsy i implementacje ILogger<TCategoryName> i ILoggerFactory są uwzględnione w zestawie SDK platformy .NET Core. Są one również dostępne w następujących pakietach NuGet:

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:

using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;

var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter("System", LogLevel.Debug);
builder.Logging.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information);
builder.Logging.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace);

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 Information i wyższy.
  • Wszystkie kategorie rozpoczynające się od ciągu "Microsoft".

Automatyczne rejestrowanie zakresu za pomocą SpanId, TraceId, ParentId, Baggage i Tags.

Biblioteki rejestrowania niejawnie tworzą obiekt zakresu z elementami SpanId, TraceId, ParentId, Baggage i Tags. To zachowanie jest konfigurowane za pomocą właściwości ActivityTrackingOptions.

var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddSimpleConsole(options =>
{
    options.IncludeScopes = true;
});

builder.Logging.Configure(options =>
{
    options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
                                       | ActivityTrackingOptions.TraceId
                                       | ActivityTrackingOptions.ParentId
                                       | ActivityTrackingOptions.Baggage
                                       | ActivityTrackingOptions.Tags;
});
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Jeśli nagłówek żądania HTTP traceparent jest ustawiony, ParentId w zakresie dziennika pokazuje parent-id W3C z nagłówka ruchu przychodzącego traceparent, a SpanId w zakresie dziennika pokazuje zaktualizowany parent-id dla następnego kroku/zakresu ruchu wychodzącego. Aby uzyskać więcej informacji, zobacz Mutowanie pola traceparent.

Tworzenie rejestratora niestandardowego

Aby utworzyć niestandardowy rejestrator, zobacz Implementowanie niestandardowego dostawcy rejestrowania na platformie .NET.

Dodatkowe zasoby

Autorzy: Kirk Larkin, Juergen Gutsch i Rick Anderson

W tym temacie opisano rejestrowanie na platformie .NET w odniesieniu do aplikacji ASP.NET Core. Aby uzyskać szczegółowe informacje na temat rejestrowania na platformie .NET, zobacz Rejestrowanie na platformie .NET. Aby uzyskać więcej informacji na temat rejestrowania w aplikacjach Blazor, zobacz Rejestrowanie aplikacji Blazor platformy ASP.NET Core.

Wyświetl lub pobierz przykładowy kod (jak pobrać).

Dostawcy rejestrowania

Dostawcy rejestrowania przechowują dzienniki, z wyjątkiem dostawcy Console, który wyświetla dzienniki. Na przykład dostawca usługi Azure Application Insights przechowuje dzienniki w usłudze Azure Application Insights. Można włączyć wielu dostawców.

Domyślne szablony aplikacji internetowych platformy ASP.NET Core:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Powyższy kod przedstawia klasę Program utworzoną przy użyciu szablonów aplikacji internetowych platformy ASP.NET Core. W kilku następnych sekcjach przedstawiono przykłady oparte na szablonach aplikacji internetowych platformy ASP.NET Core, które korzystają z hosta ogólnego. Aplikacje konsolowe bez hosta zostały omówione w dalszej części tego dokumentu.

Aby zastąpić domyślny zestaw dostawców rejestrowania dodany przez Host.CreateDefaultBuilder, wywołaj polecenie ClearProviders i dodaj wymaganych dostawców rejestrowania. Na przykład następujący kod:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Aby uzyskać informacje o dodatkowych dostawcach, zobacz:

Tworzenie dzienników

Aby utworzyć dzienniki, użyj obiektu ILogger<TCategoryName> z wstrzykiwania zależności (DI).

Poniższy przykład:

  • Tworzy rejestrator, ILogger<AboutModel>, który używa kategorii dziennika w pełni kwalifikowanej nazwy typu AboutModel. 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 AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }
    public string Message { get; set; }

    public void OnGet()
    {
        Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
        _logger.LogInformation(Message);
    }
}

Poziomy i kategorie zostały omówione bardziej szczegółowo w dalszej części tego dokumentu.

Aby uzyskać informacje na temat struktury Blazor, zobacz Rejestrowanie aplikacji Blazor platformy ASP.NET Core.

Tworzenie dzienników w plikach Main i Startup pokazuje, jak utworzyć dzienniki w plikach Main i Startup.

Konfigurowanie rejestrowania

Konfiguracja rejestrowania jest często dostarczana za pomocą sekcji Logging plików appsettings.{Environment}.json. Poniższy plik appsettings.Development.json jest generowany przez szablony aplikacji internetowych platformy ASP.NET Core:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

W powyższym pliku JSON:

  • Określono kategorie "Default", "Microsoft" i "Microsoft.Hosting.Lifetime".
  • Kategoria "Microsoft" dotyczy wszystkich kategorii rozpoczynających się ciągiem "Microsoft". To ustawienie na przykład dotyczy kategorii "Microsoft.AspNetCore.Routing.EndpointMiddleware".
  • Kategoria "Microsoft" dokonuje rejestracji na poziomie dziennika Warning i 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ść LogLevel dotyczy 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 pliku JSON określono poziomy dziennika Information i Warning. 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 pliku JSON kategoria Default jest rejestrowana na poziomie Information i wyższym. 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ż użycie następującego pliku appsettings.json:

{
  "Logging": {
    "LogLevel": { // All providers, LogLevel applies to all the enabled providers.
      "Default": "Error", // Default logging, Error and higher.
      "Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information", // Overrides preceding LogLevel:Default setting.
        "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
      }
    },
    "EventSource": { // EventSource provider
      "LogLevel": {
        "Default": "Warning" // All categories of EventSource provider.
      }
    }
  }
}

Ustawienia w Logging.{providername}.LogLevel zastępują ustawienia w Logging.LogLevel. W powyższym pliku JSON domyślny poziom dziennika dostawcy Debug jest ustawiony na 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 powyższym pliku JSON kategorie "Microsoft.Hosting" i "Default" w sekcji Logging:Debug:LogLevel zastępują ustawienia w sekcji 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

W poniższym pliku appsettings.json wszyscy dostawcy są domyślnie włączeni:

{
  "Logging": {
    "LogLevel": { // No provider, LogLevel applies to all the enabled providers.
      "Default": "Error",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Warning"
    },
    "Debug": { // Debug provider.
      "LogLevel": {
        "Default": "Information" // Overrides preceding LogLevel:Default setting.
      }
    },
    "Console": {
      "IncludeScopes": true,
      "LogLevel": {
        "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
        "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
        "Microsoft.AspNetCore.Mvc.Razor": "Error",
        "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}.LogLevel zastępują ustawienia w Logging.LogLevel. Na przykład poziom w sekcji Debug.LogLevel.Default zastępuje poziom w sekcji LogLevel.Default.
  • Dla każdego dostawcy domyślnego użyto aliasu. Każdy dostawca ma zdefiniowany alias, którego można używać w konfiguracji zamiast w pełni kwalifikowanej nazwy typu. Wbudowane aliasy 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.

Separator : nie współdziała z kluczami hierarchicznymi zmiennych środowiskowych na wszystkich platformach. Symbol __ (podwójne podkreślenie):

  • Jest obsługiwany przez wszystkie platformy. Na przykład separator : nie jest obsługiwany przez powłokę Bash, a separator __ jest.
  • Jest automatycznie zastępowany przez :

Poniższe polecenia:

  • Ustawiają klucz środowiska Logging:LogLevel:Microsoft na wartość Information w systemie Windows.
  • Testują ustawienia w przypadku używania aplikacji utworzonej przy użyciu szablonów aplikacji internetowych platformy ASP.NET Core. Polecenie dotnet run należy uruchomić w katalogu projektu po użyciu polecenia set.
set Logging__LogLevel__Microsoft=Information
dotnet run

Poprzednie ustawienia środowiska:

  • są ustawiane tylko w procesach uruchamianych z poziomu okna poleceń, w którym zostały ustawione;
  • nie są odczytywane przez przeglądarki uruchamiane za pomocą programu Visual Studio.

Poniższe polecenie setx również ustawia klucz środowiska i wartość w systemie Windows. W przeciwieństwie do polecenia set, ustawienia polecenia setx są trwałe. Przełącznik /M ustawia zmienną w środowisku systemowym. Jeśli przełącznik /M nie jest używany, ustawiana jest zmienna środowiskowa użytkownika.

setx Logging__LogLevel__Microsoft Information /M

Rozważ użycie następującego pliku appsettings.json:

"Logging": {
    "Console": {
      "LogLevel": {
        "Microsoft.Hosting.Lifetime": "Trace"
      }
    }
}

Poniższe polecenie ustawia powyższą konfigurację w środowisku:

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

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, zobacz Azure Apps: zastępowanie konfiguracji aplikacji przy użyciu witryny Azure Portal.

Aby uzyskać więcej informacji na temat ustawiania wartości konfiguracji platformy ASP.NET Core przy użyciu zmiennych środowiskowych, zobacz zmienne środowiskowe. Aby uzyskać informacje na temat korzystania z innych źródeł konfiguracji, w tym wiersza polecenia, usługi Azure Key Vault, usługi Azure App Configuration, innych formatów plików i nie tylko, zobacz Konfiguracja na platformie ASP.NET Core.

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 MinimumLevel.

Rejestrowanie danych wyjściowych z polecenia dotnet run i programu Visual Studio

Zostaną wyświetlone dzienniki utworzone przy użyciu domyślnych dostawców rejestrowania:

  • W programie Visual Studio
    • W oknie danych wyjściowych debugowania podczas debugowania.
    • W oknie serwera internetowego platformy ASP.NET Core.
  • W oknie konsoli w przypadku uruchomieniu aplikacji za pomocą polecenia dotnet run.

Dzienniki rozpoczynające się od kategorii „Microsoft” pochodzą z kodu platformy ASP.NET Core. Platforma ASP.NET Core i kod aplikacji używają tego samego interfejsu API rejestrowania i tych samych dostawców.

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 kontrolerze nazwa może mieć postać "TodoApi.Controllers.TodoController". Aplikacje internetowe platformy ASP.NET Core używają ILogger<T>, aby automatycznie pobierać wystąpienie ILogger, które używa w pełni kwalifikowanej nazwy typu T jako kategorii:

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;

    public PrivacyModel(ILogger<PrivacyModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.PrivacyModel called.");
    }
}

Aby jawnie określić kategorię, wywołaj metodę ILoggerFactory.CreateLogger:

public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILoggerFactory logger)
    {
        _logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
    }

    public void OnGet()
    {
        _logger.LogInformation("GET Pages.ContactModel called.");
    }

Wywoływanie metody CreateLogger ze stałą nazwą może być przydatne w przypadku użycia w wielu metodach, 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:

PoziomRejestrowania Wartość Metoda opis
Śledzenie 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.
Debug 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 100 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 kategoria rejestrowania nie powinna 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:

[HttpGet]
public IActionResult Test1(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);

    _logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    return ControllerContext.MyDisplayRouteInfo();
}

MyLogEvents.TestItem to identyfikator zdarzenia. MyLogEvents jest częścią przykładowej aplikacji i jest wyświetlany w sekcji Identyfikator zdarzenia dziennika.

Metody MyDisplayRouteInfo i ToCtxString są dostarczane przez pakiet NuGet Rick.Docs.Samples.RouteInfo. Metody te wyświetlają informacje o trasie Controller i Razor Page.

Poniższy kod tworzy dzienniki Information i Warning:

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

W powyższym kodzie pierwszym parametrem metody Log{LogLevel}, MyLogEvents.GetItem, 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 omówione w sekcji dotyczące szablonu komunikatu w dalszej części tego dokumentu.

Wywołaj odpowiednią metodę Log{LogLevel}, aby kontrolować ilość danych wyjściowych dziennika zapisywanych na określonym nośniku magazynu. Na przykład:

  • W środowisku produkcyjnym:
    • Rejestrowanie na poziomach Trace i Information generuje dużą ilość szczegółowych komunikatów dziennika. Aby kontrolować koszty i nie przekraczać limitów magazynowania danych, rejestruj komunikaty dziennika na poziomie Trace i Information w magazynie danych o dużej pojemności i niskiej cenie. Rozważ ograniczenie dzienników Trace i Information do określonych kategorii.
    • Rejestrowanie na poziomach od Warning do Critical powinno 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.
  • W programowania:
    • Ustaw wartość Warning.
    • Dodaj komunikaty Trace lub Information podczas rozwiązywania problemów. Aby ograniczyć ilość danych wyjściowych, poziom Trace lub Information ustawiaj tylko dla kategorii, które są badane.

Platforma ASP.NET Core zapisuje dzienniki dla zdarzeń struktury. Rozważmy na przykład dane wyjściowe dziennika dla:

  • Aplikacji Razor Pages utworzonej przy użyciu szablonów platformy ASP.NET Core.
  • Dla rejestrowania ustawiono wartość Logging:Console:LogLevel:Microsoft:Information
  • Nawigacja do strony Privacy:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
      Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
      Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 149.3023ms 200 text/html; charset=utf-8

Poniższy plik JSON ustawia Logging:Console:LogLevel:Microsoft:Information:

{
  "Logging": {      // Default, all providers.
    "LogLevel": {
      "Microsoft": "Warning"
    },
    "Console": { // Console provider.
      "LogLevel": {
        "Microsoft": "Information"
      }
    }
  }
}

Identyfikator zdarzenia dziennika

Każdy dziennik może określać identyfikator zdarzenia. Przykładowa aplikacja używa klasy MyLogEvents, aby definiować identyfikatory zdarzeń:

public class MyLogEvents
{
    public const int GenerateItems = 1000;
    public const int ListItems     = 1001;
    public const int GetItem       = 1002;
    public const int InsertItem    = 1003;
    public const int UpdateItem    = 1004;
    public const int DeleteItem    = 1005;

    public const int TestItem      = 3000;

    public const int GetItemNotFound    = 4000;
    public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

Identyfikator zdarzenia kojarzy zestaw zdarzeń. Na przykład wszystkie dzienniki związane z wyświetlaniem listy elementów na stronie mogą mieć wartość 1001.

Dostawca rejestrowania może przechowywać identyfikator zdarzenia w polu identyfikatora, w komunikacie rejestrowania lub wcale. Dostawca debugowania nie pokazuje identyfikatorów zdarzeń. Dostawca konsoli wyświetla identyfikatory zdarzeń w nawiasach kwadratowych po kategorii:

info: TodoApi.Controllers.TodoItemsController[1002]
      Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
      Get(1) 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.

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
        return NotFound();
    }

    return ItemToDTO(todoItem);
}

To, które parametry są używane w celu podania wartości symboli zastępczych w komunikatach dziennika jest określane przez kolejność parametrów, a nie nazwy ich symboli zastępczych. W poniższym kodzie nazwy parametrów w symbolach zastępczych szablonu komunikatu są niezgodne z kolejnością:

var apples = 1;
var pears = 2;
var bananas = 3;

_logger.LogInformation("Parameters: {pears}, {bananas}, {apples}", apples, pears, bananas);

Parametry są jednak przypisywane do symboli zastępczych w kolejności: apples, pears, bananas. Komunikat dziennika odzwierciedla kolejność parametrów:

Parameters: 1, 2, 3

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 na przykład następującą metodę rejestratora:

_logger.LogInformation("Getting item {Id} at {RequestTime}", 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 ID i RequestTime.
  • 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 RequestTime bez konieczności analizowania czasu z komunikatu tekstowego.

Wyjątki dzienników

Metody rejestratora mają przeciążenia, które przyjmują parametr wyjątku:

[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
    var routeInfo = ControllerContext.ToCtxString(id);
    _logger.LogInformation(MyLogEvents.TestItem, routeInfo);

    try
    {
        if (id == 3)
        {
            throw new Exception("Test exception");
        }
    }
    catch (Exception ex)
    {
        _logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
        return NotFound();
    }

    return ControllerContext.MyDisplayRouteInfo();
}

Metody MyDisplayRouteInfo i ToCtxString są dostarczane przez pakiet NuGet Rick.Docs.Samples.RouteInfo. Metody te wyświetlają informacje o trasie Controller i Razor Page.

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ę internetową:

  • Utworzona przy użyciu szablonów aplikacji internetowej platformy ASP.NET.
  • Pliki appsettings.json i appsettings.Development.json zostały usunięte lub zmienione.

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:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Ogólnie rzecz biorąc, poziomy dziennika powinny być określane w konfiguracji, a nie w kodzie.

Funkcja filtru

Funkcja filtru jest wywoływana dla wszystkich dostawców i kategorii, dla których nie przypisano reguł za pomocą konfiguracji lub kodu:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddFilter((provider, category, logLevel) =>
                {
                    if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Controller")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else if (provider.Contains("ConsoleLoggerProvider")
                        && category.Contains("Microsoft")
                        && logLevel >= LogLevel.Information)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Powyższy kod wyświetla dzienniki konsoli, gdy kategoria zawiera parametr Controller lub Microsoft, a poziom dziennika ma wartość Information lub wyższą.

Ogólnie rzecz biorąc, poziomy dziennika powinny być określane w konfiguracji, a nie w kodzie.

ASP.NET Core i EF Core kategorie

Poniższa tabela zawiera niektóre kategorie używane przez platformy ASP.NET Core i Entity Framework Core wraz z uwagami dotyczącymi dzienników:

Kategoria Uwagi
Microsoft.AspNetCore Ogólna diagnostyka platformy ASP.NET Core.
Microsoft.AspNetCore.DataProtection Które klucze były rozważane, znalezione i użyte.
Microsoft.AspNetCore.HostFiltering Dozwolone hosty.
Microsoft.AspNetCore.Hosting Jak długo trwało wykonywanie żądań HTTP oraz czas ich rozpoczęcia. Które zestawy startowe hostingu zostały załadowane.
Microsoft.AspNetCore.Mvc Diagnostyka MVC i Razor. Powiązanie modelu, wykonywanie filtru, kompilacja widoku, wybór akcji.
Microsoft.AspNetCore.Routing Kierowanie zgodnych informacji.
Microsoft.AspNetCore.Server Odpowiedzi dotyczące uruchomienia i zatrzymania połączenia oraz utrzymania aktywności. Informacje o certyfikacie HTTPS.
Microsoft.AspNetCore.StaticFiles Obsłużone pliki.
Microsoft.EntityFrameworkCore Ogólna diagnostyka platformy Entity Framework Core. Aktywność i konfiguracja bazy danych, wykrywanie zmian, migracje.

Aby wyświetlić więcej kategorii w oknie konsoli, w pliku appsettings.Development.json wprowadź następujące ustawienia:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Trace",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

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:

Następujący dostawcy obsługują zakresy:

Użyj zakresu, opakowując wywołania rejestratora za pomocą bloku using:

[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
    TodoItem todoItem;
    var transactionId = Guid.NewGuid().ToString();
    using (_logger.BeginScope(new List<KeyValuePair<string, object>>
        {
            new KeyValuePair<string, object>("TransactionId", transactionId),
        }))
    {
        _logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);

        todoItem = await _context.TodoItems.FindAsync(id);

        if (todoItem == null)
        {
            _logger.LogWarning(MyLogEvents.GetItemNotFound, 
                "Get({Id}) NOT FOUND", id);
            return NotFound();
        }
    }

    return ItemToDTO(todoItem);
}

Wbudowani dostawcy rejestrowania

Platforma ASP.NET Core obejmuje następujących dostawców rejestrowania w ramach struktury udostępnionej:

Następujący dostawcy rejestrowania są dostarczani przez firmę Microsoft, ale nie w ramach struktury udostępnionej. Należy ich zainstalować jako dodatkowe pakiety nuget.

Platforma ASP.NET Core nie zawiera dostawcy rejestrowania na potrzeby zapisywania dzienników w plikach. Aby zapisywać dzienniki w plikach z aplikacji platformy ASP.NET Core, rozważ użycie dostawcy rejestrowania innej firmy.

Aby uzyskać informacje na temat właściwości stdout i rejestrowania debugowania przy użyciu modułu ASP.NET Core Module, zobacz Rozwiązywanie problemów z platformą ASP.NET Core w usługach Azure App Service oraz IIS, a także Moduł ASP.NET Core Module (ANCM) dla usług IIS.

Konsola

Dostawca Console rejestruje dane wyjściowe w konsoli. Aby uzyskać więcej informacji na temat wyświetlania dzienników dostawcy Console w środowisku programistycznym, zobacz Rejestrowanie danych wyjściowych z polecenia dotnet run i programu Visual Studio.

Debugowanie

Dostawca Debug zapisuje dane wyjściowe dziennika przy użyciu klasy System.Diagnostics.Debug. Wywołania metody System.Diagnostics.Debug.WriteLine zapisują do dostawcy Debug.

W systemie Linux lokalizacja dziennika dostawcy Debug jest zależna od dystrybucji i może być jedną z następujących:

  • /var/log/message
  • /var/log/syslog

Źródło zdarzenia

Dostawca EventSource zapisuje w międzyplatformowym źródle zdarzeń o nazwie Microsoft-Extensions-Logging. W systemie Windows dostawca używa funkcji ETW.

Narzędzia dotnet trace

Narzędzie dotnet-trace jest międzyplatformowym globalnym narzędziem interfejsu wiersza polecenia, które umożliwia zbieranie śladów platformy .NET Core uruchomionego procesu. Narzędzie to zbiera dane dostawcy Microsoft.Extensions.Logging.EventSource przy użyciu klasy LoggingEventSource.

Aby uzyskać instrukcje instalacji, zobacz dotnet-trace.

Użyj narzędzi dotnet trace, aby zebrać ślad z aplikacji:

  1. Uruchom aplikację za pomocą polecenia dotnet run.

  2. Określ identyfikator procesu (PID) aplikacji platformy .NET Core:

    dotnet trace ps
    

    Znajdź identyfikator PID dla procesu, który ma taką samą nazwę, jak zestaw aplikacji.

  3. Wykonaj polecenie dotnet trace.

    Ogólna składnia polecenia:

    dotnet trace collect -p {PID} 
        --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"
    

    W przypadku korzystania z powłoki poleceń programu PowerShell należy ująć wartość --providers w apostrofy ('):

    dotnet trace collect -p {PID} 
        --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level}
            :FilterSpecs=\"
                {Logger Category 1}:{Category Level 1};
                {Logger Category 2}:{Category Level 2};
                ...
                {Logger Category N}:{Category Level N}\"'
    

    W przypadku platform innych niż system Windows dodaj opcję -f speedscope, aby zmienić format wyjściowego pliku śledzenia na speedscope.

    W poniższej tabeli zdefiniowano słowo kluczowe:

    Słowo kluczowe opis
    1 Rejestruje zdarzenia meta dotyczące obiektu LoggingEventSource. Nie rejestruje zdarzeń z ILogger.
    2 Włącza zdarzenie Message po wywołaniu metody ILogger.Log(). Dostarcza informacje w sposób programowy (nie sformatowany).
    100 Włącza zdarzenie FormatMessage po wywołaniu metody ILogger.Log(). Dostarcza sformatowaną wersję ciągu informacji.
    8 Włącza zdarzenie MessageJson po wywołaniu metody ILogger.Log(). Dostarcza reprezentację JSON argumentów.

    W poniższej tabeli wymieniono poziomy dostawcy:

    Poziom dostawcy opis
    0 LogAlways
    1 Critical
    2 Error
    3 Warning
    4 Informational
    5 Verbose

    Analizowanie poziomu kategorii może być ciągiem lub liczbą:

    Nazwana wartość kategorii Wartość liczbowa
    Trace 0
    Debug 1
    Information 2
    Warning 3
    Error 4
    Critical 5

    Poziom dostawcy i poziom kategorii:

    • Są w odwrotnej kolejności.
    • Stałe ciągu nie są identyczne.

    Jeśli nie zostaną określone żadne elementy FilterSpecs, implementacja EventSourceLogger podejmie próbę przekonwertowania poziomu dostawcy na poziom kategorii i zastosuje to do wszystkich kategorii.

    Poziom dostawcy Poziom kategorii
    Verbose(5) Debug(1)
    Informational(4) Information(2)
    Warning(3) Warning(3)
    Error(2) Error(4)
    Critical(1) Critical(5)

    Jeśli FilterSpecs zostaną określone, każda kategoria, która znajduje się na liście, będzie używać zakodowanego tam poziomu kategorii, a wszystkie inne kategorie zostaną odfiltrowane.

    W poniższych przykładach przyjęto następujące założenia:

    • Aplikacja jest uruchomiona i wywołuje metodę logger.LogDebug("12345").
    • Identyfikator procesu (PID) został ustawiony za pośrednictwem polecenia set PID=12345, gdzie 12345 jest rzeczywistym identyfikatorem PID.

    Spójrzmy na następujące polecenie:

    dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
    

    Poprzednie polecenie:

    • Przechwytuje komunikaty debugowania.
    • Nie stosuje elementów FilterSpecs.
    • Określa poziom 5, który mapuje kategorię Debug.

    Spójrzmy na następujące polecenie:

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
    

    Poprzednie polecenie:

    • Nie przechwytuje komunikatów debugowania, ponieważ poziom kategorii 5 ma wartość Critical.
    • Dostarcza elementy FilterSpecs.

    Następujące polecenie przechwytuje komunikaty debugowania, ponieważ poziom kategorii 1 określa element Debug.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
    

    Następujące polecenie przechwytuje komunikaty debugowania, ponieważ kategoria określa element Debug.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
    

    Wpisy FilterSpecs dla {Logger Category} i {Category Level} reprezentują dodatkowe warunki filtrowania dzienników. Oddziel wpisy FilterSpecs znakiem średnika ;.

    Przykład użycia powłoki poleceń systemu Windows:

    dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
    

    Powyższe polecenie aktywuje:

    • Rejestrator źródła zdarzenia w celu utworzenia sformatowanych ciągów (4) dla błędów (2).
    • Rejestrowanie Microsoft.AspNetCore.Hosting na poziomie rejestrowania Informational (4).
  4. Zatrzymaj narzędzie dotnet trace, naciskając klawisz Enter lub klawisze Ctrl+C.

    Ślad jest zapisywany z nazwą trace.nettrace w folderze, w którym jest wykonywane polecenie dotnet trace.

  5. Otwórz ślad za pomocą narzędzia Perfview. Otwórz plik trace.nettrace i zbadaj zdarzenia śledzenia.

Jeśli aplikacja nie skompiluje hosta za pomocą metody CreateDefaultBuilder, dodaj dostawcę źródła zdarzeń do konfiguracji rejestrowania aplikacji.

Aby uzyskać więcej informacji, zobacz:

Perfview

Przy użyciu narzędzia PerfView można zbierać i wyświetlać dzienniki. Istnieją inne narzędzia do wyświetlania dzienników ETW, ale narzędzie PerfView zapewnia najlepsze środowisko do pracy ze zdarzeniami ETW emitowanymi przez platformę ASP.NET Core.

Aby skonfigurować narzędzie PerfView do zbierania zdarzeń rejestrowanych przez tego dostawcę, dodaj ciąg *Microsoft-Extensions-Logging do listy Dodatkowi dostawcy. Nie zapomnij o znaku * na początku ciągu.

Windows EventLog

Dostawca EventLog wysyła dane wyjściowe dziennika do dziennika zdarzeń systemu Windows. W przeciwieństwie do innych dostawców dostawca EventLognie dziedziczy domyślnych ustawień innych niż dostawcy. Jeśli ustawienia dziennika EventLog nie są określone, przyjmowana jest wartość domyślna LogLevel.Warning.

Aby rejestrować zdarzenia o poziomie niższym niż LogLevel.Warning należy jawnie ustawić poziom dziennika. W poniższym przykładzie domyślny poziom dziennika dla dziennika zdarzeń jest ustawiony na LogLevel.Information:

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Przeciążenia AddEventLog mogą przekazywać element EventLogSettings. Jeśli wartość wynosi null lub nie jest określona, używane są następujące ustawienia domyślne:

  • LogName: „Application”
  • SourceName: „.NET Runtime”
  • MachineName: używana jest nazwa komputera lokalnego.

Poniższy kod zmienia wartość parametru SourceName z wartości domyślnej ".NET Runtime" na wartość MyLogs:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
            {
                logging.AddEventLog(eventLogSettings =>
                {
                    eventLogSettings.SourceName = "MyLogs"; 
                });
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Azure App Service

Pakiet dostawcy Microsoft.Extensions.Logging.AzureAppServices zapisuje dzienniki w plikach tekstowych w systemie plików aplikacji usługi Azure App Service i w magazynie obiektów blob na koncie usługi Azure Storage.

Pakiet dostawcy nie jest uwzględniony w strukturze udostępnionej. Aby użyć tego dostawcy, należy dodać pakiet dostawcy do projektu.

Aby skonfigurować ustawienia dostawcy, użyj klas AzureFileLoggerOptions i AzureBlobLoggerOptions, jak pokazano w poniższym przykładzie:

public class Scopes
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
                .ConfigureServices(serviceCollection => serviceCollection
                    .Configure<AzureFileLoggerOptions>(options =>
                    {
                        options.FileName = "azure-diagnostics-";
                        options.FileSizeLimit = 50 * 1024;
                        options.RetainedFileCountLimit = 5;
                    })
                    .Configure<AzureBlobLoggerOptions>(options =>
                    {
                        options.BlobName = "log.txt";
                    }))
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

Po wdrożeniu w usłudze Azure App Service aplikacja używa ustawień z sekcji Dzienniki usługi App Service na stronie usługi App Service w witrynie Azure Portal. Po zaktualizowaniu następujących ustawień zmiany są stosowane natychmiast bez konieczności ponownego uruchamiania lub ponownego wdrażania aplikacji.

  • Rejestrowanie aplikacji (system plików)
  • Rejestrowanie aplikacji (blob)

Domyślną lokalizacją plików dziennika jest folder D:\home\LogFiles\Application, a domyślna nazwa pliku to diagnostics-yyyymmdd.txt. Domyślny limit rozmiaru pliku wynosi 10 MB, a domyślna maksymalna liczba zachowywanych plików to 2. Domyślna nazwa obiektu blob to {app-name}{timestamp}/rrrr/mm/dd/hh/{guid}-applicationLog.txt.

Ten dostawca rejestruje tylko wtedy, gdy projekt jest uruchomiony w środowisku platformy Azure.

Przesyłanie strumieniowe dzienników platformy Azure

Przesyłanie strumieniowe dzienników platformy Azure obsługuje wyświetlanie aktywności dziennika w czasie rzeczywistym z:

  • serwera aplikacji
  • serwera internetowego
  • śledzenia żądań zakończonego niepowodzeniem

Aby skonfigurować przesyłanie strumieniowe dzienników platformy Azure:

  • Przejdź do strony Dzienniki usługi App Service na stronie portalu aplikacji.
  • Dla opcji Rejestrowanie aplikacji (system plików) ustaw wartość Włączone.
  • Wybierz poziom dziennika. To ustawienie dotyczy tylko przesyłania strumieniowego dzienników platformy Azure.

Przejdź do strony Strumień dziennika, aby wyświetlić dzienniki. Komunikaty są rejestrowane za pomocą interfejsu ILogger.

Azure Application Insights

Pakiet dostawcy Microsoft.Extensions.Logging.ApplicationInsights zapisuje dzienniki w usłudze Azure Application Insights. Application Insights to usługa, która monitoruje aplikację internetową i udostępnia narzędzia do wykonywania zapytań i analizowania danych telemetrycznych. Jeśli używasz tego dostawcy, możesz wykonywać zapytania i analizować dzienniki przy użyciu narzędzi usługi Application Insights.

Dostawca rejestrowania jest dołączany jako zależność Microsoft.ApplicationInsights.AspNetCore, czyli pakietu, który zapewnia wszystkie dostępne dane telemetryczne dla platformy ASP.NET Core. Jeśli używasz tego pakietu, nie musisz instalować pakietu dostawcy.

Pakiet Microsoft.ApplicationInsights.Web jest przeznaczony dla platformy ASP.NET 4.x, a nie ASP.NET Core.

Aby uzyskać więcej informacji, zobacz następujące zasoby:

Zewnętrzni dostawcy rejestrowania

Struktury rejestrowania innych firm, które współpracują z platformą ASP.NET Core:

Niektóre struktury innych firm mogą wykonywać rejestrowanie semantyczne, znane również jako rejestrowanie strukturalne.

Korzystanie ze struktury innej firmy jest podobne do korzystania z jednego z wbudowanych dostawców:

  1. Dodaj pakiet NuGet do projektu.
  2. Wywołaj metodę rozszerzenia ILoggerFactory dostarczaną przez strukturę rejestrowania.

Aby uzyskać więcej informacji, zapoznaj się z dokumentacją każdego z dostawców. Zewnętrzni dostawcy rejestrowania nie są obsługiwani przez firmę Microsoft.

Aplikacja konsolowa bez hosta

Aby zapoznać się z przykładem użycia hosta ogólnego w aplikacji konsolowej innej niż internetowa, zobacz plik Program.csprzykładowej aplikacji zadań w tle (Zadania w tle z usługami hostowanymi na platformie ASP.NET Core).

Kod rejestrowania dla aplikacji bez hosta ogólnego różni się sposobem dodawania dostawców i tworzenia rejestratorów.

Dostawcy rejestrowania

W aplikacji konsolowej bez hosta wywołaj metodę rozszerzenia Add{provider name} dostawcy podczas tworzenia elementu LoggerFactory:

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

Tworzenie dzienników

Aby utworzyć dzienniki, użyj obiektu ILogger<TCategoryName>. Użyj elementu LoggerFactory, aby utworzyć element ILogger.

Poniższy przykład tworzy rejestrator z LoggingConsoleApp.Program jako kategorią.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

W poniższym przykładzie rejestrator jest używany do tworzenia dzienników z poziomem Information. Poziom dziennika wskazuje ważność zarejestrowanego zdarzenia.

class Program
{
    static void Main(string[] args)
    {
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder
                .AddFilter("Microsoft", LogLevel.Warning)
                .AddFilter("System", LogLevel.Warning)
                .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddConsole()
                .AddEventLog();
        });
        ILogger logger = loggerFactory.CreateLogger<Program>();
        logger.LogInformation("Example log message");
    }
}

Poziomy i kategorie zostały omówione bardziej szczegółowo w tym dokumencie.

Rejestrowanie podczas konstrukcji hosta

Rejestrowanie podczas konstrukcji hosta nie jest obsługiwane bezpośrednio. Można jednak użyć oddzielnego rejestratora. W poniższym przykładzie rejestrator Serilog jest używany do rejestrowania w CreateHostBuilder. AddSerilog używa konfiguracji statycznej określonej w Log.Logger:

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var builtConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddCommandLine(args)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.File(builtConfig["Logging:FilePath"])
            .CreateLogger();

        try
        {
            return Host.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    services.AddRazorPages();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddConfiguration(builtConfig);
                })
                .ConfigureLogging(logging =>
                {   
                    logging.AddSerilog();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host builder error");

            throw;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

Konfigurowanie usługi, która zależy od rejestratora ILogger

Wstrzykiwanie konstruktora rejestratora do Startup działa we wcześniejszych wersjach platformy ASP.NET Core, ponieważ dla hosta internetowego jest tworzony oddzielny kontener DI. Aby dowiedzieć się, dlaczego dla hosta ogólnego tworzony jest tylko jeden kontener, zobacz ogłoszenie o zmianie powodującej niezgodność.

Aby skonfigurować usługę zależną od ILogger<T>, użyj wstrzykiwania konstruktora lub podaj metodę tworzącą. Metoda tworząca jest zalecana tylko wtedy, gdy nie ma innej opcji. Rozważmy na przykład usługę, która wymaga wystąpienia ILogger<T> dostarczanego przez DI:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddRazorPages();

    services.AddSingleton<IMyService>((container) =>
    {
        var logger = container.GetRequiredService<ILogger<MyService>>();
        return new MyService() { Logger = logger };
    });
}

Powyższy wyróżniony kod to funkcja Func<T,TResult>, która jest uruchamiana po raz pierwszy, gdy kontener DI musi skonstruować wystąpienie MyService. W ten sposób możesz uzyskać dostęp do dowolnych zarejestrowanych usług.

Tworzenie dzienników w pliku Main

Poniższy kod rejestruje w pliku Main, uzyskując wystąpienie ILogger z DI po utworzeniu hosta:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var logger = host.Services.GetRequiredService<ILogger<Program>>();
    logger.LogInformation("Host created.");

    host.Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Tworzenie dzienników w pliku Startup

Poniższy kod zapisuje dzienniki w pliku Startup.Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
                      ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        logger.LogInformation("In Development.");
        app.UseDeveloperExceptionPage();
    }
    else
    {
        logger.LogInformation("Not Development.");
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapRazorPages();
    });
}

Zapisywanie dzienników przed ukończeniem konfiguracji kontenera DI w metodzie Startup.ConfigureServices nie jest obsługiwane:

  • Wstrzykiwanie rejestratora do konstruktora Startup nie jest obsługiwane.
  • Wstrzykiwanie rejestratora do podpisu metody Startup.ConfigureServices nie jest obsługiwane

Przyczyną tego ograniczenia jest to, że rejestrowanie zależy od DI i konfiguracji, która z kolei zależy od DI. Kontener DI nie jest skonfigurowany dopóki funkcja ConfigureServices nie ukończy działania.

Aby uzyskać informacje na temat konfigurowania usługi, która zależy od obiektu ILogger<T>, lub aby dowiedzieć się, dlaczego wstrzykiwanie konstruktora rejestratora do Startup działało we wcześniejszych wersjach, zobacz Konfigurowanie usługi, która zależy od obiektu ILogger

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 do niego 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. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.

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 w celu zaktualizowania konfiguracji rejestrowania aplikacji.

ILogger i ILoggerFactory

Interfejsy i implementacje ILogger<TCategoryName> i ILoggerFactory są uwzględnione w zestawie SDK platformy .NET Core. Są one również dostępne w następujących pakietach NuGet:

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:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(logging =>
               logging.AddFilter("System", LogLevel.Debug)
                  .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
                  .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

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 Information i wyższy.
  • Wszystkie kategorie rozpoczynające się od ciągu "Microsoft".

Automatyczne rejestrowanie zakresu za pomocą właściwości SpanId, TraceId i ParentId

Biblioteki rejestrowania niejawnie tworzą obiekt zakresu za pomocą właściwości SpanId, TraceId i ParentId. To zachowanie jest konfigurowane za pomocą właściwości ActivityTrackingOptions.

  var loggerFactory = LoggerFactory.Create(logging =>
  {
      logging.Configure(options =>
      {
          options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
                                              | ActivityTrackingOptions.TraceId
                                              | ActivityTrackingOptions.ParentId;
      }).AddSimpleConsole(options =>
      {
          options.IncludeScopes = true;
      });
  });

Jeśli nagłówek żądania HTTP traceparent jest ustawiony, ParentId w zakresie dziennika pokazuje parent-id W3C z nagłówka ruchu przychodzącego traceparent, a SpanId w zakresie dziennika pokazuje zaktualizowany parent-id dla następnego kroku/zakresu ruchu wychodzącego. Aby uzyskać więcej informacji, zobacz Mutowanie pola traceparent.

Tworzenie rejestratora niestandardowego

Aby utworzyć niestandardowy rejestrator, zobacz Implementowanie niestandardowego dostawcy rejestrowania na platformie .NET.

Dodatkowe zasoby