استفاده از NLog برای ورود به سیستم

تاریخ ایجاد صفحه :

محیط

ویژوال استودیو
  • ویژوال استودیو ۲۰۱۹
ASP.NET هسته
  • 5.0 (MVC، صفحه تیغ)

در ابتدا

NLog اجازه می دهد تا شما را به خروجی سیاهههای مربوط به فایل ها، ایمیل ها، و پایگاه داده ها بسته به تنظیمات خود را.

NLog ASP.NET تواند به سیستم ورود به سیستم استاندارد هسته گنجانیده شده است. ممکن است به خروجی سیاهههای مربوط با توجه به تنظیمات در حالی که با استفاده از چوب پیش فرض.

درباره سطح ورود به سیستم

لاگ های مایکروسافت و NLogs به شش مرحله تقسیم می شوند، و سطوح خروجی تقریباً یکسان هستند:

سطح
مایکروسافتNLog
0 ردیابی ردیابی
1 اشکال زدایی اشکال زدایی
2 اطلاعات اطلاعات
3 هشدار هشدار
4 خطا خطا
5 بحرانی کشنده
(6) (هیچ کدام) (خاموش)

هر چه سطح بالاتر باشد، لاگ مهم تر است و احتمال نوشتن آن بدون در نظر گرفتن محدودیت های خروجی لاگ بیشتر است.

دستورالعمل ورود به سیستم

استقرار بسته NLog

ASP.NET یک پروژه Core ایجاد کرده اید، یک بسته اضافه کنید.

وابستگی ها را برای پروژه خود کلیک راست کنید و مدیریت بسته های NuGet را انتخاب کنید.

برای نمایش بسته های مربوط به NLog روی زبانه Browse کلیک کنید و NLog را در زمینه جستجو تایپ کنید.

NLog را انتخاب کنید، و سپس دکمه نصب را با آخرین نسخه پایدار انتخاب شده کلیک کنید.

روی OK کلیک کنید.

همچنین 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..

به طور پیش فرض، مهم نیست که چگونه شما مجموعه nlog.config، Information تنها این سطوح خروجی هستند. دلیل این است که ورود به سیستم نیز متکی بر appsetting.

باز appsetting.خانم Logging.LogLevel.Default و تغییر ارزش به Trace . اگر از NLog استفاده می کنید، می توانید سطح را در سمت NLog تنظیم کنید، بنابراین می توانید عملاً تمام سطوح را با تنظیم Trace appsetting.

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

همچنین، در طول توسعه، ناراحت کننده است. تنظیمات Development.هم بارگذاری شده اند، بنابراین ما آنها را نیز تغییر میدهیم.

{
  "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 IndexModel منتقل شده ILogger<IndexModel> logger است. همچنین در زمینه خصوصی تنظیم شده _logger است، بنابراین شما می توانید از آن برای ورود به سیستم استفاده کنید.

در زیر نمونه ای از خروجی از یک صفحه تیغ است، اما 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"
رویداد خواص شناسه رویداد و غیره خروجی log مشخص شده توسط برنامه را نمایش می دهد
سطح سطوحی مانند ردیابی و خطا
پیام پیام مشخص شده در ورود به سیستم برنامه
استثنا چه می شود اگر شما تصویب استثنا در ورود به سیستم برنامه
callsite محل ورود به سیستم، نام فایل و غیره.

مثال خروجی

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" کند ، و ورود به سیستم در پنجره خروجی ویژوال استودیو چاپ شده است. این می تواند در درجه اول برای اشکال زدایی اعدام استفاده می شود.

دوم مشخص و xsi:type="File" سیاهههای مربوط به یک فایل در مسیر مشخص شده است. اگر در مسیر مشخص کنید، می توانید ورود به پرونده تاریخ ورود به سیستم را در زمان ورود به سیستم ${shortdate} بنویسید. همچنین پوشه ${aspnet-appbasepath} ریشه برای پروژه وب را مشخص می کند. با این حال ، در هنگام فعالیت ، بهتر است به خروجی فایل های ورود به سیستم خارج از دایرکتوری وب برای جایگزینی برنامه و امنیت.

سوم مشخص شده xsi:type="Console" است و می تواند در کنسول در برنامه کنسول نمایش داده شود. ASP.NET Core خود یک برنامه کنسول نیست، اما می توان از آن در محیط هایی مانند داکر و لاجورد نیز استفاده کرد زیرا ایالت می تواند در کنسول نمایش داده شود. این توضیحات در وب سایت رسمی 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 شده در است ، بنابراین آن را در خروجی TraceOutput ویژوال استودیو ظاهر می شود.

دوم خروجی به 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 wildcard است، که به این 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}" />

پارامترهای مورد استفاده در اینجا به این معنی است:

توضیحات
پارامتر
archiveNumbering تاریخ یک فایل آرشیو بر اساس تاریخ ایجاد می کند.
archiveEvery روز به صورت روزانه برای بایگانی استفاده می شود. همچنین راه هایی برای مشخص کردن "ماه"، "ساعت"، "یکشنبه"، و غیره وجود دارد.
archiveFileName مسیر بایگانی به. {#} بر اساس آرشیو به بایگانی تغییر می کند.
archiveDateFormat تاریخ به تاریخ آرشیو فرمت تاریخ نام فایل.
maxArchiveFiles مشخص می کند که چگونه بسیاری از فایل ها را به بایگانی تا.

همچنین راه هایی برای بایگانی روش های غیر تاریخ وجود دارد. برای کسب اطلاعات بیشتر به وب سایت رسمی مراجعه کنید.

وقتی اعدام می شود، به این شکل به نظر می رسد:

ارسال ایمیل در هر ورود به سیستم

NLog همچنین اجازه می دهد تا شما را به ارسال ایمیل در هنگام ورود به سیستم. با این حال ، اگر شما ارسال یک ایمیل مانند ورود به سیستم اشکال زدایی ، آن را تبدیل خواهد شد بیش از حد برای ارسال ، این ایده خوبی برای هدف قرار دادن تنها سطوح ورود به سیستم محدود، مانند خطا و کشنده است. علاوه بر این ، برای جلوگیری از خطر شکست ، مانند مسدود کردن سرور الکترونیکی به دلیل انتقال overs ، ما توصیه می کنیم که یک حساب ایمیل تنها ورود به سیستم را مشخص کنید.

در زیر نمونه ای از یک پیکربندی است. اگر می خواهید در واقع نامه ارسال کنید، سرور 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.هم می نویسد. nlog.config اجازه می دهد تا شما را به بار اطلاعات در appsettings.. تنظیمات آزمایشی هستند، بنابراین لطفا آنها را با توجه به پایگاه داده واقعی تنظیم کنید. نام کلیدی دلخواه است، اما توسط 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("ページを表示するタイミングでログを出力します。");
}