Verwenden von NLog zum Protokollieren

Erstellungsdatum der Seite :

Umgebung

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 5.0 (MVC, Razor-Seite)

Zunächst

Mit NLog können Sie Protokolle in Dateien, E-Mails und Datenbanken ausgeben, abhängig von Ihren Einstellungen.

NLog ASP.NET in das Standardprotokollierungssystem des Kerns integriert werden. Es ist möglich, Protokolle entsprechend den Einstellungen auszugeben, während Sie die Standard-Logger verwenden.

Informationen zu Protokollebenen

Microsoft-Protokolle und NLogs sind in sechs Stufen unterteilt, und die Ausgabeebenen sind ungefähr gleich:

Stufe MicrosoftNLog
0 Spur Spur
1 Debuggen Debuggen
2 Informationen Informationen
3 Warnung Warnen
4 Fehler Fehler
5 Kritisch Schwerwiegender
(6) (Keine) (Aus)

Je höher die Ebene, desto wichtiger ist das Protokoll und desto wahrscheinlicher ist es, dass es unabhängig von den Protokollausgabeeinschränkungen geschrieben wird.

Protokollierungsanweisungen

NLog-Paketbereitstellung

ASP.NET Sie ein Core-Projekt erstellt haben, fügen Sie ein Paket hinzu.

Klicken Sie mit der rechten Maustaste auf Abhängigkeiten für Ihr Projekt, und wählen Sie NuGet-Pakete verwalten aus.

Klicken Sie auf die Registerkarte Durchsuchen, und geben Sie NLog in das Suchfeld ein, um NLog-bezogene Pakete anzuzeigen.

Wählen Sie NLog aus, und klicken Sie dann auf die Schaltfläche Installieren mit der neuesten stabilen Version.

Klicken Sie auf OK.

Installieren Sie auch NLog.Web.AspNetCore.

Das Paket wurde dem Projekt hinzugefügt.

Nlog.config hinzufügen

Fügen Sie nlog.config, die Ausgabedefinition des NLog-Protokolls, zum Projekt hinzu. Der Inhalt ist im XML-Format, daher habe ich ihn als XML-Datei erstellt. Der Dateiname sollte nlog.config (Kleinbuchstabe) lauten.

Erstellen Sie die Datei wie folgt: Detaillierte Einstellungen werden später erläutert.

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

Stellen Sie sicher, dass die Eigenschaften von nlog.config auf Build Action: Content, Copy to Output Directory: Copy if New festgelegt sind.

Bearbeiten von appsetting.json

Standardmäßig werden unabhängig davon, wie Sie nlog.config festlegen, Information nur diese Ebenen ausgegeben. Dies liegt daran, dass die Protokollierung auch auf appsetting.json basiert.

Öffnen Sie appsetting.json, Logging.LogLevel.Default und ändern Sie den Wert in Trace . Wenn Sie NLog verwenden, können Sie den Pegel auf der NLog-Seite anpassen, sodass Sie praktisch alle Ebenen ausgeben können, Trace indem Sie appsetting.json festlegen.

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

Auch während der Entwicklung, Appsettings. Die Einstellungen von Development.json werden geladen, daher ändern wir sie ebenfalls.

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

Vorbereiten von Programmen für NLog

Fügen Sie ein Programm hinzu, damit Sie sich im NLog-Mechanismus anmelden können.

Öffnen Sie .cs Programmdatei und beheben Sie sie wie folgt:

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

Protokollierung

Für MVC-Projekte HomeComtroller , für IndexModel Razor-Seiten, wären Sie an den ILogger<IndexModel> logger Konstruktor übergeben worden. Es ist auch im privaten Feld auf, _logger sodass Sie es zum Protokollieren verwenden können.

Im Folgenden finden Sie ein Beispiel für die Ausgabe von einer Razor-Seite, aber MVC kann mit demselben Code ausgegeben werden.

// 省略

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

Beim Debuggen denke ich, dass eine Protokolldatei im Ordner des Projekts erstellt werden kann.

Sie können das Protokoll überprüfen, indem Sie sich den Inhalt der Datei ansehen.

Beispiel nlog.config Kommentar

Ich erkläre es in der Reihenfolge, aber ich erkläre nicht die weniger wichtigen Teile.

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

Es gibt Parameter, z. B. die Protokollausgabeeinstellungen für NLog selbst.

internalLogFile wird das Ziel des Protokolls sein. Dies kann z. B. hilfreich sein, wenn ein Fehler in der Ausgabe des Protokolls selbst auftritt. ${basedir} verweist auf den Ausführungsordner des Programms.

internalLogLevel ist die Ausgabeebene des NLog-Protokolls. Off wenn ja, wird es überhaupt nicht ausgegeben.

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

Die Variable wird auf das Layout festgelegt, in dem der Inhalt des Protokolls ausgegeben wird. Sie können direkt in spätere Ziele eingeben, aber wenn Sie mehrere desselben Layouts angeben, ist es einfacher, sie in einer Variablen zu verwalten.

Es ist besser, auf die offizielle Website zu verweisen, um zu sehen, welche Parameter im Layout angegeben werden können.

Als Referenz werden die hier angegebenen Parameter im folgenden Format ausgegeben:

Parameterausgabeinhalt
longdate Datums- und Zeitminuten wie "2021-03-17 11:46:36.5034"
Ereigniseigenschaften Zeigt die Ereignis-ID usw. der vom Programm angegebenen Protokollausgabe an
Ebene Ebenen wie Trace und Error
Nachricht In der Programmprotokollierung angegebene Meldung
Ausnahme Was passiert, wenn Sie eine Ausnahme in der Programmprotokollierung bestehen?
Callsite Protokollierungsspeicherort, Dateiname usw.

Ausgabebeispiel

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>

Gibt das ziel an, das ausgegeben werden soll. Es kann mehrere angegeben werden.

Die erste xsi:type="Trace" gibt an, und das Protokoll wird im Visual Studio-Ausgabefenster gedruckt. Es kann in erster Linie zum Debuggen der Ausführung verwendet werden.

Die zweite xsi:type="File" gibt eine Datei im angegebenen Pfad an und protokolliert sie in dieser. Wenn Sie ${shortdate} im Pfad angeben, können Sie das Protokoll zum Zeitpunkt des Protokolls in die Datei des Datums des Protokolls schreiben. Gibt auch ${aspnet-appbasepath} den Stammordner für das Webprojekt an. Bei der Betriebsart ist es jedoch besser, Protokolldateien außerhalb des Webverzeichnisses auszugeben, um den Programmaustausch und die Sicherheit zu gewährleisten.

Die dritte wird xsi:type="Console" angegeben und kann in der Konsole in der Konsolen-App angezeigt werden. ASP.NET Core selbst ist keine Konsolen-App, kann aber auch in Umgebungen wie Docker und Azure verwendet werden, da der Status in der Konsole angezeigt werden kann. Dies ist die Beschreibung auf der offiziellen NLog-Website.

<!-- ロガー名からターゲットにマップするルール -->
<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>

Hier geben Sie an, welche Ebene und welche Art von Protokollen wo ausgegeben werden sollen. Diese Beschreibung wird von oben nach oben angewendet.

Die erste besteht darin, name="*" alle Protokolle an das Ziel auszugeben, da die Ebene beim Angeben angegeben writeTo wird. Dies target ist die angegebene in , also wird sie in der Visual TraceOutput Studio-Ausgabe angezeigt.

Die zweite wird Microsoft.Hosting.Lifetime an die Protokollausgabe in der writeTo (コンソール) Bibliothek ausgegeben. ConsoleLifetime-Zuordnungen können in Konsolen wie Azure und Docker aktiviert werden. minlevel="Info" da sie Trace Debug angibt und nicht protokolliert wird. Außerdem geben nachfolgende Definitionen keine final="true" Microsoft.Hosting.Lifetime verwandten Protokolle aus.

Die dritte name="Microsoft.*" besteht darin, die Protokollierung zu name="System.Net.Http.*" beenden, final="true" indem Sie für und Protokolle angeben. name *ist ein Platzhalter, was Microsoft System.Net.Http bedeutet, dass er sich auf alle zugehörigen Bibliotheken bezieht. , aber stoppen Sie hier maxlevel="Info" Trace , Debug Information weil WArningDas Error Protokoll , wird auch in nachfolgenden Critical Definitionen ausgegeben.

Die vierte wird in final="true" eine andere Datei als das oben angehaltene Protokoll ausgegeben.

Archivprotokolle

Es gibt auch eine Methode zum Archivieren der alten Protokolldatei in einem separaten Ordner für jedes Datum mit nur einer Hauptprotokolldatei.

Zum Beispiel:

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

Die hier verwendeten Parameter bedeuten:

Parameterbeschreibung
archivNummerierung Datum erstellt eine Archivdatei nach Datum.
archivEvery Der Tag wird verwendet, um täglich zu archivieren. Es gibt auch Möglichkeiten, "Monat", "Stunde", "Sonntag" usw. anzugeben.
archiveFileName Pfad zum Archivieren. Änderungen auf Archiv-für-Archiv-Basis.
archiveDateFormat Datum-für-Datum-Archivdatumsformat des Dateinamens.
maxArchiveFiles Gibt an, wie viele Dateien archiviert werden sollen.

Es gibt auch Möglichkeiten, Nicht-Datumsmethoden zu archivieren. Weitere Informationen finden Sie auf der offiziellen Website.

Wenn sie ausgeführt wird, sieht es wie folgt aus:

Senden von E-Mails pro Protokoll

Mit NLog können Sie auch E-Mails beim Protokollieren senden. Wenn Sie jedoch eine E-Mail wie ein Debugprotokoll senden, wird es zu viel, um sie zu senden, Es ist eine gute Idee, nur begrenzte Protokollebenen wie Fehler und Schwerwiegend zu zielen. Um das Risiko eines Ausfalls zu vermeiden, wie z. B. das Blockieren des Mailservers aufgrund von Es wird empfohlen, dass Sie ein nur protokollagtes E-Mail-Konto angeben.

Im Folgenden finden Sie ein Beispiel für eine Konfiguration. Wenn Sie tatsächlich E-Mails senden möchten, folgen Sie dem SMTP-Server, den Sie verwenden möchten.

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

Schreiben von Protokollen in die Datenbank

NLog kann auch Protokolle in die Datenbank schreiben. Im Folgenden finden Sie ein Beispiel, daher lesen Sie bitte die offizielle Website für Details.

In diesem Abschnitt werden die Schritte zum Schreiben in SQL Server auf einem anderen Server beschrieben.

Erstellen Sie zunächst eine Tabelle für die Protokollierung im SQL Server-Zielserver. Da Sie den zu schreibenden Wert auswählen können, definieren Sie das, was Sie als Protokoll als Spalte benötigen.

Im Folgenden finden Sie ein Beispiel für SQL für die Tabellenerstellung.

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

Für die Datenbankverarbeitung ist eine Datenbankclientbibliothek System.Data.SqlClient erforderlich. Lassen Sie uns es von NuGet installieren.

Schreibt Datenbankinformationen in appsettings.json. Mit nlog.config können Sie die Informationen in appsettings.json laden. Die Einstellungen sind vorläufig, also stellen Sie sie bitte entsprechend der tatsächlichen Datenbank ein. Der Schlüsselname ist willkürlich, wird aber von nlog.config verwendet.

{
  "": "省略",

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

Legen Sie nlog.config wie folgt fest:

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

Wenn keine Fehler ausgeführt werden, wird sie wie folgt geschrieben:

Übrigens.cs beachten Sie, dass der Versuch, Protokolle in der Datenbank in einem frühen Stadium zu schreiben, z. B. vor .cs CreateHostBuilder Methoden, fehlschlagen kann.

Logger von RequestServices abrufen und protokollieren

Es kann mühsam sein, dem Konstruktor jedes Mal hinzuzufügen, wenn Sie ILogger einen neuen Controller oder ein neues Seitenmodell erstellen. Alternativ RequestServices können Sie von erhalten.

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

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

Wenn die Angabe eines eigenen Controllers oder Seitenmodells ebenfalls umständlich ist, können Sie Erweiterungsmethoden oder grundlegende Klassen erstellen.

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

Anwendungsfälle

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

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