Gunakan NLog untuk log

Tarikh penciptaan halaman :

Persekitaran

Visual Studio
  • Studio Visual 2019
ASP.NET Teras
  • 5.0 (MVC, laman Cukur)

Pada mulanya

NLog membolehkan anda mengeluarkan log ke fail, e-mel dan pangkalan data bergantung pada tetapan anda.

NLog ASP.NET dimasukkan ke dalam sistem pembalakan standard teras. Ia adalah mungkin untuk output kayu balak mengikut tetapan semasa menggunakan pembalak lalai.

Peritikai aras log

Microsoft log dan NLogs dibahagikan kepada enam peringkat, dan tahap output adalah kira-kira sama:

Aras MicrosoftNLog
0 Mengesan Mengesan
1 Nyahpepijat Nyahpepijat
2 Maklumat Maklumat
3 Amaran Memberi amaran kepada
4 Ralat Ralat
5 Kritikal Maut
(6) (Tiada) (Mati)

Semakin tinggi tahap, yang lebih penting log adalah, dan semakin besar kemungkinan ia akan ditulis tanpa mengira kekangan output log.

Arahan pembalakan

Penggunaan Pakej NLog

ASP.NET anda telah mencipta projek Teras, menambah pakej.

Klik kanan Kebergantungan untuk projek anda dan pilih Uruskan Pakej NuGet.

Klik tab Layari dan taipkan NLog dalam medan carian untuk memaparkan pakej berkaitan NLog.

Pilih NLog, dan kemudian klik butang pemasangan dengan versi stabil terkini yang dipilih.

Klik OK.

Juga memasang NLog.Web.AspNetCore.

Pakej ini telah ditambah kepada projek.

Tambah nlog.config

Tambah nlog.config, definisi output log NLog, kepada projek. Kandungannya dalam format XML, jadi saya menciptanya sebagai fail XML. Nama fail sepatutnya nlog.config (lowercase).

Cipta fail seperti berikut: Seting terperinci akan dibincangkan kemudian.

<?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 sifat nlog.config disetkan untuk Membina Tindakan: Kandungan, Salinan ke Direktori Output: Salin jika Baru.

Edit appsetting.json

Secara lalai, tidak kira bagaimana anda menetapkan nlog.config, Information hanya tahap ini output. Ini kerana pembalakan juga bergantung pada appsetting.json.

Buka appsetting.json Logging.LogLevel.Default dan tukar nilai kepada Trace . Jika anda menggunakan NLog, anda boleh melaraskan tahap di sebelah NLog, jadi anda boleh mengeluarkan hampir semua Trace peringkat dengan menetapkan appsetting.json.

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

Juga, semasa pembangunan, aplikasi. Tetapan Development.json dimuatkan, jadi kami mengubahnya juga.

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

Menyediakan program untuk NLog

Tambah atur cara supaya anda boleh log masuk mekanisme NLog.

Buka .cs atur cara dan betulkannya seperti 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 のセットアップ
}

Pembalakan

Untuk projek MVC, HomeComtroller untuk halaman Razor, IndexModel anda telah ILogger<IndexModel> logger diserahkan kepada pembangun. Ia juga ditetapkan dalam _logger bidang persendirian, jadi anda boleh menggunakannya untuk log.

Berikut adalah contoh output dari halaman Razor, tetapi MVC boleh mengeluarkan dengan kod 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("ページを表示するタイミングでログを出力します。");
  }
}

Apabila nyahpepijat, saya fikir fail log boleh dibuat dalam folder projek.

Anda boleh menyemak log dengan melihat kandungan fail.

Contoh nlog.config komentar

Saya menerangkannya teratur, tetapi saya tidak menjelaskan bahagian 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">

Terdapat parameter, seperti tetapan output log untuk NLog itu sendiri.

internalLogFile akan menjadi destinasi log. Ini boleh membantu, sebagai contoh, jika terdapat ralat dalam output log itu sendiri. ${basedir} merujuk kepada folder pelaksanaan atur cara.

internalLogLevel adalah tahap output log NLog. Off jika ia adalah, ia tidak akan 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})" />

Pemboleh ubah disetkan ke susun atur kandungan log akan output. Anda boleh menaip terus ke dalam sasaran kemudian, tetapi jika anda menentukan berbilang susun atur yang sama, lebih mudah untuk menguruskannya dalam satu pemboleh ubah.

Adalah lebih baik untuk merujuk kepada laman web rasmi untuk melihat apa parameter yang boleh ditentukan dalam susun atur.

Untuk rujukan, parameter yang dinyatakan di sini adalah output dalam format berikut:

Kandungan
output parameter
panjang Tarikh dan masa minit seperti "2021-03-17 11:46:36.5034"
sifat peristiwa Memaparkan ID peristiwa, dan lain-lain output log yang ditentukan oleh program
Tahap Aras seperti Jejak dan Ralat
Mesej Mesej yang ditentukan dalam log atur cara
Pengecualian Bagaimana jika anda lulus pengecualian dalam log atur cara
callsite Lokasi pembalakan, nama fail, dll.

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

Tentukan sasaran untuk output. Berbilang boleh ditentukan.

Yang xsi:type="Trace" pertama menentukan , dan log dicetak dalam tetingkap output Visual Studio. Ia boleh digunakan terutamanya untuk pelaksanaan nyahpepijat.

Yang xsi:type="File" kedua menentukan dan log ke fail dalam laluan yang ditentukan. Jika ${shortdate} anda menentukan dalam laluan, anda boleh menulis log ke fail tarikh log pada masa log. ${aspnet-appbasepath} Juga menentukan folder akar untuk projek Web. Walau bagaimanapun, apabila beroperasi, lebih baik mengeluarkan fail log di luar direktori Web untuk penggantian dan keselamatan atur cara.

Yang ketiga xsi:type="Console" ditentukan dan boleh dipaparkan dalam konsol dalam aplikasi konsol. ASP.NET Teras itu sendiri bukan aplikasi konsol, tetapi ia juga boleh digunakan dalam persekitaran seperti Docker dan Azure kerana negeri ini boleh dipaparkan dalam konsol. Ini adalah penerangan di laman web rasmi 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 tahap apa dan jenis kayu balak untuk output ke mana. Perihalan ini digunakan dari atas ke atas.

Yang pertama adalah name="*" untuk mengeluarkan semua kayu balak ke sasaran kerana tahap writeTo ditentukan semasa menentukan . Ini target adalah yang ditentukan dalam , TraceOutput jadi ia muncul dalam output Visual Studio.

Yang kedua Microsoft.Hosting.Lifetime ialah output kepada output log di writeTo (コンソール) perpustakaan. Persatuan KonsolLifetime boleh diperiksa dalam konsol seperti Azure dan Docker. minlevel="Info" kerana Trace Debug ia menentukan , dan tidak dilog. Juga, definisi berikutnya tidak mengeluarkan final="true" Microsoft.Hosting.Lifetime log yang berkaitan.

Yang name="Microsoft.*" ketiga adalah name="System.Net.Http.*" untuk menghentikan log dengan menentukan dan final="true" log. name *adalah kad bebas, yang Microsoft System.Net.Http bermaksud bahawa ia merujuk kepada semua perpustakaan yang berkaitan. , tetapi berhenti di maxlevel="Info" Trace sini , Debug Information kerana WArningThe Error , , log juga output dalam Critical definisi berikutnya.

Keempat adalah output ke final="true" fail selain daripada log yang dihentikan di atas.

Balak arkib

Terdapat juga kaedah mengarkibkan fail log lama dalam folder berasingan untuk setiap tarikh dengan hanya satu fail log utama.

Contohnya:

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

Perihalan parameter
arkib Tarikh mencipta fail arkib mengikut tarikh.
arkibEvery Hari digunakan untuk mengarkib setiap hari. Terdapat juga cara untuk menentukan "Bulan", "Jam", "Ahad", dll.
arkibFileName Laluan ke arkib. {#} perubahan pada asas arkib mengikut arkib.
arkibFormat Format tarikh arkib tarikh nama fail.
maxArchiveFiles Tentukan berapa banyak fail untuk diarkibkan.

Terdapat juga cara untuk mengarkibkan kaedah bukan tarikh. Untuk maklumat lanjut, lihat laman web rasmi.

Apabila dilaksanakan, ia kelihatan seperti ini:

Hantar e-mel setiap log

NLog juga membolehkan anda menghantar e-mel semasa log. Walau bagaimanapun, jika anda menghantar e-mel seperti log nyahpepijat, ia akan menjadi terlalu banyak untuk dihantar, Ia adalah idea yang baik untuk menyasarkan hanya tahap log terhad, seperti Ralat dan Maut. Di samping itu, untuk mengelakkan risiko kegagalan, seperti menyekat pelayan mel kerana penghantaran berlebihan, Kami mengesyorkan agar anda menentukan akaun e-mel log sahaja.

Berikut adalah contoh konfigurasi. Jika anda mahu benar-benar menghantar mel, ikuti pelayan SMTP yang anda mahu 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>

Tulis balak ke pangkalan data

NLog juga boleh menulis balak ke pangkalan data. Berikut adalah contoh, jadi sila rujuk laman web rasmi untuk maklumat lanjut.

Bahagian ini menerangkan langkah-langkah untuk menulis ke SQL Server pada pelayan lain.

Pertama, cipta jadual untuk log masuk sasaran SQL Server. Oleh kerana anda boleh memilih nilai untuk menulis, tentukan apa yang anda perlukan sebagai log sebagai lajur.

Berikut adalah contoh penciptaan jadual 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

Perpustakaan pelanggan pangkalan data System.Data.SqlClient diperlukan untuk pemprosesan pangkalan data. Mari kita pasang dari NuGet.

Menulis maklumat pangkalan data kepada appsettings.json. nlog.config membolehkan anda memuatkan maklumat dalam appsettings.json. Tetapan adalah tentatif, jadi sila tetapkannya mengikut pangkalan data sebenar. Nama utama sewenang-wenangnya, tetapi digunakan oleh nlog.config.

{
  "": "省略",

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

Tetapkan nlog.config seperti 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 tiada ralat untuk dijalankan, ia akan ditulis seperti berikut:

Dengan cara ini.cs bahawa cuba menulis kayu balak ke pangkalan data pada peringkat awal, seperti sebelum program CreateHostBuilder .cs, mungkin gagal.

Dapatkan pembalak daripada RequestServices dan log mereka

Ia boleh membosankan untuk ditambah kepada pemula setiap kali ILogger anda mencipta pengawal baru atau model halaman. Sebagai alternatif, RequestServices anda boleh mendapatkan dari .

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

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

Jika menentukan model pengawal atau halaman anda sendiri juga rumit, anda boleh mencipta kaedah sambungan atau kelas asas.

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

Guna kes

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

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