Logowanie za pomocą NLoga

Data utworzenia strony :

Środowiska

Visual Studio
  • Visual Studio 2019
Rdzeń ASP.NET
  • 5.0 (MVC, strona Razor)

Na początku

NLog umożliwia wyprowadzanie dzienników do plików, wiadomości e-mail i baz danych w zależności od ustawień.

NLog ASP.NET być włączone do standardowego systemu rejestrowania core. Istnieje możliwość wyprowadzania dzienników zgodnie z ustawieniami podczas korzystania z domyślnego rejestratora.

Poziomy dziennika — informacje

Dzienniki firmy Microsoft i NLogs są podzielone na sześć etapów, a poziomy wyjściowe są mniej więcej takie same:

Poziom MicrosoftNLog
0 Śledzenia Śledzenia
1 Debugowania Debugowania
2 Informacji Informacji
3 Ostrzeżenie Ostrzec
4 Błąd Błąd
5 Krytyczne Śmiertelne
(6) (Brak) (Wył.)

Im wyższy poziom, tym ważniejszy jest dziennik i tym większe prawdopodobieństwo, że zostanie zapisany niezależnie od ograniczeń danych wyjściowych dziennika.

Instrukcje rejestrowania

Wdrażanie pakietu NLog

ASP.NET utworzeniu projektu Core dodaj pakiet.

Kliknij prawym przyciskiem myszy zależności dla projektu i wybierz pozycję Zarządzaj pakietami NuGet.

Kliknij kartę Przeglądaj i wpisz NLog w polu wyszukiwania, aby wyświetlić pakiety związane z NLog.

Wybierz NLog, a następnie kliknij przycisk zainstaluj z najnowszą wersją stabilną.

Kliknij przycisk OK.

Zainstaluj również NLog.Web.AspNetCore.

Pakiet został dodany do projektu.

Dodaj plik nlog.config

Dodaj nlog.config, definicję danych wyjściowych dziennika NLog, do projektu. Zawartość jest w formacie XML, więc utworzyłem go jako plik XML. Nazwa pliku powinna być nlog.config (małe litery).

Utwórz plik w następujący sposób: Szczegółowe ustawienia zostaną omówione później.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

  <!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
  <variable name="layoutDefine"
            value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

  <!-- 書き込むターゲット -->
  <targets>
    <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
    <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

    <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
    <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

    <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
    <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
  </targets>

  <!-- ロガー名からターゲットにマップするルール -->
  <rules>
    <!-- Microsoft からのものを含むすべてのログ -->
    <logger name="*" writeTo="TraceOutput" />

    <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
    <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

    <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
    <logger name="Microsoft.*" maxlevel="Info" final="true" />
    <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

    <!-- 上記で除外したもの以外をファイルに出力 -->
    <logger name="*" writeTo="FileOutput" />
  </rules>
</nlog>

Upewnij się, że właściwości pliku nlog.config są ustawione na Akcja kompilacji: zawartość, Kopiuj do katalogu wyjściowego: Kopiuj, jeśli nowy.

Edytuj plik appsetting.json

Domyślnie, bez względu na to, jak ustawić nlog.config, Information tylko te poziomy są dane wyjściowe. Dzieje się tak, ponieważ rejestrowanie opiera się również na appsetting.json.

Otwórz plik appsetting.json Logging.LogLevel.Default i zmień wartość na Trace . Jeśli używasz NLog, można dostosować poziom po stronie NLog, dzięki czemu można wyprowadzić praktycznie wszystkie Trace poziomy, ustawiając appsetting.json.

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

Ponadto, podczas tworzenia, appsettings. Ustawienia development.json są ładowane, więc zmieniamy je również.

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

Przygotowywanie programów dla NLog

Dodaj program, aby można było zalogować się do mechanizmu NLog.

Otwórz .cs plik programu i napraw go w następujący sposób:

using NLog.Web;  // 追加

// 省略

public class Program
{
  public static void Main(string[] args)
  {
    var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    try
    {
      CreateHostBuilder(args).Build().Run();
    }
    catch (Exception exception)
    {
      // NLog:セットアップエラーをキャッチ
      logger.Error(exception, "例外のためにプログラムを停止しました。");
      throw;
    }
    finally
    {
      // アプリケーションを終了する前に、内部タイマー/スレッドをフラッシュして停止するようにしてください
      // (Linux でのセグメンテーション違反を回避してください)
      NLog.LogManager.Shutdown();
    }
  }

  public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      {
        webBuilder.UseStartup<Startup>();
      })
      .ConfigureLogging(logging =>
      {
        logging.ClearProviders();                 // NLog 以外で設定された Provider の無効化.
        logging.SetMinimumLevel(LogLevel.Trace);  // 最小ログレベルの設定
      })
      .UseNLog();  // NLog:依存性注入のための NLog のセットアップ
}

Rejestrowania

W przypadku projektów MVC HomeComtroller dla stron Razor IndexModel zostałbyś przekazany ILogger<IndexModel> logger konstruktorowi. Jest również ustawiona _logger w polu prywatnym, dzięki czemu można go używać do rejestrowania.

Poniżej przedstawiono przykład danych wyjściowych ze strony Razor, ale MVC można wyprowadzić z tym samym kodem.

// 省略

public class IndexModel : PageModel
{
  private readonly ILogger<IndexModel> _logger;
  
  public IndexModel(ILogger<IndexModel> logger)
  {
    _logger = logger;
    
    _logger.LogTrace("Trace で出力します。");
    _logger.LogDebug("Debug で出力します。");
    _logger.LogInformation("Information で出力します。");
    _logger.LogWarning("Warning で出力します。");
    _logger.LogError("Error で出力します。");
    _logger.LogCritical("Critical で出力します。");
    
    _logger.LogInformation(1, "EventID ありで出力します。");
  }
  
  public void OnGet()
  {
    _logger.LogInformation("ページを表示するタイミングでログを出力します。");
  }
}

Podczas debugowania, myślę, że plik dziennika mogą być wykonane w folderze projektu.

Dziennik można sprawdzić, patrząc na zawartość pliku.

Przykładowy komentarz nlog.config

Wyjaśniam to w porządku, ale nie wyjaśniam mniej ważnych części.

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      throwConfigExceptions="true"
      internalLogFile="${basedir}/internal-nlog-AspNetCore.txt">

Istnieją parametry, takie jak ustawienia wyjścia dziennika dla samego NLog.

internalLogFile będzie miejscem docelowym dziennika. Może to być pomocne, na przykład, jeśli występuje błąd w danych wyjściowych samego dziennika. ${basedir} odnosi się do folderu wykonywania programu.

internalLogLevel jest poziomem wyjściowym dziennika NLog. Off jeśli tak, to w ogóle nie będzie wyprowadzany.

<!-- ログの出力レイアウトを変数 layoutDefine で定義 -->
<variable name="layoutDefine"
          value="${longdate} [${event-properties:item=EventId_Id:whenEmpty=0}][${level:padding=-5}] ${message} ${exception:format=tostring} (${callsite:includeNamespace=false:fileName=true:includeSourcePath=false})" />

Zmienna jest ustawiona na jaki układ zawartość dziennika będzie wyprowadzana. Można wpisać bezpośrednio do późniejszych obiektów docelowych, ale jeśli określisz wiele tego samego układu, łatwiej jest zarządzać nimi w jednej zmiennej.

Lepiej jest odwołać się do oficjalnej strony internetowej, aby zobaczyć, jakie parametry można określić w układzie.

Dla odwołania parametry określone w tym miejscu są dane wyjściowe w następującym formacie:

Zawartość wyjściowa parametru
długa Minuty daty i godziny, takie jak "2021-03-17 11:46:36.5034"
właściwości zdarzenia Wyświetla identyfikator zdarzenia itp danych wyjściowych dziennika określonych przez program
Poziom Poziomy takie jak Śledzenie i Błąd
Komunikat Komunikat określony w rejestrowaniu programu
Wyjątek Co zrobić, jeśli przejdziesz wyjątek podczas rejestrowania programów
callsite (wymagalit) Lokalizacja rejestrowania, nazwa pliku itp.

Przykład wyjścia

2021-03-17 11:46:37.3537 [0][Info ] ページを表示するタイミングでログを出力します。  (IndexModel.OnGet(Index.cshtml.cs:26))
<!-- 書き込むターゲット -->
<targets>
  <!-- Visual Studio の出力 (デバッグ) に書き込みます -->
  <target xsi:type="Trace" name="TraceOutput" rawWrite="true" layout="${layoutDefine}" />

  <!-- 基本的な詳細を含むすべてのログメッセージのファイルターゲット -->
  <target xsi:type="File" name="FileOutput" fileName="${aspnet-appbasepath}/Log-${shortdate}.log" layout="${layoutDefine}" />

  <!-- Docker / Visual Studio の起動検出を改善するためにライフタイムメッセージをホストするためのコンソールターゲット  -->
  <target xsi:type="Console" name="LifetimeConsole" layout="${level:truncate=4}\: ${logger}[0]${newline}      ${message}${exception:format=tostring}" />
</targets>

Określa obiekt docelowy do wysuń. Można określić wiele.

Pierwszy xsi:type="Trace" określa , a dziennik jest drukowany w oknie danych wyjściowych programu Visual Studio. Może służyć głównie do debugowania wykonywania.

Drugi xsi:type="File" określa i rejestruje plik w określonej ścieżce. Jeśli ${shortdate} określisz w ścieżce, można zapisać dziennik do pliku daty dziennika w czasie dziennika. Określa również ${aspnet-appbasepath} folder główny projektu sieci Web. Jednak podczas pracy lepiej jest wyprowadzić pliki dziennika poza katalogiem sieci Web w celu zastąpienia i zabezpieczenia programu.

Trzeci jest xsi:type="Console" określony i może być wyświetlany w konsoli w aplikacji konsoli. ASP.NET Core sam nie jest aplikacją konsoli, ale może być również używany w środowiskach, takich jak Platformy Docker i Azure, ponieważ stan może być wyświetlany w konsoli. Jest to opis na oficjalnej stronie NLog.

<!-- ロガー名からターゲットにマップするルール -->
<rules>
  <!-- Microsoft からのものを含むすべてのログ -->
  <logger name="*" writeTo="TraceOutput" />

  <!-- 起動の検出を高速化するために、ホスティングライフタイムメッセージをコンソールターゲットに出力します。Microsoft.Hosting.Lifetime はここより下の定義には出力しません -->
  <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="LifetimeConsole" final="true" />

  <!-- 重要でない Microsoft ログをスキップして、自分のログのみをログに記録する。システムが出す Warning 以上のログ以外はここより下の定義には出力されません -->
  <logger name="Microsoft.*" maxlevel="Info" final="true" />
  <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

  <!-- 上記で除外したもの以外をファイルに出力 -->
  <logger name="*" writeTo="FileOutput" />
</rules>

W tym miejscu można określić, jaki poziom i jaki typ dzienników do danych wyjściowych do gdzie. Ten opis jest stosowany od góry do góry.

Pierwszym z nich jest name="*" wyjście wszystkich dzienników do obiektu docelowego, ponieważ poziom jest writeTo określony podczas określania . Jest to target określone w programie , więc pojawia się w danych TraceOutput wyjściowych programu Visual Studio.

Drugi jest Microsoft.Hosting.Lifetime dane wyjściowe do danych wyjściowych dziennika w writeTo (コンソール) bibliotece. Skojarzenia ConsoleLifetime można zaewidencjonować w konsolach, takich jak Azure i Docker. minlevel="Info" ponieważ Trace Debug określa , i nie jest rejestrowany. Ponadto kolejne definicje nie final="true" Microsoft.Hosting.Lifetime wyprowadzają powiązanych dzienników.

Trzecim name="Microsoft.*" jest name="System.Net.Http.*" zatrzymanie rejestrowania final="true" przez określenie for i dzienników. name *jest symbolem wieloznacznym, co Microsoft System.Net.Http oznacza, że odnosi się do wszystkich powiązanych bibliotek. , ale zatrzymaj się maxlevel="Info" Trace tutaj, Debug Information ponieważ WArningDziennik Error , jest również wyprowadzany w kolejnych Critical definicjach.

Czwarty jest dane wyjściowe do final="true" pliku innego niż dziennik zatrzymany powyżej.

Dzienniki archiwum

Istnieje również metoda archiwizacji starego pliku dziennika w osobnym folderze dla każdej daty z tylko jednym głównym plikiem dziennika.

Na przykład:

<target xsi:type="File"
        name="FileOutput"
        fileName="${aspnet-appbasepath}/Log.log"
        archiveNumbering="Date"
        archiveEvery="Day"
        archiveFileName="${aspnet-appbasepath}/Archive/Log_{#}.log"
        archiveDateFormat="yyyy-MM-dd"
        maxArchiveFiles="7"
        layout="${layoutDefine}" />

Parametry użyte w tym miejscu oznaczają:

Opis parametru
archiwumLiczanie numerujące Data tworzy plik archiwum według daty.
archiwumWszysk Dzień jest używany do archiwizacji na co dzień. Istnieją również sposoby, aby określić "Miesiąc", "Godzina", "Niedziela" itp.
archiwumFileName Ścieżka do archiwum. {#} zmienia się na podstawie archiwum po archiwum.
archiveDateFormat Format daty archiwum data daty nazwy pliku.
maxArchiveFiles (Pliki maksymalne) Określa liczbę plików do archiwizacji.

Istnieją również sposoby archiwizowania metod niedaty. Więcej informacji można znaleźć na oficjalnej stronie internetowej.

Po wykonaniu wygląda to tak:

Wysyłanie wiadomości e-mail na dziennik

NLog pozwala również na wysyłanie wiadomości e-mail podczas logowania. Jeśli jednak wyślesz wiadomość e-mail, taką jak dziennik debugowania, będzie ona zbyt duża, aby Dobrym pomysłem jest kierowanie tylko ograniczonych poziomów dziennika, takich jak Błąd i Krytyczne. Ponadto, aby uniknąć ryzyka awarii, takiej jak blokowanie serwera poczty z powodu transmisji Zaleca się określenie konta e-mail tylko do logowania.

Poniżej przedstawiono przykład konfiguracji. Jeśli chcesz faktycznie wysyłać pocztę, postępuj zgodnie z serwerem SMTP, którego chcesz użyć.

<targets>
  <target xsi:type="Mail"
          name="SendMail"
          smtpServer="SMTP Server Name"
          smtpPort="25"
          subject="XXXX システムでエラーが発生しました"
          from="aaaa@example.com"
          to="bbbb@example.com"
          enableSsl="False"
          smtpAuthentication="None"
          smtpUserName=""
          smtpPassword=""
          layout="${layoutDefine}"/>
</targets>

<rules>
  <logger name="*" minlevel="Error" writeTo="SendMail" />
</rules>

Zapisywanie dzienników w bazie danych

NLog można również zapisywać dzienniki do bazy danych. Oto przykład, więc prosimy o zapoznanie się z oficjalną stroną internetową, aby uzyskać szczegółowe informacje.

W tej sekcji opisano kroki, które należy zapisać na programie SQL Server na innym serwerze.

Najpierw utwórz tabelę do rejestrowania w docelowym programie SQL Server. Ponieważ można wybrać wartość do zapisu, zdefiniuj to, czego potrzebujesz jako dziennik jako kolumnę.

Poniżej przedstawiono przykład tworzenia tabeli SQL.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Log](
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Application] [nvarchar](50) NOT NULL,
  [Logged] [datetime] NOT NULL,
  [Level] [nvarchar](50) NOT NULL,
  [User] [nvarchar](250) NOT NULL,
  [Message] [nvarchar](max) NOT NULL,
  [Logger] [nvarchar](250) NULL,
  [Callsite] [nvarchar](max) NULL,
  [Exception] [nvarchar](max) NULL,
  CONSTRAINT [PK_dbo.Log] PRIMARY KEY CLUSTERED 
(
  [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

Do przetwarzania bazy danych wymagana jest biblioteka klienta bazy System.Data.SqlClient danych. Zainstalujmy go z NuGet.

Zapisuje informacje o bazie danych do appsettings.json. nlog.config pozwala na załadowanie informacji w appsettings.json. Ustawienia są wstępne, więc ustaw je zgodnie z rzeczywistą bazą danych. Nazwa klucza jest dowolna, ale jest używana przez nlog.config.

{
  "": "省略",

  "NlogConnection": {
    "DbHost": "ServerName\\SQLEXPRESS",
    "Database": "TestDatabase",
    "User": "UserName",
    "Password": "********"
  }
}

Ustaw plik nlog.config w następujący sposób:

<targets>
  <target xsi:type="Database"
          name="DatabaseOutput"
          dbProvider="sqlserver"
          dbHost="${configsetting:name=NlogConnection.DbHost}"
          dbDatabase="${configsetting:name=NlogConnection.Database}"
          dbUserName="${configsetting:name=NlogConnection.User}"
          dbPassword="${configsetting:name=NlogConnection.Password}">
    <commandText>
      insert into dbo.Log (
        Application, Logged, [Level], [User], Message, Logger, CallSite, Exception
      ) values (
        @Application, @Logged, @Level, @User, @Message, @Logger, @Callsite, @Exception
      );
    </commandText>
    <parameter name="@application" layout="XXXX System" />
    <parameter name="@logged" layout="${date}" />
    <parameter name="@level" layout="${level}" />
    <parameter name="@user" layout="${aspnet-user-identity}" />
    <parameter name="@message" layout="${message}" />
    <parameter name="@logger" layout="${logger}" />
    <parameter name="@callSite" layout="${callsite:filename=true}" />
    <parameter name="@exception" layout="${exception:tostring}" />
  </target>
</targets>

<rules>
  <logger name="*" writeTo="DatabaseOutput" />
</rules>

Jeśli nie ma żadnych błędów do uruchomienia, zostanie on zapisany w następujący sposób:

Nawiasem mówiąc.cs należy pamiętać, że próba zapisu dzienników do bazy danych na wczesnym etapie, na przykład przed program .cs CreateHostBuilder metody, może zakończyć się niepowodzeniem.

Pobierz rejestratory z RequestServices i zarejestruj je

Dodawanie do konstruktora za każdym razem, gdy tworzysz nowy kontroler lub model strony, może być ILogger nużące. Alternatywnie, RequestServices można uzyskać z .

public void OnGet()
{
  // RequestServices から ILogger を取得する
  var logger = (ILogger<IndexModel>)HttpContext.RequestServices.GetService(typeof(ILogger<IndexModel>));

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}

Jeśli określenie własnego kontrolera lub modelu strony jest również uciążliwe, można utworzyć metody rozszerzenia lub klasy podstawowe.

public static class AspNetExtention
{
  /// <summary>
  /// ロガーを取得する拡張メソッドです。
  /// </summary>
  public static ILogger<T> GetLogger<T>(this T self) where T : PageModel
    => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));

  // MVC の場合
  //public static ILogger<T> GetLogger<T>(this T self) where T : Controller
  //  => (ILogger<T>)self.HttpContext.RequestServices.GetService(typeof(ILogger<T>));
}

Przypadki użycia

public void OnGet()
{
  // RequestServices から ILogger を取得する (this. は必要)
  var logger = this.GetLogger();

  logger.LogInformation("ページを表示するタイミングでログを出力します。");
}