ارتقاء به ASP.NET Core 1.0 - قسمت 17 - بررسی فریم ورک Logging
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: پنج دقیقه

ASP.NET Core به همراه یک فریم ورک توکار ثبت وقایع (Logging) ارائه شده‌ی توسط تزریق وابستگی‌ها است که به صورت پیش فرض نیز فعال است.


این تصویر را پیشتر در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 6 - سرویس‌ها و تزریق وابستگی‌ها» مشاهده کرده‌اید. در اینجا لیست سرویس‌هایی را مشاهده می‌کنید که به صورت پیش فرض، ثبت شده‌اند و فعال هستند و ILogger و ILoggerFactory نیز جزئی از آن‌ها هستند. بنابراین نیازی به فعال سازی آن‌ها نیست؛ اما برای استفاده‌ی از آن‌ها نیاز به انجام یک سری تنظیمات است.


پیاده سازی ثبت وقایع در ASP.NET Core

اولین قدم کار با فریم ورک ثبت وقایع ASP.NET Core، معرفی ILoggerFactory به متد Configure کلاس آغازین برنامه است:
public void Configure(ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env)
{
   loggerFactory.AddConsole(Configuration.GetSection("Logging"));
   loggerFactory.AddDebug();
متد Configure امضای مشخصی را ندارد و در اینجا به هر تعداد سرویسی که نیاز باشد، می‌توان اینترفیس‌های آن‌ها را جهت تزریق وابستگی‌های متناظر توسط IoC Containser توکار ASP.NET Core، معرفی کرد. در اینجا برای تنظیم ویژگی‌های سرویس ثبت وقایع، تزریق وابستگی ILoggerFactory  صورت گرفته‌است.
سطر اول متد، تنظیمات ثبت وقایع را از خاصیت Logging فایل appsettings.json برنامه می‌خواند (در مورد خاصیت Configuration، در مطلب «ارتقاء به ASP.NET Core 1.0 - قسمت 7 - کار با فایل‌های config» بیشتر بحث شد) و لاگ کردن ویژه‌ی در کنسول NET Core. را فعال می‌کند:
{
    "Logging": {
        "IncludeScopes": false,
        "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information"
        }
    }
}
در مورد Log Level و یا سطوح ثبت وقایع، در ادامه‌ی مطلب بحث خواهد شد.

و سطر دوم سبب نمایش اطلاعات لاگ شده در کنسول دیباگ ویژوال استودیو می‌شود.
متد AddDebug برای شناسایی، نیاز به افزودن وابستگی‌های ذیل در فایل project.json برنامه را دارد:
{
    "dependencies": {
        //same as before 
        "Microsoft.Extensions.Logging": "1.0.0",
        "Microsoft.Extensions.Logging.Console": "1.0.0",
        "Microsoft.Extensions.Logging.Debug": "1.0.0" 
    }
}
پس از این تنظیمات، برنامه را اجرا کنید.


در اینجا می‌توانید ریز وقایعی را که توسط ASP.NET Core لاگ شده‌است، مشاهده کنید. برای مثال چه درخواستی صورت گرفته‌است و چقدر اجرای آن زمان‌برده‌است.
این فعال سازی مرتبط است به متد AddDebug که اضافه شد. اگر می‌خواهید خروجی AddConsole را هم مشاهده کنید، از طریق خط فرمان، به پوشه‌ی اصلی پروژه وارد شده و سپس دستور dotnet run را اجرا کنید:


دستور dotnet run سبب راه اندازی وب سرور برنامه بر روی پورت 5000 شده‌است که در تصویر نیز مشخص است.
بنابراین اینبار برای دسترسی به برنامه باید مسیر http://localhost:5000 را در مرورگر خود طی کنید. در اینجا نیز می‌توان حالت‌های مختلف اطلاعات لاگ شده را مشاهده کرد و تمام این‌ها مرتبط هستند به ذکر متد AddConsole .


کار با سرویس ثبت وقایع ASP.NET Core از طریق تزریق وابستگی‌ها

برای کار با سرویس ثبت وقایع توکار ASP.NET Core در قسمت‌های مختلف برنامه، می‌توان از ترزیق وابستگی ILogger آن استفاده کرد:
[Route("[controller]")]
public class AboutController : Controller
{
    private readonly ILogger<AboutController> _logger;
 
    public AboutController(ILogger<AboutController> logger)
    {
        _logger = logger;
    }
 
    [Route("")]
    public ActionResult Hello()
    {
        _logger.LogInformation("Running Hello");
        return Content("Hello from DNT!");
    }
در این کنترلر، وابستگی اینترفیس ILogger با پارامتری از نوع کنترلر جاری به سازنده‌ی کلاس تزریق شده‌است. علت ذکر این پارامتر جنریک این است که ILoggerFactory بداند چگونه باید متد CreateLogger خود را در پشت صحنه وهله سازی کند.
سپس با توجه به اینکه این سرویس جزو سرویس‌های از پیش ثبت شده‌ی ASP.NET Core است، امکانات آن بدون نیاز به تنظیمات بیشتری در دسترس است. برای مثال از متد LogInformation آن در اکشن متد Hello استفاده شده‌است و خروجی عبارت لاگ شده‌ی آن‌را در اینجا می‌توانید مشاهده کنید:



سطوح مختلف ثبت وقایع

اینترفیس ILogger به همراه متدهای مختلفی است؛ مانند LogError، LogDebug و غیره. معانی آن‌ها به شرح زیر هستند:
Debug (1): ثبت واقعه‌ای است با بیشترین حد جزئیات ممکن که عموما شامل اطلاعات حساسی نیز می‌باشد. بنابراین نباید در حالت ارائه‌ی نهایی برنامه فعال شود.
(2) Verbose: ثبت وقایعی مفصل، جهت بررسی مشکلات در حین توسعه‌ی برنامه. تنها باید حاوی اطلاعاتی برای دیباگ برنامه باشند.
(3) Information: عموما برای ردیابی قسمت‌های مختلف برنامه مورد استفاده قرار می‌گیرند.
(4) Warning: جهت ثبت واقعه‌ای نامطلوب در سیستم بکار می‌رود و سبب قطع اجرای برنامه نمی‌شود.
(5) Errors: مشکلات برنامه را که سبب قطع سرویس دهی آن شده‌اند را ثبت می‌کند. هدف آن ثبت مشکلات واحد جاری است و نه کل برنامه.
Critical (6): هدف آن ثبت مشکلات بحرانی کل سیستم است که سبب از کار افتادن آن شده‌اند.

برای مثال در حین تنظیم متد AddDebug که سبب نمایش اطلاعات لاگ شده در کنسول دیباگ ویژوال استودیو می‌شود، می‌توان حداقل سطح ثبت وقایع را نیز ذکر کرد:
 loggerFactory.AddDebug(minLevel: LogLevel.Information);
این حداقل مرتبط است با اعدادی که در کنار سطوح فوق ملاحظه می‌کنید. برای مثال اگر حداقل سطح ثبت وقایع به Information تنظیم شود، چون سطح آن 3 است، دیگر سطوح پایین‌تر از آن لاگ نخواهند شد. اهمیت این مساله در اینجا است که اگر صرفا نیاز به اطلاعات Critical داشتیم، نیازی نیست تا با انبوهی از اطلاعات لاگ شده سر و کار داشته باشیم و به این ترتیب می‌توان حجم اطلاعات نمایش داده شده را کاهش داد.

البته ترتیب واقعی این سطوح را در enum مرتبط با آن‌ها بهتر می‌توان مشاهده کرد:
  public enum LogLevel
  {
    Trace,
    Debug,
    Information,
    Warning,
    Error,
    Critical,
    None,
  }

یک نکته: زمانیکه متد AddDebug را بدون پارامتر فراخوانی می‌کنید، حداقل سطح ثبت وقایع آن به Information تنظیم شده‌است. یعنی در این لاگ، خبری از اطلاعات Debug نخواهد بود (چون سطح دیباگ پایین‌تر است از Information).  بنابراین اگر می‌خواهید این اطلاعات را هم مشاهده کنید باید پارامتر minLevel آن‌را به LogLevel.Debug تنظیم نمائید.


امکان استفاده‌ی از پروایدرهای ثبت وقایع ثالث

تا اینجا، دو نمونه از پروایدرهای توکار ثبت وقایع ASP.NET Core را بررسی کردیم. اگر نیاز به ثبت این اطلاعات با فرمت‌های مختلف و یا در بانک اطلاعاتی وجود دارد، می‌توان به تامین کننده‌های ثالثی که قابلیت کار با ILoggerFactory را دارند نیز مراجعه کرد. برای مثال:
- elmah.io - provider for the elmah.io service
- Loggr - provider for the Loggr service
- NLog - provider for the NLog library
- Serilog - provider for the Serilog library
  • #
    ‫۷ سال و ۶ ماه قبل، دوشنبه ۷ فروردین ۱۳۹۶، ساعت ۰۰:۳۷
    به روز رسانی
    با حذف فایل project.json در VS 2017، اکنون با کلیک راست بر روی گروه نام پروژه (فایل csproj)، گزینه‌ی Edit آن ظاهر شده و مداخل ذکر شده‌ی در مطلب فوق، چنین تعاریفی را پیدا می‌کنند: 
    <Project Sdk="Microsoft.NET.Sdk.Web">
      <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.1" />
        <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
      </ItemGroup>
    </Project>
  • #
    ‫۷ سال و ۳ ماه قبل، یکشنبه ۲۸ خرداد ۱۳۹۶، ساعت ۱۴:۲۷
    امکانش هست برای ثبت وقایع در دیتابیس یا filesystem از همین امکان logger استفاده کرد با customize کردن یا پیشنهاد میکنید برای این منظور مثلا از elmah استفاده شود؟
    در حقیقت چون من تا به اینجا از این لاگر استفاده کرده بودم در یک پروژه میخواستم پیشنهاد بدید تغییرش بدم یا به فکر custom کردنش باشم.
  • #
    ‫۷ سال و ۱ ماه قبل، پنجشنبه ۲۶ مرداد ۱۳۹۶، ساعت ۱۵:۴۲
    یک نکته‌ی تکمیلی: تغییرات ثبت Logging در ASP.NET Core 2.0

    در ASP.NET Core 2.0، دو روش جدید برای ثبت Loggerهای مختلف ارائه شده‌است:
    روش اول: معرفی Loggers در ConfigureServices فایل آغازین برنامه
    public void ConfigureServices(IServiceCollection services)
    {
       services.AddLogging(builder => builder.AddConsole().AddDebug());
       services.AddMvc();
    }

    روش دوم: معرفی Loggers در فایل Program.cs
    public static IWebHost BuildWebHost(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    .ConfigureLogging((hostingContext, logging) =>
                    {
                        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                        logging.AddConsole();
                        logging.AddDebug();
                    })
                    .Build();
    مزیت روش دوم، خالی شدن فایل Startup.cs و همچنین امکان دسترسی به hostingContext است که در متد ConfigureLogging پیش بینی شده‌است. در اینجا متد AddConfiguration امکان دسترسی به تنظیمات مدخل ذیل را پیدا می‌کند (با توجه به اینکه متد جدید WebHost.CreateDefaultBuilder کار خواندن فایل‌های appsettings.json و appsettings.{env.EnvironmentName}.json را به صورت خودکار انجام می‌دهد):
    {
      "Logging": {
        "IncludeScopes": false,
        "Console": {
          "LogLevel": {
            "Default": "Warning"
          }
        }
      }
    }
  • #
    ‫۶ سال و ۹ ماه قبل، شنبه ۱۸ آذر ۱۳۹۶، ساعت ۲۳:۳۴
    یک نکته‌ی تکمیلی: روش فعالسازی ثبت لاگ‌ها در Windows EventLog 

    اگر از سرور ویندوزی استفاده می‌کنید، ثبت لاگ‌های برنامه در Windows EventLog و مشاهده‌ی آن‌ها توسط Event viewer ویندوز، یکی از روش‌های مناسب بررسی مشکلات برنامه پس از publish آن است. برای کار با آن، ابتدا نیاز است Windows Compatibility Pack for .NET Core را نصب کنید:
    > dotnet add package Microsoft.Windows.Compatibility --version 2.0.0-preview1-25914-04
    همچنین بسته‌ی نیوگت Microsoft.Extensions.Logging.EventLog نیز باید نصب شود (اگر از بسته‌ی Microsoft.AspNetCore.All استفاده می‌کنید، هم اکنون قابل دسترسی است).
    پس از آن فعالسازی ثبت در EventLog ویندوز به صورت ذیل است:
    var webHost = new WebHostBuilder()
                    //...
                    .ConfigureLogging((hostingContext, logging) =>
                    {
                      logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                      logging.AddEventLog();
                    })
                    //...
    • #
      ‫۳ سال و ۲ ماه قبل، شنبه ۵ تیر ۱۴۰۰، ساعت ۰۰:۲۷
      نکته تکمیلی
      برای ثبت لاگ در Windows event log در سطح Information و Information به پایین باید بخش Logging در appsettings.json را به شکل زیر تغییر داد :
      {
        "Logging": {
          "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
          },
          "EventLog": { // here ...
            "LogLevel": {
              "Default": "Information" //Trace, Debug
            }
          }
        }
      }
  • #
    ‫۵ سال و ۶ ماه قبل، پنجشنبه ۲ اسفند ۱۳۹۷، ساعت ۱۴:۲۹
    یک نکته‌ی تکمیلی: اگر تنظیمات Logging در فایل applicationsettings.json قید نشوند، برنامه به شدت کند خواهد شد
    عموما در فایل applicationsettings.json یک چنین تنظیمی وجود دارد:
    {
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      }
    }
    اگر در حین ارائه‌ی نهایی برنامه این فایل یا این تنظیم را فراموش کنید، سطح لاگ پیش‌فرض برنامه به Information تنظیم می‌شود. در این حالت کوچکترین رخ‌دادی نیز در برنامه لاگ خواهد شد و این مساله به شدت کارآیی برنامه را کاهش می‌دهد (تا حدود 40 برابر!). بنابراین ارائه‌ی پیش‌فرض فوق را فراموش نکنید.
    • #
      ‫۵ سال و ۶ ماه قبل، شنبه ۱۸ اسفند ۱۳۹۷، ساعت ۱۵:۰۱
      استفاده از تامین کننده Console در حین ارائه نهایی نیز به شدت باعث کند شدن و کاهش کارآیی برنامه خواهد شد. بهتر است این تامین کننده را صرفا در محیط Development تنظیم کنید:
      public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
          WebHost.CreateDefaultBuilder(args)
              .UseDefaultServiceProvider((context, options) =>
              {
                  options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
              })
              .ConfigureLogging((hostingContext, logging) =>
              {
                  logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                  logging.AddDebug();
                  
                  if (hostingContext.HostingEnvironment.IsDevelopment())
                  {
                      logging.AddConsole();
                  }
              })
              .UseStartup<Startup>();

      • #
        ‫۵ سال و ۶ ماه قبل، یکشنبه ۱۹ اسفند ۱۳۹۷، ساعت ۱۵:۴۰
        نکته تکمیلی
         اگر از WebHost.CreateDefaultBuilder استفاده می‌کنید، به صورت پیش‌فرض سه تامین کننده زیر ثبت خواهند شد:
        Console
        Debug
        EventSource
        در نکته مطرح شده در بازخورد بالا، ابتدا لازم است با استفاده از logging.ClearProviders، تامین کننده‌های ثبت شده پیش‌فرض را حذف کنید.
  • #
    ‫۴ سال و ۵ ماه قبل، چهارشنبه ۲۰ فروردین ۱۳۹۹، ساعت ۱۵:۵۸
    نکته تکمیلی 
    اگر در تنظیمات Serilog برنامه جهت لاگ زدن پیغام استثنائات این خط ()Enrich.WithExceptionDetails را اضافه کرده اید.  
    using Serilog;
    using Serilog.Exceptions;
    
    ILogger logger = new LoggerConfiguration()
        .Enrich.WithExceptionDetails()   // This Line
        .WriteTo.RollingFile(
            new JsonFormatter(renderMessage: true), 
            @"C:\logs\log-{Date}.txt")    
        .CreateLogger();
    در EntityFrameworkCore باید موارد دیگری را  نیز به تنظیمات اضافه کنید. در غیر این صورت در مواقع خاص باعث میشود کل جداول موجود در DbConext برنامه را Select زده، که باعث افت شدید برنامه و گاها از کار افتادن برنامه می‌شود.
     
  • #
    ‫۳ سال و ۸ ماه قبل، سه‌شنبه ۲ دی ۱۳۹۹، ساعت ۱۳:۳۲
    یک نکته‌ی تکمیلی: معرفی سیستم Logging در Asp.Net Core

    سیستم Logging  در نسخه Core بصورت پیشفرض موجود هست، اما در پروژه‌های غیر Core اگر نیاز به استفاده از آن را داشتید باید اول پکیج Microsoft.Extensions.Logging.Console را نصب کنید. طریقه استفاده ازین سیستم بسیار راحت بوده و کانفیگ خیلی خاصی ندارد؛ اما قبل از استفاده باید با اصطلاحات اولیه آن آشنا بشیم. چیزی که مسئولیت ثبت Log در برنامه‌های Core را دارد Logging Api تعریف شده در خود پلتفرم Asp.Net Core میباشد. Log‌ها طبق این سیستم ذخیره میشوند و توسط Provider‌های مختلف قابل نمایش میباشند. اما Logging Provider چیست؟ ابزاری که با استفاده از آن میتوانیم Log‌های ذخیره شده توسط Logger را مشاهده کنیم و یا بعضا دستور ذخیره Log‌ها را به Logger  ارسال کنیم. در ادامه لیستی از Logging Provider‌های موجود را میبینیم که شامل Debug  , Console , EventSource , EventLog , AzureAppService , Application Insights و... میباشد. Log Provider‌های متنوعی وجود دارند که بعضی از آن‌ها مزایا و معایب خود را دارند و قابل همگام سازی با سیستم Asp.Net Core Logging میباشند مثل Provider‌های Serilog , NLog و دیگر پکیج‌هایی که برای این موضوع وجود دارند. در وهله بعد وقتی صحبت از ذخیره Log‌ها به میان میاید تعاریفی برای درجه اهمیت هر Log و الویت بندی Log‌ها مطابق اهمیتشان وجود دارد که به ما کمک میکند دسته بندی و نظم بهتری در Log‌های برنامه خودمان بیابیم. به این الویت‌ها اصطلاحا Log Level گفته میشود که به شرح زیر میباشد.
    ◾️الویت 0  Trace
    گزارش‌هایی که شامل دقیق‌ترین پیام‌ها هستند. این پیام‌ها ممکن است حاوی داده‌های حساس برنامه باشند. این پیام‌ها به طور پیش فرض غیرفعال هستند و هرگز نباید در محیط تولید فعال شوند.

    ◾️الویت 1 Debug
    اطلاعات مربوط به بررسی لحظه‌ای در حین رفع خطا یا روند Debugging. این گزارش‌ها در درجه اول باید حاوی اطلاعات مفیدی برای رفع اشکال باشند و هیچ ارزش طولانی مدتی ندارند.

    ◾️الویت 2 Information
    گزارش‌هایی که جریان کلی برنامه را ردیابی می‌کنند. این Log‌ها باید چرخه درازمدت داشته باشند.

    ◾️الویت 3 Warning
    گزارش‌هایی که یک رویداد غیر عادی یا غیر منتظره را در جریان برنامه ثبت میکنند؛ اما در غیر این صورت باعث توقف اجرای برنامه نمی‌شوند.

    ◾️الویت 4 Error
    گزارش‌هایی که هنگام توقف جریان اجرای فعلی به دلیل خرابی، ثبت می‌شوند. اینها باید نشان دهنده‌ی یک شکست در فعالیت فعلی باشند، نه یک شکست در کل برنامه.

    ◾️الویت 5 Critical
    اطلاعات غیرقابل بازیابی برنامه یا خرابی سیستم که نیاز به توجه فوری دارند.

    برای فعالسازی Logging پیشفرض در Core ابتدا باید در کلاس Program، برنامه Provider مورد استفاده را مشخص کنید. اطلاعات مربوط به Log Level نمایشی برنامه در فایل AppSettingJson قرار دارد که معمولا Log Level نمایشی روی Information قرار دارد و Log هایی با الویت کمتر از Information را نمایش نمیدهد. میتوانید با تغیر در سطح الویت LogLevel اطلاعات مربوط به سطوح پایین‌تر یعنی Trace و  Debug را نیز مشاهده کنید.
    روش‌های دیگری نیز برای دسته بندی Log‌ها وجود دارند از جمله Log Category یا Log Event Id که میتوانید به سادگی از آن‌ها استفاده کنید و دسته بندی دلخواه خود را برای Log‌ها در برنامه داشته باشید.