Utilizzare NLog per registrare

Data di creazione della pagina :

ambiente

Visual Studio
  • Visual Studio 2019
ASP.NET Nucleo
  • 5.0 (MVC, pagina Razor)

dapprima

NLog consente di generare registri in file, e-mail e database a seconda delle impostazioni.

NLog ASP.NET essere incorporato nel sistema di registrazione standard del core. È possibile emettere registri in base alle impostazioni durante l'utilizzo del logger predefinito.

Informazioni sui livelli di registro

I registri Microsoft e gli NLog sono suddivisi in sei fasi e i livelli di output sono all'incirca gli stessi:

Livello MicrosoftNLog
0 traccia traccia
1 Debug Debug
2 informazione Informazioni
3 avvertimento avvertire
4 errore errore
5 critico fatale
(6) (Nessuno) (Disattivato)

Più alto è il livello, più importante è il log e più è probabile che venga scritto indipendentemente dai vincoli di output del log.

Istruzioni per la registrazione

Distribuzione del pacchetto NLog

ASP.NET hai creato un progetto Core, aggiungi un pacchetto.

Fare clic con il pulsante destro del mouse su Dipendenze per il progetto e scegliere Gestisci pacchetti NuGet.

Fare clic sulla scheda Sfoglia e digitare NLog nel campo di ricerca per visualizzare i pacchetti correlati a NLog.

Selezionare NLog e quindi fare clic sul pulsante di installazione con l'ultima versione stabile selezionata.

Fare clic su OK.

Installare anche NLog.Web.AspNetCore.

Il pacchetto è stato aggiunto al progetto.

Aggiungere nlog.config

Aggiungere nlog.config, la definizione di output del log NLog, al progetto. Il contenuto è in formato XML, quindi l'ho creato come file XML. Il nome del file deve essere nlog.config (minuscolo).

Creare il file come segue: Le impostazioni dettagliate saranno discusse in seguito.

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

Assicurarsi che le proprietà di nlog.config siano impostate su Azione di compilazione: Contenuto, Copia nella directory di output: Copia se nuovo.

Modifica appsetting.json

Per impostazione predefinita, indipendentemente dal modo in cui si imposta nlog.config, Information vengono esistiti solo questi livelli. Questo perché la registrazione si basa anche su appsetting.json.

Aprire appsetting.json Logging.LogLevel.Default e modificare il valore in Trace . Se si utilizza NLog, è possibile regolare il livello sul lato NLog, in modo da poter emettere praticamente tutti i Trace livelli impostando appsetting.json.

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

Inoltre, durante lo sviluppo, appsettings. Le impostazioni di Development.json vengono caricate, quindi le stiamo cambiando anche noi.

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

Preparazione dei programmi per NLog

Aggiungere un programma in modo da poter accedere al meccanismo NLog.

Aprire .cs file di programma e risolverlo come segue:

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

Registrazione

Per i progetti MVC HomeComtroller , per le pagine IndexModel Razor, sarebbe stato passato al ILogger<IndexModel> logger costruttore. È anche impostato su _logger nel campo privato, quindi è possibile utilizzarlo per registrare.

Di seguito è riportato un esempio di output da una pagina Razor, ma MVC può eseguire l'output con lo stesso codice.

// 省略

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

Durante il debug, penso che sia possibile creare un file di registro nella cartella del progetto.

È possibile controllare il registro esaminando il contenuto del file.

Commento nlog.config di esempio

Lo sto spiegando in ordine, ma non sto spiegando le parti meno importanti.

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

Esistono parametri, ad esempio le impostazioni di output del log per NLog stesso.

internalLogFile sarà la destinazione del log. Questo può essere utile, ad esempio, se c'è un errore nell'output del log stesso. ${basedir} si riferisce alla cartella di esecuzione del programma.

internalLogLevel è il livello di output del log NLog. Off se lo è, non verrà prodotto affatto.

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

La variabile è impostata sul layout in cui verrà prodotto il contenuto del log. È possibile digitare direttamente nelle destinazioni successive, ma se si specificano più dello stesso layout, è più facile gestirli in un'unica variabile.

È meglio fare riferimento al sito web ufficiale per vedere quali parametri possono essere specificati nel layout.

Per riferimento, i parametri specificati qui sono output nel seguente formato:

Contenuto di output dei parametri
longdate Minuti di data e ora come "2021-03-17 11:46:36.5034"
proprietà dell'evento Visualizza l'ID evento e così via dell'output del registro specificato dal programma
livello Livelli come Traccia ed Errore
Messaggio Messaggio specificato nella registrazione del programma
eccezione Cosa succede se si passa l'eccezione nella registrazione del programma
callsite Percorso di registrazione, nome file, ecc.

Esempio di output

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>

Specifica la destinazione da generare. È possibile specificare più.

Il primo xsi:type="Trace" specifica e il log viene stampato nella finestra di output di Visual Studio. Può essere utilizzato principalmente per il debug dell'esecuzione.

Il secondo xsi:type="File" specifica e accede a un file nel percorso specificato. Se si ${shortdate} specifica nel percorso, è possibile scrivere il registro nel file della data del registro al momento del log. Specifica ${aspnet-appbasepath} inoltre la cartella radice per il progetto Web. Tuttavia, quando si opera, è meglio generare file di registro all'esterno della directory Web per la sostituzione e la protezione del programma.

Il terzo è xsi:type="Console" specificato e può essere visualizzato nella console nell'app console. ASP.NET Core stesso non è un'app console, ma può essere usato anche in ambienti come Docker e Azure perché lo stato può essere visualizzato nella console. Questa è la descrizione sul sito ufficiale di 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>

Qui si specifica quale livello e quale tipo di registri emettere dove. Questa descrizione viene applicata dall'alto verso l'alto.

Il primo è quello di name="*" generare tutti i log nella destinazione perché il livello è specificato durante la specifica di writeTo . Si target tratta dell'oggetto specificato in , pertanto TraceOutput viene visualizzato nell'output di Visual Studio.

Il secondo è Microsoft.Hosting.Lifetime l'output nell'output del log nella writeTo (コンソール) libreria. Le associazioni ConsoleLifetime possono essere archiviate in console quali Azure e Docker. minlevel="Info" perché specifica Trace Debug e non è registrato. Inoltre, le definizioni successive non esvengono final="true" Microsoft.Hosting.Lifetime esati nei registri correlati.

Il terzo name="Microsoft.*" è interrompere la registrazione name="System.Net.Http.*" final="true" specificando per e log. name *è un carattere jolly, il che significa che si riferisce a Microsoft System.Net.Http tutte le librerie correlate. , ma fermati maxlevel="Info" Trace qui, Debug Information perché WArningIl Error log , , viene anche prodotto nelle definizioni Critical successive.

Il quarto è l'output final="true" in un file diverso dal registro arrestato sopra.

Registri di archiviazione

Esiste anche un metodo per archiviare il vecchio file di registro in una cartella separata per ogni data con un solo file di registro principale.

Per esempio:

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

I parametri qui utilizzati significano:

Descrizione del parametro
archiveNumerazione Data crea un file di archivio per data.
archivioEvery Il giorno viene utilizzato per archiviare quotidianamente. Esistono anche modi per specificare "Mese", "Ora", "Domenica", ecc.
archiveFileName Percorso da archiviare. {#} cambia in base all'archivio.
archiveDateFormat Formato data per data di archiviazione del nome del file.
File maxArchive Specifica il numero di file da archiviare fino a.

Esistono anche modi per archiviare metodi non datati. Per ulteriori informazioni, consultare il sito ufficiale.

Quando viene eseguito, ha questo aspetto:

Inviare messaggi di posta elettronica per registro

NLog ti consente anche di inviare e-mail durante la registrazione. Tuttavia, se si invia un'e-mail come un registro di debug, diventerà troppo da inviare, È una buona idea indirizzare solo livelli di log limitati, ad esempio Errore e Fatale. Inoltre, per evitare il rischio di guasti, come il blocco del server di posta a causa della trasmissione overs, È consigliabile specificare un account di posta elettronica solo log.

Di seguito è riportato un esempio di configurazione. Se si desidera inviare effettivamente la posta, seguire il server SMTP che si desidera utilizzare.

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

Scrivere registri nel database

NLog può anche scrivere log nel database. Di seguito è riportato un esempio, quindi si prega di fare riferimento al sito Web ufficiale per i dettagli.

In questa sezione vengono descritti i passaggi per scrivere in SQL Server in un server diverso.

Creare innanzitutto una tabella per l'accesso a SQL Server di destinazione. Poiché è possibile scegliere il valore da scrivere, definire ciò di cui è necessario come log come colonna.

Di seguito è riportato un esempio di SQL per la creazione di tabelle.

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

Per l'elaborazione del database System.Data.SqlClient è necessaria una libreria client di database. Installiamolo da NuGet.

Scrive le informazioni del database in appsettings.json. nlog.config consente di caricare le informazioni in appsettings.json. Le impostazioni sono provvisorie, quindi si prega di impostarle in base al database effettivo. Il nome della chiave è arbitrario, ma viene utilizzato da nlog.config.

{
  "": "省略",

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

Impostare nlog.config come segue:

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

Se non ci sono errori da eseguire, verrà scritto come segue:

A proposito.cs notare che il tentativo di scrivere log nel database in una fase iniziale, ad esempio prima che il programma .cs CreateHostBuilder metodi, potrebbe non riuscire.

Ottenere logger da RequestServices e registrarli

Può essere noioso aggiungere al costruttore ogni volta che si crea un ILogger nuovo controller o modello di pagina. In alternativa, RequestServices è possibile ottenere da .

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

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

Se anche specificare il proprio controller o modello di pagina è complicato, è possibile creare metodi di estensione o classi di base.

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

Casi d'uso

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

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