Protokolování pomocí protokolu NLog

Datum vytvoření stránky :

Prostředí

Visual Studio
  • Visual Studio 2019
ASP.NET jádro
  • 5.0 (MVC, stránka Razor)

Zpočátku

NLog umožňuje vytvářet protokoly do souborů, e-mailů a databází v závislosti na vašem nastavení.

NLog ASP.NET být začleněn do standardního systému protokolování jádra. Protokoly je možné vysílávat podle nastavení při použití výchozího protokolování.

O úrovních protokolu

Protokoly Microsoftu a NLogy jsou rozděleny do šesti fází a výstupní úrovně jsou zhruba stejné:

Úroveň MicrosoftNLog
0 Trasování Trasování
1 Ladění Ladění
2 Informace Info
3 Upozornění Varovat
4 Chyba Chyba
5 Kritické Fatální
(6) (Žádné) (Vypnuto)

Čím vyšší je úroveň, tím důležitější je protokol a tím je pravděpodobnější, že bude zapsán bez ohledu na omezení výstupu protokolu.

Pokyny pro protokolování

Nasazení balíčku protokolu NLog

ASP.NET jste vytvořili projekt Core, přidejte balíček.

Klikněte pravým tlačítkem myši na Závislosti pro váš projekt a vyberte Spravovat balíčky NuGet.

Kliknutím na kartu Procházet a zadáním protokolu NLog do vyhledávacího pole zobrazíte balíčky související s NLogem.

Vyberte NLog a pak klepněte na tlačítko instalovat s vybranou nejnovější stabilní verzí.

Klikněte na OK.

Nainstalujte také NLog.Web.AspNetCore.

Balíček byl přidán do projektu.

Přidat nlog.config

Přidejte do projektu nlog.config, výstupní definici protokolu NLog. Obsah je ve formátu XML, proto jsem ho vytvořil jako soubor XML. Název souboru by měl být nlog.config (malá písmena).

Vytvořte soubor následujícím způsobem: Podrobná nastavení budou popsána později.

<?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>

Ujistěte se, že vlastnosti nlog.config jsou nastaveny na Akci sestavení: Obsah, Kopírovat do výstupního adresáře: Kopírovat, pokud je nový.

Upravit appsetting.json

Ve výchozím nastavení, bez ohledu na to, jak nastavíte nlog.config, Information jsou výstupem pouze tyto úrovně. Je to proto, že protokolování také spoléhá na appsetting.json.

Otevřete appsetting.json Logging.LogLevel.Default a změňte hodnotu na Trace . Pokud používáte NLog, můžete upravit úroveň na straně NLog, takže můžete výstup prakticky všech úrovní Trace nastavením appsetting.json.

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

Také během vývoje, appsettings. Nastavení development.json jsou načtena, takže je také měníme.

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

Příprava programů pro NLog

Přidejte program, abyste se mohli přihlásit do mechanismu NLog.

Otevřete .cs programový soubor a opravte ho následujícím způsobem:

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 のセットアップ
}

Protokolování

U projektů MVC HomeComtroller byste pro stránky Razor byli IndexModel ILogger<IndexModel> logger předáni konstruktoru. Je také nastavena _logger na soukromé pole, takže ji můžete použít k protokolování.

Následuje příklad výstupu ze stránky Razor, ale MVC může výstup se stejným kódem.

// 省略

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("ページを表示するタイミングでログを出力します。");
  }
}

Při ladění si myslím, že soubor protokolu lze vytvořit ve složce projektu.

Protokol můžete zkontrolovat tak, že se podíváme na obsah souboru.

Ukázkový komentář nlog.config

Vysvětluji to v pořádku, ale nevysvětluji ty méně důležité části.

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

Existují parametry, například nastavení výstupu protokolu pro samotný NLog.

internalLogFile bude cílem protokolu. To může být užitečné například v případě, že dojde k chybě ve výstupu samotného protokolu. ${basedir} odkazuje na složku spuštění programu.

internalLogLevel je výstupní úroveň protokolu NLog. Off pokud ano, nebude to výstup vůbec.

<!-- ログの出力レイアウトを変数 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})" />

Proměnná je nastavena na to, v jakém rozložení bude obsah protokolu výstupem. Můžete psát přímo do pozdějších cílů, ale pokud zadáte více stejného rozložení, je snazší je spravovat v jedné proměnné.

Je lepší se podívat na oficiální webové stránky, abyste zjistili, jaké parametry lze zadat v rozvržení.

Pro informaci, zde zadané parametry jsou výstupem v následujícím formátu:

Výstupní obsah parametru
dlouhé datum Datum a čas minut, například "2021-03-17 11:46:36.5034"
vlastnosti události Zobrazí ID události atd. výstupu protokolu určeného programem.
Úrovni Úrovně, jako je trasování a chyba
Zprávu Zpráva zadaná v protokolování programů
Výjimka Co když projdete výjimkou v protokolování programů
na telefonním bajce Umístění protokolování, název souboru atd.

Příklad výstupu

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>

Určuje cíl výstupu. Lze zadat více.

První určuje xsi:type="Trace" a protokol se vytiskne ve výstupním okně sady Visual Studio. Může být použit především pro ladění spuštění.

Druhý xsi:type="File" určuje a protokoluje soubor v zadané cestě. Pokud ${shortdate} v cestě zadáte, můžete protokol zapsat do souboru data protokolu v době protokolu. Určuje ${aspnet-appbasepath} také kořenovou složku webového projektu. Při provozu je však lepší výstup souborů protokolu mimo webový adresář pro nahrazení programu a zabezpečení.

Třetí je zadán xsi:type="Console" a lze jej zobrazit v konzole v aplikaci konzoly. ASP.NET Core není konzolová aplikace, ale může se také použít v prostředích, jako je Docker a Azure, protože stav se může zobrazit v konzole. Toto je popis na oficiálních stránkách 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>

Zde určíte, na jakou úroveň a jaký typ protokolů se má výstupovat kam. Tento popis se aplikuje shora nahoru.

První je výstup name="*" všech protokolů do cíle, protože úroveň je writeTo určena při zadání . Toto target je zadané v oblasti , takže se zobrazí ve TraceOutput výstupu sady Visual Studio.

Druhý je výstup Microsoft.Hosting.Lifetime do výstupu protokolu v writeTo (コンソール) knihovně. Přidružení ConsoleLifetime se můžou kontrolovat v konzolích, jako jsou Azure a Docker. minlevel="Info" protože Trace Debug určuje a není protokolován. Následující definice také nevysílou final="true" Microsoft.Hosting.Lifetime související protokoly.

Třetí name="Microsoft.*" je zastavit name="System.Net.Http.*" protokolování final="true" zadáním pro a protokoly. name *je zástupný znak, což Microsoft System.Net.Http znamená, že odkazuje na všechny související knihovny. , ale zastavte se maxlevel="Info" Trace zde , Debug Information protože WArningProtokol Error , je také výstupem v následných Critical definicích.

Čtvrtý je výstup do final="true" jiného souboru, než je protokol zastavený výše.

Archivní protokoly

Existuje také způsob archivace starého souboru protokolu v samostatné složce pro každé datum pouze s jedním hlavním souborem protokolu.

Například:

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

Zde použité parametry znamenají:

Popis parametru
archivNumbering Datum vytvoří soubor archivu podle data.
archivEvery Den se denně archivuje. Existují také způsoby, jak zadat "Měsíc", "Hodina", "Neděle" atd.
archiveFileName Cesta k archivaci. {#} se mění podle archivace.
archiveDateFormat Formát data data archivace názvu souboru
maxArchiveFiles Určuje, na kolik souborů se má archivovat.

Existují také způsoby archivace neautuových metod. Další informace naleznete na oficiálních stránkách.

Při spuštění to vypadá takhle:

Odesílání e-mailů podle protokolu

Protokol NLog také umožňuje odesílat e-maily při protokolování. Pokud však odešlete e-mail, například protokol ladění, bude příliš mnoho na odeslání, Je dobré cílit pouze na omezené úrovně protokolu, například Error a Fatal. Kromě toho, aby se zabránilo riziku selhání, jako je blokování poštovního serveru v důsledku přenosu přes Doporučujeme zadat e-mailový účet pouze pro protokol.

Následuje příklad konfigurace. Chcete-li skutečně odesílat poštu, postupujte podle serveru SMTP, který chcete použít.

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

Zápis protokolů do databáze

Protokoly NLog lze také zapisovat do databáze. Níže je příkladem, takže podrobnosti naleznete na oficiálních webových stránkách.

Tato část popisuje postup zápisu na sql server na jiném serveru.

Nejprve vytvořte tabulku pro protokolování na cílovém serveru SQL Server. Vzhledem k tomu, že můžete zvolit hodnotu pro zápis, definujte to, co potřebujete jako protokol jako sloupec.

Následuje příklad vytvoření tabulky 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

Pro zpracování databáze je System.Data.SqlClient vyžadována knihovna databázových klientů. Nainstalujeme ji z NuGetu.

Zapíše informace o databázi na appsettings.json. nlog.config umožňuje načíst informace do appsettings.json. Nastavení jsou předběžná, proto je nastavte podle skutečné databáze. Název klíče je libovolný, ale používá ho nlog.config.

{
  "": "省略",

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

Nastavte nlog.config takto:

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

Pokud nejsou k dispozici žádné chyby ke spuštění, bude zapsána následujícím způsobem:

Mimochodem, .cs, že pokus o zápis protokolů do databáze v rané fázi, například před metodami CreateHostBuilder .cs, může selhat.

Získejte protokolátory z RequestServices a zaprotokolují je

Může být únavné přidávat do konstruktoru pokaždé, když ILogger vytvoříte nový řadič nebo stránkový model. Případně se RequestServices můžete dostat z .

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

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

Pokud je zadání vlastního řadiče nebo modelu stránky také těžkopádné, můžete vytvořit metody rozšíření nebo základní třídy.

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>));
}

Případy použití

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

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