Gunakan NLog untuk log

Tanggal pembuatan halaman :

Lingkungan

Visual Studio
  • Studio Visual 2019
ASP.NET Inti
  • 5.0 (MVC, halaman Pisau Cukur)

Pada awalnya

NLog memungkinkan Anda untuk mengeluarkan log ke file, email, dan database tergantung pada pengaturan Anda.

NLog ASP.NET akan dimasukkan ke dalam sistem pencatatan standar inti. Dimungkinkan untuk keluaran log sesuai dengan pengaturan saat menggunakan pencatat default.

Tentang tingkat log

Log dan NLog Microsoft dibagi menjadi enam tahap, dan tingkat outputnya kira-kira sama:

Tingkat MicrosoftNLog
0 Jejak Jejak
1 Debug Debug
2 Informasi Info
3 Peringatan Memperingatkan
4 Kesalahan Kesalahan
5 Kritis Fatal
(6) (Tidak ada) yang mengetahuinya. (Nonaktif)

Semakin tinggi levelnya, semakin penting log, dan semakin besar kemungkinan untuk ditulis terlepas dari batasan output log.

Instruksi pencatatan

Penyebaran Paket NLog

ASP.NET Anda telah membuat proyek Inti, tambahkan paket.

Klik kanan Dependensi untuk proyek Anda dan pilih Kelola Paket NuGet.

Klik tab Telusuri dan ketik NLog di bidang pencarian untuk menampilkan paket terkait NLog.

Pilih NLog, lalu klik tombol instal dengan versi stabil terbaru dipilih.

Klik OK.

Instal juga NLog.Web.AspNetCore.

Paket telah ditambahkan ke proyek.

Tambahkan nlog.config

Tambahkan nlog.config, definisi output dari log NLog, ke proyek. Konten dalam format XML, jadi saya membuatnya sebagai file XML. Nama berkas harus nlog.config (huruf kecil).

Buat file sebagai berikut: Pengaturan terperinci akan dibahas nanti.

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

Pastikan bahwa properti nlog.config diatur ke Build Action: Content, Copy to Output Directory: Copy if New.

Edit appsetting.json

Secara default, tidak peduli bagaimana Anda mengatur nlog.config, Information hanya level ini yang keluaran. Ini karena pencatatan juga bergantung pada appsetting.json.

Buka appsetting.json Logging.LogLevel.Default dan ubah nilainya menjadi Trace . Jika Anda menggunakan NLog, Anda dapat menyesuaikan level di sisi NLog, sehingga Anda dapat menghasilkan hampir semua level Trace dengan mengatur appsetting.json.

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

Juga, selama pengembangan, appsettings. Pengaturan Development.json dimuat, jadi kami juga mengubahnya.

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

Mempersiapkan program untuk NLog

Tambahkan program sehingga Anda dapat masuk ke mekanisme NLog.

Buka .cs program anda dan perbaiki sebagai berikut:

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

Penebangan

Untuk proyek MVC, HomeComtroller untuk halaman Razor, IndexModel Anda akan diteruskan ke ILogger<IndexModel> logger konstruktor. Ini juga diatur ke di _logger bidang pribadi, sehingga Anda dapat menggunakannya untuk log.

Berikut ini adalah contoh output dari halaman Razor, tetapi MVC dapat menghasilkan dengan kode yang sama.

// 省略

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

Saat men-debug, saya berpikir bahwa file log dapat dibuat di folder proyek.

Anda dapat memeriksa log dengan melihat isi file.

Contoh komentar nlog.config

Aku menjelaskannya secara bermusyutan, tapi aku tidak menjelaskan bagian yang kurang penting.

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

Ada parameter, seperti pengaturan output log untuk NLog itu sendiri.

internalLogFile akan menjadi tujuan log. Ini dapat membantu, misalnya, jika ada kesalahan dalam output log itu sendiri. ${basedir} mengacu pada folder eksekusi program.

internalLogLevel adalah tingkat output dari log NLog. Off jika ya, itu tidak akan menjadi output sama sekali.

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

Variabel diatur ke tata letak apa isi log akan keluaran. Anda dapat mengetik langsung ke target nanti, tetapi jika Anda menentukan kelipatan tata letak yang sama, lebih mudah untuk mengelolanya dalam satu variabel.

Lebih baik merujuk ke situs web resmi untuk melihat parameter apa yang dapat ditentukan dalam tata letak.

Untuk referensi, parameter yang ditentukan di sini adalah output dalam format berikut:

Konten output parameter
longdate Tanggal dan menit waktu seperti "2021-03-17 11:46:36.5034"
properti kejadian Menampilkan ID kejadian, dll.
Tingkat Tingkat seperti Jejak dan Kesalahan
Pesan Pesan yang ditentukan dalam pembuatan log program
Pengecualian Bagaimana jika Anda melewati pengecualian dalam pembuatan log program
callite Lokasi pencatatan, nama berkas, dll.

Contoh keluaran

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>

Menentukan target ke keluaran. Kelipatan dapat ditentukan.

Yang xsi:type="Trace" pertama menentukan , dan log dicetak di jendela output Visual Studio. Ini dapat digunakan terutama untuk eksekusi debugging.

Yang xsi:type="File" kedua menentukan dan log ke file di jalur yang ditentukan. Jika ${shortdate} Anda menentukan di jalur, Anda dapat menulis log ke file tanggal log pada saat log. Juga ${aspnet-appbasepath} menentukan folder root untuk proyek Web. Namun, ketika beroperasi, lebih baik untuk mengeluarkan file log di luar direktori Web untuk penggantian dan keamanan program.

Yang ketiga xsi:type="Console" ditentukan dan dapat ditampilkan di konsol di aplikasi konsol. ASP.NET Core sendiri bukanlah aplikasi konsol, tetapi juga dapat digunakan di lingkungan seperti Docker dan Azure karena keadaan dapat ditampilkan di konsol. Ini adalah deskripsi di situs resmi 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>

Di sini Anda menentukan tingkat apa dan tipe log apa yang akan keluaran ke mana. Deskripsi ini diterapkan dari atas ke atas.

Yang pertama adalah name="*" untuk output semua log ke target karena level ditentukan saat menentukan writeTo . Ini target adalah yang ditentukan dalam , TraceOutput sehingga muncul di output Visual Studio.

Yang kedua Microsoft.Hosting.Lifetime adalah output ke keluaran log di writeTo (コンソール) pustaka. Asosiasi ConsoleLifetime dapat di-check in konsol seperti Azure dan Docker. minlevel="Info" karena Trace Debug menentukan , dan tidak dicatat. Selain itu, definisi berikutnya tidak final="true" Microsoft.Hosting.Lifetime menghasilkan log terkait.

Yang name="Microsoft.*" ketiga adalah name="System.Net.Http.*" menghentikan pencatatan dengan menentukan untuk dan final="true" log. name *adalah wildcard, yang Microsoft System.Net.Http berarti mengacu pada semua pustaka terkait. , tapi berhenti di maxlevel="Info" Trace sini, Debug Information karena WArningLog Error , , juga keluaran dalam definisi Critical berikutnya.

Keempat adalah keluaran final="true" ke berkas selain log yang berhenti di atas.

Log arsip

Ada juga metode pengarsipan file log lama di folder terpisah untuk setiap tanggal dengan hanya satu file log utama.

Misalnya:

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

Parameter yang digunakan di sini berarti:

Deskripsi parameter
archiveJumlah Tanggal membuat file arsip menurut tanggal.
archiveEvery Hari digunakan untuk mengarsipkan setiap hari. Ada juga cara untuk menentukan "Bulan", "Jam", "Minggu", dll.
archiveFileName Jalur untuk diarsipkan. {#} berubah berdasarkan archive-by-archive.
archiveDateFormat Format tanggal demi tanggal dari nama file.
MaxArchiveFiles Menentukan berapa banyak berkas yang akan diarsipkan.

Ada juga cara untuk mengarsipkan metode non-tanggal. Untuk informasi selengkapnya, lihat situs web resmi.

Ketika dijalankan, sepertinya ini:

Mengirim email per log

NLog juga memungkinkan Anda mengirim email saat masuk. Namun, jika Anda mengirim email seperti log debug, itu akan menjadi terlalu banyak untuk dikirim, Adalah ide yang baik untuk menargetkan hanya tingkat log terbatas, seperti Kesalahan dan Fatal. Selain itu, untuk menghindari risiko kegagalan, seperti memblokir server email karena transmisi overs, Kami menyarankan agar Anda menentukan akun email log-saja.

Berikut ini adalah contoh konfigurasi. Jika Anda ingin benar-benar mengirim email, ikuti server SMTP yang ingin Anda gunakan.

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

Menulis log ke database

NLog juga dapat menulis log ke database. Berikut ini adalah contohnya, jadi silakan merujuk ke situs web resmi untuk detailnya.

Bagian ini menjelaskan langkah-langkah untuk menulis ke SQL Server di server yang berbeda.

Pertama, buat tabel untuk masuk ke target SQL Server. Karena Anda dapat memilih nilai untuk ditulis, tentukan apa yang Anda butuhkan sebagai log sebagai kolom.

Berikut ini adalah contoh pembuatan tabel 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

Pustaka klien System.Data.SqlClient database diperlukan untuk pemrosesan database. Mari kita instal dari NuGet.

Menulis informasi database ke appsettings.json. nlog.config memungkinkan Anda untuk memuat informasi di appsettings.json. Pengaturannya tentatif, jadi silakan atur sesuai dengan database yang sebenarnya. Nama kunci sewenang-wenang, tetapi digunakan oleh nlog.config.

{
  "": "省略",

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

Set nlog.config sebagai berikut:

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

Jika tidak ada kesalahan untuk dijalankan, itu akan ditulis sebagai berikut:

By the way.cs mencatat bahwa mencoba menulis log ke database pada tahap awal, seperti sebelum program CreateHostBuilder .cs, mungkin gagal.

Dapatkan penebang dari RequestServices dan catat

Ini bisa membosankan untuk ditambahkan ke konstruktor setiap kali Anda ILogger membuat pengontrol atau model halaman baru. Atau, RequestServices Anda bisa mendapatkan dari .

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

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

Jika menentukan pengontrol atau model halaman Anda sendiri juga rumit, Anda dapat membuat metode ekstensi atau kelas dasar.

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

Gunakan kasus

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

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