• خانه
  • وبلاگ
  • Tools
  • لاگ كردن خطاها و پيام های دلخواه در Microsoft.Net با Log4Net

لاگ كردن خطاها و پيام های دلخواه در Microsoft.Net با Log4Net

لاگ كردن خطاها و پيام های دلخواه در Microsoft.Net با Log4Net

یکی از بزرگترین ابزارهای لاگ کردن ( Logging ) که برای Microsoft .Net وجود دارد log4net است. یک استاندارد عالی برای این که چطور باید لاگ های خودمون رو تولید و نگهداری کنیم . بسیار ساده ، قدرتمند ، و قابل توسعه است. این ابزار متن باز و رایگان و دارای مستندات و قدرتمندی در جهت نحوه استفاده از آن ارائه شده ، اما این مستندات کمی دارای پیچیدگی هستند ، اما اگر شما میدانید که log4net چیست و اساسا چه کارهایی میتواند برای شما انجام میدهد و فقط نیاز به نحوه پیاده سازی و syntax  آن دارید ، این مستندات برای شما مفید هستند . این مقاله آموزشی تنها بخشی از این سیستم را به شما معرفی میکند و سعی دارد شما را با ساختار اصلی و اساس این ابزار آشنا کند.

نحوه استفاده

برای استفاده از log4net سه قدم اساسی در پیش داریم. انجام تنظیمات ، نصب ، فراخوانی . تنظیمات معمولا در فایل های app.config و web.config انجام می شوند که در ادامه به شرح کامل آن خواهیم پرداخت . حتی اگر میخواهید چندین تنظیمات مختلف داشته باشید ، میتوانید خارج از Web.Config یا App.Config در فایل های جدا تنظیمات خود را برای Logger های مختلف ذخیره کنید . نصب مجموعه ای از خطوط کد است که برای برقراری ارتباط با Logger به ترتیب فراخوانی شوند. در آخر راحت ترین بخش کار فراخوانی و استفاده از این ابزار برای log کردن است .

Logging Levels  ( سطوح لاگ گیری )

هفت سطح برای لاگ ها وجود دارد ، از واژه سطح استفاده میکنیم زیرا ترتیب آنها مهم است .

  1. OFF – هیچ چیز لاگ نشود (در کد قابل فراخوانی نیست)
  2. FATAL
  3. ERROR
  4. WARN
  5. INFO
  6. DEBUG
  7. ALL – همه چیز لاگ شود (در کد قابل فراخوانی نیست)

 

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

 

تنظیمات

راه معمول برای انجام تنظیمات log4net استفاده از فایل app.congif در windows applications ویا web.config در web Application است. برای راه اندازی log4net باید تنظیمات اندکی در فایل config به ترتیب قرار دهید. این تنظیمات به log4net می گوید که چگونه خود را پیکربندی کند. برای تغییراتی که بعدا در این تنظیمات انجام میدهید نیازی به کامپایل مجدد برنامه خود ندارید.

Root

در اولین قدم برای Config، جهت قرار دادن تنظیمات لاگر به یک Root Section نیاز دارید. اینها تنظیماتی هستند که لاگر های دیگر از لاگر Root به ارث میبرند. یکی از تنظیماتی که در Root Section قرار می گیرد ، حداقل سطح لاگ گیری است. از آنجا که همه چیز از Root به ارث برده می شود ، هیچ Appernderی هیچ پیامی را زیر حداقل سطح تایین شده لاگ نخواهد کرد. این راه بسیار ساده ای برای کنترل سریع سطح لاگ گیری در برنامه نرم افزار ما است. در مثال زیر مقدار پیشفرض INFO در نظر گرفته شده ( به این معنا که پیام های DEBUG لاگ نخواهند شد ) و ارجاع لاگ ها به دو Appender که یکی لاگ ها را درون فایل ذخیره سازی میکند و دیگری برروی پنجره نمایش Console نمایش میدهد .

<root>
  <level value="INFO"/>
  <appender-ref ref="FileAppender"/>
  <appender-ref ref="ConsoleAppender" />
</root>

 

Additional Loggers

بعضی وقت ها نیاز هست که از تکه ای از برنامه بصورت مجزا لاگ بگیریم. log4net این مورد را از قبل پیشبینی کرده و به شما اجازه میدهد فراتر از Root Logger چندین Additional logger تعریف کنید. برای مثال در کانفیگ زیر ما یک Additional logger داریم که لاگ های کلاس OtherClass را درون Console برای ما لاگ میکند .

<logger name="Log4NetTest.OtherClass">
  <level value="DEBUG"/>
  <appender-ref ref="ConsoleAppender"/>
</logger>

توجه داشته باشید که : نام لاگر باید نام کلاس + فضای نام ( NameSpace ) آن باشد و بصورت کامل درج شود. اگر میخواهید کل پیام های یک فضای نام را لاگ کنید، خیلی ساده میتوانید بجای نام کلاس نام NameSpace مورد نظر خود را قرار دهید. من به شما پیشنهاد میکنم سعی کنید از چندین Logger استفاده کنید تا نتایج مفیدتری جهت بررسی در اختیار داشته باشید .
 

ConfigSections

چون تنظیمات log4net معمولا در فایل config انجام می شود ، برای آنکه مشخص کنیم تنظیمات کجا قرار خواهند گرفت نیاز به تعریف یک Section داریم .

<configSections>
  <section name="log4net" 
    type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>

توجه داشته باشید که configSection اولین تک بعداز تگ اصلی Configurations است.

 

Appender ( تعریف کلی )

Appender نامی است برای چیزی که اطلاعات را لاگ میکند . Appender مشخص می کند که اطلاعات باید کجا لاگ شود ، چگونه لاگ شود ، و تحت چه شرایطی لاگ شود. هر Appender بر اساس اینکه قرار است اطلاعات را کجا لاگ کند پارامترها و تنظیمات مختلفی خواهد داشت . ولی همگی آنها با یک Element ثابت و پارامترهای نام و نوع شروع می شوند. نام میتواند دلخواه باشد و نوع آن بسته به این است که شما میخواهید لاگ های خود را به کجا بفرستید. در یک فایل ذخیره کنید ، ایمیل کنید ، در Database ذخیره کنید و  یا ... ، Appender های مختلفی وجود دارد که شما میتوانید لیست آنها را در اینجا ببینید.

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">

Layout

درون هر Appender باید یک Layout وجود داشته باشد که نسبت به نوع Appender شما ممکن است کمی متفاوت باشد ، اما بطور کلی پایه تمام آنها یکی است. شما به یک Type نیاز دارید که مشخص می کند که اطلاعات چگونه باید نوشته شوند. انتخاب های مختلفی وجود دارد ، یکی از مواردی که پیشنهاد میکنم حتما استفاده کنید pattern layout type است ، زیرا به شما اجازه میدهد که نحوه نوشته شدن لاگ را مشخص کنید. اگر شما از نوع pattern layout استفاده کنید ، باید درون Layout یک تگ به نام conversionpattern تعریف کنید که همان الگویی است که نحوه نوشته شدن لاگ را تعیین میکند . در ادامه اطلاعات کامل تری درمورد conversion patterns به شما خواهم داد ، اما فعلا در زیر مثالی برای نحوه تعریف تگ Layout با نوع pattern layout خواهیم داشت :

<layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger [%ndc] 
    - %message%newline"/>
</layout>
Conversion Patterns

همانطور که در زیر گفته شده، conversion pattern برای تعریف نحوه نگارش لاگ ها در pattern layout استفاده می شود. برای ساخت conversion pattern کلمات کلیدی مختلفی جهت نمایش اطلاعات مختلف مثل تاریخ و زمان و ... استفاده می شوند. در اینجا به شرح برخی از موارد مهم و کاربردی آن می پردازیم. شما میتوانید لیست کاملی از این کلمات کلیدی را در مستندات log4net پیدا کنید.

  • %date : تاریخ جاری را بر اساس اطلاعات زمان محلی چاپ می کند. این تاریخ میتواند با استفاده از آکولاد و یک الگو مانند : %date{MMMM dd, yyyy HH:mm:ss, fff} تغییر شکل داده شود. اگر چه پیشنهاد می شود که برای کارایی بهتر از یکی از formatter های خود log4net مانند (ABSOLUTE, DATE, ISO8601) استفاده شود.
  • %utcdate : این modifier هم همانند %date است تنها با این تفاوت که تاریخ آن بصورت تاریخ جهانی ثبت می شود .
  • %exception : اگر یک Exception درون لاگ پاس داده شود Exception Message نوشته می شود و بعداز آن مکان نما جهت ادامه به خط بعد می رود، اگر هیچ Exceptionی جهت لاگ شدن پاس داده نشود، این modifier درنظر گرفته نمی شود و مکان نما هم به خط بعد منتقل نخواهد شد. این modifier معمولا در آخر یک لاگ قرار میگیرد و بهتر است قبل از آن با استفاده از modifier بعدی یک خط جدید ایجاد کنید تا لاگ شما خوانایی بیشتری داشته باشد.
  • %newline : با استفاده از این modifier میتوانید به خط بعد بروید و ادامه لاگ خود را در خط بعد بنویسید.
  • %level : این modifier همان سطحی را که شما برای لاگ کردن رویداد خود انتخاب کرده اید نمایش می دهد مثل : ( DEBUG , INFO , WARN و ... )
  • %message : این همان پیامی است که شما برای لاگ شدن ارسال می کنید.
  • %timestamp : این یک شماره از زمان اجرای برنامه به میلی ثانیه است.
  • %thread : این modifier نام thread جاری را برای شما بر میگرداند، در صورتی که therad شما دارای نام نباشد شماره آن لاگ خواهد شد.

بعداز این موارد چند مورد بسیار کاربردی دیگر وجود دارد . اما باید با احتیاط از آنها استفاده کرد زیرا برروی performance دارد و می تواند موجب کاهش سرعت نرم افزار شما شود ، این موارد شامل :

  • %identity : این modifier با استفاده از متد Principal.Identity.Name میتواند UserName کاربری که درحال استفاده است را در اختیاد ما قرار دهد.
  • %location : بصورت فوق العاده ای در مواردی که شما درحال Debug هستید کاربرد دارد، به شما میگوید که این لاگ در کدام خط در کدام متد و  ... انجام شده است، اگرچه زمانی که برنامه را کامپایل میکنید درصورتی که سیستم بتواند به کدهای کامپایل شده دسترسی پیدا کند این مقادیر نمایش داده خواهند شد.
  • %line : شماره خطی را که لاگ در آن انجام شده را بر میگرداند ( به مشکلات استفاده از location مراجعه کنید )
  • %method : نام متدی که لاگ در آن انجام شده را برمیگرداند ( به مشکلات استفاده از location مراجعه کنید )
  • %username : این modifier مقدار WindowsIdentity را برمیگرداند.
     

هر یک از کلمات کلیدی که در بالا توضیح دادیم میتوانند بصورتی قالب بندی شودند که پهنای مشخصی داشته باشند. برای رسیدن به یک پهنای دلخواه ممکن است کاراکترهای آن حذف یا در ابتدا یا انتهای آن space اضافه شود . ساده ترین نحوه انجام این کار اضافه کردن یک عدد بین نام modifier و % است. در زیر به شرح این Modifier ها می پردازیم :

  • X : حداقل تعداد کاراکتر ها را مشخص میکند. هرچیزی که کاراکتر کمتری داشته باشد ، در سمت چپ آن space قرار خواهد گرفت تا به طول مشخص شده برسد. بطور مثال :  %25message مقدار "My Custom Message            " برای شما برمیگرداند .
  • -X : مثل بالایی است با این تفاوت که Space را در سمت راست رشته اضافه میکند. مثال :  %-25message مقدار "            My Custom Message" برای شما برمیگرداند .
  • .X : حداکثر تعداد کاراکتر را مشخص میکند. مهمترین نکته ای که در مورد این modifier وجود دارد این است که درصورتی که طول رشته از حداکثر مجاز بیشتر باشد از ابتدای رشته حذف میکند. مثال : اگر رشته ما "Error Message"  باشد و modifier ما %.10message مقدار خروجی "or Message" خواهد بود .

شما میتوانید بصورت ترکیبی از modifier های بالا استفاده کنید بصورت مثال : %10.20message که اگر پیام کتر از 10 کاراکتر داشت در سمت چپ آن space قرار میدهد و یا در صورتی که بیشتر از 20 کاراکتر بود از ابتدای آن حذف می کند.

Filters

فیلترها بخش بسیار مهم دیگری از هر Appender هستند. با استفاده از یک فیلتر شما میتوانید مشخصی کنید کدام سطح لاگ شود و یا حتی تعیین کنید تنها درصورت وجود کلمه ای خاص درون message لاگ شود. فیلترها میتوانند با یکدیگر ترکیب یا جفت شوند، اما شما باید در انجام اینکار احتیاط کنید. زمانی که یک message با شرایط یک فیلتر جور می شود لاگ شده و پردازش آن فیلتر تمام می شود. اگر شما درحال ساخت یک فیلتر ترکیبی هستید به ترتیب آن توجه کنید ، زیرا ترتیب آنها مهم است و فیلتر برروی یک message به ترتیب اعمال می شود.

 

String match filter

با استفاده از string match filter  در صورت وجود يك كلمه كليدي درون اطلاعاتي كه در حال لاگ شدن هستند ، لاگ انجام مي شود. شما مي توانيد از چند String match filter بصورت تركيبي استفاده كنيد. در این شرایط فیلترها با هم Or خواهند شد. تا زمانی که شرایط یکی از فیلترها با اطلاعات لاگ برقرار شود، فیلتر به ترتیب کلمات را بررسی میکند. نكته مهم اين است اگر لاگ با فیلتر تطبيق نداشت و كلمه در لاگ پيدا نشد آن لاگ به فيلتر بعدي ارسال مي شود و در آخر هم اگر با فيلتر آخر هم تطبيق نداشت باز هم از رده خارج نمي شود و لاگ خواهد شد مگر اينكه در انتهاي تمام فيلتر ها از deny all filter استفاده كنيم تا اگر اطلاعات با هيچكدام از فيلترها تطبيق نداشت از لاگ شدن آن جلوگيري شود. در ادامه Deny All Filter بيشتر شرح خواهيم داد. در زير مثالي از String Match Filter وجود دارد :

<filter type="log4net.Filter.StringMatchFilter">
  <stringToMatch value="test" />
</filter>
LevelRangeFilter

یک Level range Filter تعیین میکند که تنها لاگ هایی که در محدوده تعیین شده هستند ثبت شوند. این محدوده شامل خود سطح تعیین شده هم می باشد. در مثال زیر رویدادهایی که لاگ خواهند شد : INFO , WARN , ERROR , FATAL خواهند بود و DEBUG داخل محدوده تعیین شده نیست. نیازی نیست بعداز این از Deny all filter استفاده کنید.

<filter type="log4net.Filter.LevelRangeFilter">
  <levelMin value="INFO" />
  <levelMax value="FATAL" />
</filter>
LevelMatchFilter

این فیلتر هم همانند Level range filter کار میکند، اما تنها یک سطح از لاگها را جهت ثبت مشخص میکند. این فیلتر لاگ هایی را که در این سطح نیستند deny نمیکند و شما باید بعداز این فیلتر حتما از deny all filter استفاده کنید.

<filter type="log4net.Filter.LevelMatchFilter">
  <levelToMatch value="ERROR"/>
</filter>
DenyAllFilter

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

<filter type="log4net.Filter.DenyAllFilter" />

انواع Appender ها

هریک از انواع Appender ها بسته به اینکه قرار است کجا داده ها را ارسال کند، نحوه پیاده سازی مشخصی دارند. مشکلترین و پیچیده ترین آنها، آن Apperder ها آنهايي هستند که اطلاعات را درون database ذخیره میکنند. در اینجا چند مورد از Appender هایی که به نظر من کاربرد بیشتری دارند را برای شما نام خواهیم برد. البته با ( copy & paste ) از نمونه کدهایی که در سایت ها وجود دارد نباید مشکلی وجود داشته باشد. در سایت log4net نمونه های بسیار فوق العاده ای از انواع مختلف Appenderها وجود دارد. در اینجا هم چند مورد از این نمونه ها آورده شده که تفاوتی با مثال های اصلی در مستندات log4net ندارد. من معمولا این مثال ها را کپی و آنها را همانطور که میخواهم ویرایش میکنم .