You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-dev@logging.apache.org by Ron Grabowski <ro...@yahoo.com> on 2006/12/23 19:54:21 UTC

Re: XmlHierarchyConfigurator [from log4net-users]

If I wanted to add this additional snippet to my configuration which would automatically call Flush on some buffered appenders at the given interval:

<flushBufferingAppendersTimer>
    <interval value="5000" />
    <appender-ref ref="BufferingAppender1" />
    <appender-ref ref="BufferingAppender2" />
</flushBufferingAppendersTimer>

my code would look something like this (I need two classes because the Hierarchy and the way its configured are currently two seperate classes):

    // untested
    public class FlushBufferingAppendersTimerHierarchy : Hierarchy
    {
        private Timer timer = null;
        private FlushBufferingAppendersTimerXmlHierarchyConfigurator configurator;

        // this method was added to allow a custom configuration instance
        public override XmlHierarchyConfigurator CreateXmlHierarchyConfigurator(Hierarchy hierarchy)
        {
            hierarchy.ConfigurationChanged += new LoggerRepositoryConfigurationChangedEventHandler(hierarchy_ConfigurationChanged);
            configurator = new FlushBufferingAppendersTimerXmlHierarchyConfigurator(hierarchy);
            return configurator;
        }

        private void hierarchy_ConfigurationChanged(object sender, EventArgs e)
        {
            if (timer != null)
            {
                timer.Stop();
            }

            timer = new Timer();
            timer.Interval = configurator.Interval;
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            foreach (BufferingAppenderSkeleton bufferingAppender in configurator.BufferingAppendersToFlush)
            {
                bufferingAppender.Flush();
            }
        }
    }

    public class FlushBufferingAppendersTimerXmlHierarchyConfigurator : XmlHierarchyConfigurator
    {
        private AppenderCollection bufferingAppendersToFlush = new AppenderCollection();
        private double interval = 5000;

        public FlushBufferingAppendersTimerXmlHierarchyConfigurator(Hierarchy hierarchy)
            : base(hierarchy)
        {
            // empty
        }

        public override void ParseUnknownElement(XmlElement xmlElement, Hierarchy hierarchy)
        {
            if (xmlElement.LocalName == "flushBufferingAppendersTimer")
            {
                foreach (XmlNode currentNode in xmlElement.ChildNodes)
                {
                    if (currentNode.NodeType == XmlNodeType.Element)
                    {
                            // TODO: add code to parse the <interval> node
                        XmlElement appenderRef = (XmlElement) currentNode;

                        BufferingAppenderSkeleton bufferingAppender = 
                            FindAppenderByReference(appenderRef) as BufferingAppenderSkeleton;

                        if (bufferingAppender != null)
                        {
                            bufferingAppendersToFlush.Add(bufferingAppender);
                        }
                    }
                }
            }
            else
            {
                base.ParseUnknownElement(xmlElement, hierarchy);
            }
        }

        public AppenderCollection BufferingAppendersToFlush
        {
            get { return this.bufferingAppendersToFlush; }
        }

        public double Interval
        {
            get { return this.interval; }
        }
    }

You could write something similiar to automatically delete, move, compress, etc. old log files at a given interval on a different thread within log4net without the application having to worry about that.

The code is quite long :-( If things were done with plugins it would be possible to retrieve the plugin from the repository and change its properties during the application's lifetime similiar to how you can retrieve an IHttpModule by name and call methods on it:

// might appear in an admin area for an ASP.Net application
GZippedPageOutput gZippedPageOutput = 
    (GZippedPageOutput)Context.ApplicationInstance.Modules["GZippedPageOutput"];
gZippedPageOutput.CompressionLevel = 2;

// might appear on an admin screen for your application
FlushBufferingAppendersPlugin flusher = 
    (FlushBufferingAppendersPlugin)LogManager.GetRepository().PluginMap["FlushBufferingAppendersPlugin"];
// calls Stop, sets Timer.Interval to the new value, then calls Start
flusher.SetInterval(10000);

The plugin architecture would allow you to add multiple plugins (compress old log files, flush buffers at a given internval, retrieve logging statistics, etc.) and easily retrieve them by name. Going back my recent post on plugins...I can't figure out a good way to allow plugins to hook into the configuration process parse the raw configuration file.

Comments?


----- Original Message ----

From: Igor Trofimov <ia...@gmail.com>

To: Log4NET User <lo...@logging.apache.org>

Sent: Friday, December 22, 2006 2:08:57 AM

Subject: Re: XmlHierarchyConfigurator



Yes! It would be great!

 And what about this small modification? :)



 

 2006/12/22, Ron Grabowski <ro...@yahoo.com>: The call to SetParameter (XmlHierarchyConfigurator.cs:185) in the foreach loop inside the Configure method could be replaced with a call to ParseUnknownElement: 



protected virtual ParseUnknownElement(XmlElement xmlElement, Hierarchy hierarchy)

{

SetParameter(xmlElement, hierarchy);

}



to match ParseLogger, ParseRenderer, etc. That would allow you do extend XmlHierarchyConfigurator and do custom processing on user defined top level elements. The default behavior of calling SetParameter would remain the same. 



----- Original Message ----

From: Igor Trofimov <ia...@gmail.com>

To: Log4NET User <log4net-user@logging.apache.org >

Sent: Sunday, December 17, 2006 1:37:21 PM

Subject: Re: XmlHierarchyConfigurator



Well, i want to add recognition of my specific elements in hierarchy

configuration, similar to <logger>.

And this elements can contain <appender-ref> elements (just as logger do) 

with reference to some appender - so, i can't use default capabilities of

SetParameter - there can't be sutable add-method for "appender-ref".



---------------

You wrote to "Log4NET User" < log4net-user@logging.apache.org> on Sun, 17 Dec

2006 10:02:22 -0800 (PST):



RG> XmlHierarchyConfigurator seems like a fairly complex class that was

RG> designed to parse a particular file structure without much thought for 

RG> extensibility (its probably not a good thing to encourage people to use

RG> their own slightly different configuration file structure). Take the

RG> SetParameter method for example...making that virtual (~250 lines) 

RG> would allow you to change how parameters are set but my guess is that

RG> you'd still need to copy and paste a lot of that code to get your

RG> override to perform similiar to the base method.

 

RG> What parts of XmlHierarchyConfigurator do you want to override?