استخدام NLog لتسجيل

تاريخ إنشاء الصفحة :

وسط

استوديو مرئي
  • استوديو مرئي 2019
ASP.NET كور
  • 5.0 (MVC، صفحة الشفرة)

في البداية

يسمح لك NLog بإخراج سجلات الملفات ورسائل البريد الإلكتروني وقواعد البيانات اعتمادا على إعداداتك.

ASP.NET يتم دمج NLog في نظام التسجيل القياسي الأساسي. فمن الممكن لإخراج سجلات وفقا للإعدادات أثناء استخدام المسجل الافتراضي.

حول مستويات السجل

تنقسم سجلات Microsoft وNLogs إلى ست مراحل، ومستويات الإخراج هي نفسها تقريبا:

مستوى مايكروسوفتNLog
0 أثر أثر
1 تصحيح تصحيح
2 معلومات معلومات
3 تحذير حذر
4 خطأ خطأ
5 حرج قاتل
(6) (لا يوجد) (إيقاف)

كلما ارتفع المستوى، كلما كان السجل أكثر أهمية، وكلما زاد احتمال كتابته بغض النظر عن قيود إخراج السجل.

تعليمات التسجيل

نشر حزمة NLog

ASP.NET قمت بإنشاء مشروع Core، قم بإضافة حزمة.

انقر بزر الماوس الأيمن فوق تبعيات المشروع وحدد إدارة حزم NuGet.

انقر فوق علامة التبويب استعراض واكتب NLog في حقل البحث لعرض الحزم المرتبطة ب NLog.

حدد NLog، ثم انقر فوق زر التثبيت مع تحديد أحدث إصدار مستقر.

انقر فوق موافق.

أيضا تثبيت NLog.Web.AspNetCore.

تمت إضافة الحزمة إلى المشروع.

إضافة nlog.config

إضافة nlog.config تعريف الإخراج سجل NLog إلى المشروع. المحتويات بتنسيق XML، لذلك قمت بإنشائه كملف XML. يجب أن يكون اسم الملف nlog.config (صغيرة).

إنشاء الملف كما يلي: ستتم مناقشة الإعدادات التفصيلية لاحقا.

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

تأكد من أن يتم تعيين خصائص nlog.config إلى بناء الإجراء: المحتوى، نسخ إلى دليل الإخراج: نسخ إذا جديد.

تحرير appsetting.json

بشكل افتراضي، بغض النظر عن كيفية تعيين nlog.config، Information يتم إخراج هذه المستويات فقط. وذلك لأن التسجيل يعتمد أيضا على appsetting.json.

افتح appsetting.json Logging.LogLevel.Default وغير القيمة إلى Trace . إذا كنت تستخدم NLog، يمكنك ضبط المستوى على الجانب NLog، حتى تتمكن من إخراج جميع المستويات تقريبا Trace عن طريق تعيين appsetting.json.

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

أيضا ، أثناء التطوير ، appsettings. يتم تحميل إعدادات Development.json ، لذلك نحن نغيرها أيضا.

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

إعداد برامج ل NLog

إضافة برنامج بحيث يمكنك تسجيل الدخول إلى آلية NLog.

فتح ملف برنامج .cs وإصلاحه كما يلي:

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

تسجيل

لمشاريع MVC HomeComtroller ، لصفحات Razor ، كنت IndexModel قد تم ILogger<IndexModel> logger تمريرها إلى المنشئ. كما يتم تعيينها إلى _logger في الحقل الخاص، بحيث يمكنك استخدامها لتسجيل الدخول.

فيما يلي مثال على الإخراج من صفحة Razor ولكن MVC يمكن الإخراج بنفس التعليمات البرمجية.

// 省略

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

عند تصحيح الأخطاء، أعتقد أنه يمكن إجراء ملف سجل في مجلد المشروع.

يمكنك التحقق من السجل من خلال النظر في محتويات الملف.

نموذج تعليق nlog.config

أنا أشرح ذلك بالترتيب، لكنني لا أشرح الأجزاء الأقل أهمية.

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

هناك معلمات، مثل إعدادات إخراج السجل ل NLog نفسه.

internalLogFile ستكون وجهة السجل. يمكن أن يكون هذا مفيدا، على سبيل المثال، إذا كان هناك خطأ في إخراج السجل نفسه. ${basedir} يشير إلى مجلد تنفيذ البرنامج.

internalLogLevel هو مستوى إخراج سجل NLog. Off إذا كان، فإنه لن يكون الناتج على الإطلاق.

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

يتم تعيين المتغير إلى أي تخطيط سيتم إخراج محتويات السجل فيه. يمكنك الكتابة مباشرة إلى أهداف لاحقة، ولكن إذا قمت بتحديد مضاعف من نفس التخطيط، فمن الأسهل إدارتها في متغير واحد.

من الأفضل الرجوع إلى الموقع الرسمي لمعرفة المعلمات التي يمكن تحديدها في التخطيط.

للرجوع إليها، المعلمات المحددة هنا هي الإخراج بالتنسيق التالي:

محتوى إخراج
المعلمة
تاريخ طويل التاريخ والوقت دقائق مثل "2021-03-17 11:46:36.5034"
خصائص الحدث يعرض معرف الحدث، وما إلى ذلك من إخراج السجل المحدد من قبل البرنامج
مستوى مستويات مثل التتبع والخطأ
رسالة الرسالة المحددة في تسجيل البرنامج
استثناء ماذا لو قمت بتمرير استثناء في تسجيل البرنامج
موقع المكالمات تسجيل الموقع، اسم الملف، الخ.

مثال الإخراج

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>

تحديد الهدف إلى الإخراج. يمكن تحديد متعددة.

يحدد الأول xsi:type="Trace" ، ويتم طباعة السجل في إطار الإخراج Visual Studio. يمكن استخدامه بشكل أساسي لتصحيح الأخطاء التنفيذ.

يحدد الثاني xsi:type="File" ويسجل إلى ملف في المسار المحدد. إذا قمت ${shortdate} بتحديد في المسار، يمكنك كتابة السجل إلى ملف تاريخ السجل في وقت السجل. كما ${aspnet-appbasepath} يحدد المجلد الجذر لمشروع ويب. ومع ذلك، عند التشغيل، فمن الأفضل إخراج ملفات السجل خارج دليل ويب لاستبدال البرنامج والأمان.

يتم تحديد الثالث xsi:type="Console" ويمكن عرضه في وحدة التحكم في تطبيق وحدة التحكم. ASP.NET Core نفسه ليس تطبيق وحدة تحكم، ولكن يمكن استخدامه أيضا في بيئات مثل Docker و Azure لأنه يمكن عرض الحالة في وحدة التحكم. هذا هو الوصف على الموقع الرسمي 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>

هنا يمكنك تحديد ما هو مستوى ونوع من السجلات لإخراج إلى أين. يتم تطبيق هذا الوصف من الأعلى إلى الأعلى.

الأول هو name="*" إخراج كافة السجلات إلى الهدف لأنه يتم تحديد المستوى writeTo أثناء تحديد . هذا target هو المحدد في ، بحيث يظهر في إخراج Visual TraceOutput Studio.

والثاني هو Microsoft.Hosting.Lifetime الإخراج إلى إخراج السجل في writeTo (コンソール) المكتبة. يمكن إيداع اقترانات ConsoleLifetime في لوحات المفاتيح مثل Azure و Docker. minlevel="Info" لأنه Trace Debug يحدد ، ولا يتم تسجيل. كما أن التعريفات اللاحقة لا تقوم بإخراج final="true" Microsoft.Hosting.Lifetime السجلات ذات الصلة.

والثالث name="Microsoft.*" هو name="System.Net.Http.*" إيقاف تسجيل final="true" الدخول عن طريق تحديد وسجلات. name *حرف بدل، مما يعني Microsoft System.Net.Http أنه يشير إلى جميع المكتبات ذات الصلة. ، ولكن توقف هنا maxlevel="Info" Trace ، Debug Information لأن WArningيتم Error أيضا إخراج السجل ، في Critical التعريفات اللاحقة.

الرابع هو الإخراج إلى final="true" ملف آخر غير السجل توقف أعلاه.

سجلات الأرشيف

هناك أيضا طريقة أرشفة ملف السجل القديم في مجلد منفصل لكل تاريخ مع ملف سجل رئيسي واحد فقط.

على سبيل المثال:

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

المعلمات المستخدمة هنا تعني:

وصف المعلمة
أرشيفرقم التاريخ بإنشاء ملف أرشيف حسب التاريخ.
أرشيفكل شيء يستخدم اليوم للأرشفة على أساس يومي. وهناك أيضا طرق لتحديد "شهر"، "ساعة"، "الأحد"، الخ.
اسم ملف الأرشيف المسار إلى الأرشيف إلى. يتغير {#} على أساس كل أرشيف على حدة.
أرشيفتاريخ_تنسيق تنسيق تاريخ تاريخ الأرشيف من اسم الملف.
ملفات الأرشفة القصوى تحديد عدد الملفات التي سيتم أرشفتها.

وهناك أيضا طرق لأرشفة أساليب غير التاريخ. لمزيد من المعلومات، راجع الموقع الرسمي.

عند تنفيذها، يبدو الأمر كما يلي:

إرسال رسائل البريد الإلكتروني لكل سجل

يسمح لك NLog أيضا بإرسال رسائل البريد الإلكتروني عند تسجيل الدخول. ومع ذلك، إذا قمت بإرسال بريد إلكتروني مثل سجل التصحيح، سوف تصبح أكثر من اللازم لإرسال، من المستحسن استهداف مستويات تسجيل محدودة فقط، مثل الخطأ و Fatal. بالإضافة إلى ذلك، لتجنب خطر الفشل، مثل حظر خادم البريد بسبب انتقال المبالغ، نوصي بتحديد حساب بريد إلكتروني لتسجيل الدخول فقط.

فيما يلي مثال على تكوين. إذا كنت تريد إرسال البريد فعليا اتبع ملقم SMTP الذي تريد استخدامه.

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

كتابة سجلات إلى قاعدة البيانات

يمكن أيضا كتابة سجلات NLog إلى قاعدة البيانات. وفيما يلي مثال على ذلك، لذا يرجى الرجوع إلى الموقع الرسمي للحصول على التفاصيل.

يصف هذا القسم الخطوات الكتابة إلى SQL Server على ملقم آخر.

أولا، إنشاء جدول لتسجيل الدخول إلى ملقم SQL الهدف. نظرا لأنه يمكنك اختيار القيمة للكتابة، حدد ما تحتاجه كسجل كأعمدة.

التالي مثال لإنشاء جدول 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

مطلوب مكتبة عميل قاعدة بيانات System.Data.SqlClient لمعالجة قاعدة البيانات. دعونا تثبيته من NuGet.

يكتب معلومات قاعدة البيانات إلى appsettings.json. nlog.config يسمح لك بتحميل المعلومات في appsettings.json. الإعدادات مؤقتة ، لذا يرجى تعيينها وفقا لقاعدة البيانات الفعلية. اسم المفتاح إجبارية ولكن يتم استخدامه بواسطة nlog.config.

{
  "": "省略",

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

تعيين nlog.config كما يلي:

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

إذا كان هناك أية أخطاء لتشغيل، سيتم كتابتها كما يلي:

بالمناسبة.cs لاحظ أن محاولة كتابة سجلات إلى قاعدة البيانات في مرحلة مبكرة، مثل قبل أساليب .cs CreateHostBuilder البرنامج، قد تفشل.

الحصول على قاطعي الأخشاب من RequestServices وتسجيلها

يمكن أن يكون مملة لإضافة إلى المنشئ في كل مرة تقوم ILogger بإنشاء وحدة تحكم جديدة أو نموذج صفحة. بدلا من ذلك، RequestServices يمكنك الحصول على من .

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

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

إذا كان تحديد وحدة التحكم الخاصة بك أو نموذج الصفحة مرهقا أيضا ، فيمكنك إنشاء أساليب تمديد أو فئات أساسية.

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

حالات الاستخدام

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

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