كيف يمكنك تكوين وتمكين log4net لتجميع مكتبة فئة مستقلة؟

StackOverflow https://stackoverflow.com/questions/1028375

  •  06-07-2019
  •  | 
  •  

سؤال

خلفية

أنا أكتب تجميعًا لمكتبة الفصل الدراسي في C# .NET 3.5 والذي يُستخدم للتكامل مع التطبيقات الأخرى بما في ذلك الأدوات التجارية الجاهزة (COTS) التابعة لجهات خارجية.لذلك، في بعض الأحيان سيتم استدعاء مكتبة الفئات هذه بواسطة التطبيقات (EXEs) التي أتحكم فيها بينما في أحيان أخرى سيتم استدعاؤها بواسطة مكتبات DLL أخرى أو التطبيقات التي أقوم بها لا يتحكم.

الافتراضات

  • أنا أستخدم C# 3.0 و.NET 3.5 SP1 وVisual Studio 2008 SP1
  • أنا أستخدم log4net 1.2.10.0 أو أحدث

قيود

أي حل يجب أن:

  • السماح لمكتبة الفصل بتمكين التسجيل وتكوينه عبر ملف التكوين الخاص بها، إذا لم يقم تطبيق الاستدعاء بتكوين log4net.
  • السماح لمكتبة الفصل بتمكين التسجيل وتكوينه عبر تكوين تطبيقات الاتصال، إذا كانت تحدد معلومات log4net

أو

  • السماح لمكتبة الفصل بتمكين التسجيل وتكوينه باستخدام ملف التكوين الخاص بها في جميع الأوقات.

مشكلة

عندما يتم استدعاء مكتبة الفصل المستقلة الخاصة بي بواسطة ملف DLL أو تطبيق لا أتحكم فيه (مثل أداة COTS التابعة لجهة خارجية) والتي لا تحدد معلومات تكوين log4net، فإن مكتبة الفصل الخاصة بي غير قادرة على القيام بأي من عمليات التسجيل الخاصة بها .


سؤال

كيف يمكنك تكوين وتمكين log4net لتجميع مكتبة فئة مستقلة بحيث يتم تسجيلها بغض النظر عما إذا كان تطبيق الاتصال يوفر تكوين log4net؟

هل كانت مفيدة؟

المحلول 2

الحل 1

الحل للمجموعة الأولى من القيود هو التفاف ملف log4net.LogManager في فئة LogManager المخصصة الخاصة بك مثل يعقوب, جيروين, ، و ماكوافلستيكس اقترحت (انظر الكود أدناه).

لسوء الحظ، ال log4net.LogManager الفئة ثابتة وC# لا تدعم الوراثة الثابتة، لذلك لا يمكنك الوراثة منها وتجاوز طريقة GetLogger.لا يوجد الكثير من الأساليب في log4net.LogManager الطبقة ومع ذلك، لذلك هذا هو بالتأكيد احتمال.

العيب الآخر لهذا الحل هو أنه إذا كان لديك قاعدة تعليمات برمجية موجودة (وهو ما أفعله في حالتي)، فسيتعين عليك استبدال كافة الاستدعاءات الموجودة إلى log4net.LogManager بفئة التغليف الخاصة بك.ومع ذلك، ليست مشكلة كبيرة مع أدوات إعادة الهيكلة اليوم.

بالنسبة لمشروعي، تفوقت هذه العيوب على فوائد استخدام تكوين التسجيل الذي يوفره تطبيق الاتصال، لذا اخترت الحل 2.

شفرة

أولاً، أنت بحاجة إلى فئة مجمعة LogManager:

using System;
using System.IO;
using log4net;
using log4net.Config;

namespace MyApplication.Logging
{
    //// TODO: Implement the additional GetLogger method signatures and log4net.LogManager methods that are not seen below.
    public static class LogManagerWrapper
    {
        private static readonly string LOG_CONFIG_FILE= @"path\to\log4net.config";

        public static ILog GetLogger(Type type)
        {
            // If no loggers have been created, load our own.
            if(LogManager.GetCurrentLoggers().Length == 0)
            {
                LoadConfig();
            }
            return LogManager.GetLogger(type);
        }

        private void LoadConfig()
        {
           //// TODO: Do exception handling for File access issues and supply sane defaults if it's unavailable.   
           XmlConfigurator.ConfigureAndWatch(new FileInfo(LOG_CONFIG_FILE));
        }              
}

ثم في الفصول الدراسية الخاصة بك، بدلاً من:

private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

يستخدم:

private static readonly ILog log = LogManagerWrapper.GetLogger(typeof(MyApp));

الحل 2

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

من وثيقة أباتشي log4net:

"قد يختار التجميع استخدام مستودع تسجيل مسمى بدلاً من المستودع الافتراضي.يؤدي هذا إلى فصل تسجيل التجميع عن باقي التطبيق بشكل كامل.يمكن أن يكون هذا مفيدًا جدًا لمطوري المكونات الذين يرغبون في استخدام log4net لمكوناتهم ولكنهم لا يريدون أن يطلبوا أن تكون جميع التطبيقات التي تستخدم مكوناتهم على علم بـ log4net.وهذا يعني أيضًا أن تكوين تصحيح الأخطاء الخاص بهم منفصل عن تكوين التطبيقات.يجب أن يحدد التجميع RepositoryAttribute لتعيين مستودع التسجيل الخاص به."

شفرة

لقد وضعت الأسطر التالية في ملف AssemblyInfo.cs الخاص بمكتبة صفي:

// Log4Net configuration file location
[assembly: log4net.Config.Repository("CompanyName.IntegrationLibName")]
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "CompanyName.IntegrationLibName.config", Watch = true)]

    

مراجع

نصائح أخرى

ربما يمكنك ترميز شيء ما حول XMLConfigurator فصل:

public static class MyLogManager
{
    // for illustration, you should configure this somewhere else...
    private static string configFile = @"path\to\log4net.config";

    public static ILog GetLogger(Type type)
    {
        if(log4net.LogManager.GetCurrentLoggers().Length == 0)
        {
            // load logger config with XmlConfigurator
            log4net.Config.XmlConfigurator.Configure(configFile);
        }
        return LogManager.GetLogger(type);
    }
}

ثم في الفصول الدراسية الخاصة بك، بدلاً من:

private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

يستخدم:

private static readonly ILog log = MyLogManager.GetLogger(typeof(MyApp));

بالطبع، سيكون من الأفضل جعل هذه الفئة خدمة وتكوينها ديناميكيًا باستخدام حاوية IoC التي تختارها، لكن هل فهمت الفكرة؟

يحرر: تمت الإشارة إلى مشكلة Count() الثابتة في التعليقات.

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

log4net.LogManager.GetCurrentLoggers().Count()

يمكنك بعد ذلك على سبيل المثال استخدام XmlConfigurator لتحميل التكوين الافتراضي من ملف:

log4net.Config.XmlConfigurator.Configure(configFile)

يمكنك إجراء التهيئة في مُنشئ ثابت أو عادي.

class Sample
{
    private static readonly log4net.ILog LOG;

    static Sample()
    {
        if (log4net.LogManager.GetCurrentLoggers().Count() == 0)
        {
            loadConfig();
        }
        LOG = log4net.LogManager.GetLogger(typeof(Sample));

    }

    private static void loadConfig()
    {
        /* Load your config file here */
    }

    public void YourMethod()
    {
       LOG.Info("Your messages");
    }
}

في مكتبة الفصل المستقلة الخاصة بك، لديك ملف مفرد يقوم بتحميل ملف log4net ملف التكوين باستخدام log4net.Config.XmlConfigurator.

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

يمكنك العثور على وصف جيد هنا:سجل4نيت:دليل البدء السريع

كما توضح المقالة، لتكوينه لكل تجميع على حدة، قم بإنشاء ملف XML لتجميعك المسمى AssemblyName.dll.log4net ووضع كود XML التالي فيه:

<?xml version="1.0" encoding="utf-8"?>
<log4net debug="false">
   <appender name="XmlSchemaFileAppender" type="log4net.Appender.FileAppender">
      <file value="AppLog.xml" />
      <appendToFile value="true" />
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <layout type="log4net.Layout.XmlLayout" />
   </appender>

   <root>
      <level value="WARN" />
      <appender-ref ref="XmlSchemaFileAppender" />
   </root>
</log4net>

ويصف أيضًا، لإنشاء مثيل لمسجل جديد، ما عليك سوى الإعلان عنه كمتغير للفئة بأكملها على النحو التالي:

public class LogSample
{
    private static readonly log4net.ILog Log 
            = log4net.LogManager.GetLogger(typeof(LogSample));
    // Class Methods Go Here...
}

يمكنك بعد ذلك استخدام المتغير الخاص Log داخل صفك مثل:

Log.Info("Sample message");

وبالمثل يمكنك استخدام Log.Error("Error occurred while running myMethod", ex) لتسجيل الأخطاء مع تفاصيل الاستثناء.

وما وجدته هو ما يلي:

  • لا تنسى الاتصال log4net.Config.XmlConfigurator.Configure(); لتفعيل التكوين الخاص بك

  • إذا كنت تريد معرفة مسار الملف (الملفات) المكتوبة، هنا بعض التعليمات البرمجية كيفية الحصول عليها من Log4Net

آمل أن يساعد هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top