NLog: القواعد والمرشحات

NLog: القواعد والمرشحات


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


كيفية تكوين NLog


وسنبدأ بتذكير قليل بما يمكننا القيام به من خلال تكوين NLog. في أبسط الحالات ، يكون هذا التكوين ملف 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"> <targets> <target name="target1" xsi:type="ColoredConsole" layout="Access Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="red"/> </target> <target name="target2" xsi:type="ColoredConsole" layout="Common Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="green"/> </target> <target name="target3" xsi:type="ColoredConsole" layout="Yellow Log|${level:uppercase=true}|${logger}|${message}"> <highlight-row condition="true" foregroundColor="yellow"/> </target> </targets> <rules> <logger name="*" minlevel="Warn" writeTo="target1,target2,target3" /> </rules> </nlog> 

يمكنك تنزيل هذا الملف بسطر واحد من التعليمات البرمجية:


 LogManager.Configuration = new XmlLoggingConfiguration("NLog.config"); 

ماذا يمكننا أن نفعل به؟ يمكننا ضبط عدة أجهزة استقبال للرسائل (الهدف) على القاعدة:


 <rules> <logger name="*" minlevel="Warn" writeTo="target1,target2,target3" /> </rules> 

يمكننا تحديد مستويات تسجيل هذه القاعدة المطبقة:


 <rules> <logger name="*" minlevel="Warn" writeTo="target1" /> <logger name="*" levels="Debug,Warn,Info" writeTo="target2" /> </rules> 

يمكننا تعيين مرشحات لكل قاعدة:


 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <filters defaultAction='Log'> <when condition="contains('${message}','Common')" action="Ignore" /> </filters> </logger> </rules> 

وأخيراً ، يمكننا تحديد القواعد المتداخلة:


 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <logger name="*" minlevel="Warn" writeTo="target2" /> </logger> </rules> 

حان الوقت لمعرفة كيف يعمل كل شيء.


إنشاء تكوين مسجل


عندما تطلب مثيل المسجل ،


 var commonLogger = LogManager.GetLogger("Common"); 

NLog إما يأخذ واحدة موجودة من ذاكرة التخزين المؤقت أو يخلق واحدة جديدة (انظر هنا ). في الحالة الأخيرة ، يتم أيضًا تكوين تهيئة للمسجل بالاسم المحدد. دعونا ننظر في عملية إنشائه.


باختصار ، تكوين المسجل عبارة عن سلسلة منفصلة من المستقبلات والفلاتر المقابلة لكل مستوى تسجيل ( Trace ، Debug ، Info ، Warn ، Error ، Fatal ) (انظر هنا ). الآن سأريكم كيف بنيت هذه السلاسل.


الطريقة الرئيسية المسؤولة عن إنشاء هذه السلاسل هي GetTargetsByLevelForLogger للفئة LogFactory . هذه هي الطريقة التي يعمل بها. يتم تحديد جميع القواعد المحددة في تكوين NLog بدوره. أولاً ، يتم التحقق لمعرفة ما إذا كان اسم القاعدة يطابق اسم المسجل. يمكن أن تحتوي أسماء القواعد على أحرف بدل ، مثل تلك التي نستخدمها لكائنات نظام الملفات:


  • * - تسلسل تعسفي من الشخصيات
  • ? - أي شخصية واحدة

وبالتالي ، يطابق اسم القاعدة " * " أي اسم مسجل ، ويطابق "عام Common* " جميع أدوات التسجيل التي تبدأ أسماؤها بـ "عام".


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


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


 <rules> <logger name="*" minlevel="Info" writeTo="target1" final="true"> <logger name="*" minlevel="Warn" writeTo="target2" /> </logger> </rules> 

لن تصل أي رسائل إلى target2 . لكن من الممكن كتابة شيء مثل هذا:


 <rules> <logger name="*" minlevel="Warn" writeTo="target1" final="true"> <logger name="*" minlevel="Info" writeTo="target2" /> </logger> </rules> 

نظرًا لعدم تمكين القاعدة الخارجية لمستوى Info ، فلن تنتهي سلسلة المستقبلات لهذا المستوى بالقاعدة الخارجية. لذلك ، سوف تنقسم جميع الرسائل ذات مستوى Info إلى target2 .


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


في المجموع ، التكوين للمسجل جاهز. أنه يحتوي على سلاسل من أجهزة الاستقبال مع مرشحات لكل مستوى ممكن من قطع الأشجار:


سلسلة الاستقبال


حان الوقت لنرى كيف يتم استخدام هذا التكوين.


باستخدام التكوين المسجل


لنبدأ بأشياء بسيطة. فئة Logger لها أسلوب IsXXXEnabled وخصائص IsXXXEnabled المقترنة ( IsDebugEnabled ، IsInfoEnabled ، ...). كيف تعمل؟ في الواقع ، يقومون ببساطة بالتحقق مما إذا كانت سلاسل المستقبل لمستوى معين من التسجيل تحتوي على رابط واحد على الأقل (انظر هنا ). هذا يعني أن المرشحات لا تؤثر أبدًا على قيم هذه الخصائص.


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


إليك كيفية تكوين المرشحات:


 <rules> <logger name="*" minlevel="Info" writeTo="target1"> <filters defaultAction='Log'> <when condition="contains('${message}','Common')" action="Ignore" /> </filters> </logger> </rules> 

عادة ما يحتوي المرشح على بعض الحالات المنطقية. هنا يمكنك أن تقرر ما إذا كان عامل التصفية إرجاع true أو false لكل رسالة. لكن هذا ليس كذلك. نتيجة عملهم هي قيمة النوع FilterResult . إذا تم إرجاع شرط التصفية إلى true ، تصبح نتيجة التصفية هي القيمة المحددة في سمة action (في مثالنا ، هذا هو Ignore ). إذا عادت الحالة false ، فستكون نتيجة المرشح Neutral . هذا يعني أن المرشح لا يريد أن يقرر ما يجب فعله بالرسالة.


يمكنك أن ترى كيف تتم معالجة سلسلة المتلقي هنا . لكل مستقبل ، يتم حساب نتيجة عوامل التصفية المقابلة في أسلوب GetFilterResult . إنه يساوي نتيجة التصفية الأولى التي لم يتم إرجاعها. هذا يعني أنه إذا كانت بعض المرشحات تُرجع قيمة غير Neutral ، فلن يتم تنفيذ جميع المرشحات التالية.


ولكن ماذا يحدث إذا عادت جميع المرشحات Neutral ؟ في هذه الحالة ، سيتم استخدام القيمة الافتراضية. يتم تعيين هذه القيمة باستخدام سمة defaultAction لعنصر filters للقاعدة. ما رأيك هي القيمة الافتراضية ل defaultAction ؟ أنت محق إذا كنت تعتقد أن هذا Neutral . وهذا هو ، يمكن أن سلسلة التصفية بأكملها إرجاع Neutral نتيجة لذلك. في هذه الحالة ، يتصرف NLog بنفس طريقة تلقي Log . سيتم كتابة الرسالة إلى المتلقي (انظر هنا ).


كما قد تكون خمنت ، إذا IgnoreFinal عامل التصفية Ignore أو Ignore IgnoreFinal ، فلن تتم كتابة الرسالة إلى المتلقي. إذا كانت نتيجة المرشح هي Log أو LogFinal ، فسيتم تسجيل الرسالة. ولكن ما هو الفرق بين Ignore و IgnoreFinal وبين Log أو LogFinal ؟ انها بسيطة. في حالة IgnoreFinal و LogFinal يتوقف NLog عن معالجة سلسلة المستقبل ولا يكتب أي شيء إلى المستقبلات الموجودة في الروابط التالية.


استنتاج


ساعدني تحليل رمز NLog في فهم كيفية عمل القواعد والمرشحات. آمل أن تكون هذه المقالة مفيدة لك. حظا سعيدا

Source: https://habr.com/ru/post/ar450728/


All Articles