Okay, here goes on my solution, but be warned, my spelling is HORRIBLE:

PART ONE:  The problem
________________________________________________________________________
_________________________

Log4net does not quite do what I want it to do by default, so I had to
mess with the code.

I wanted it to have a logger that calls a doRender function which
returns a string
that is a seperated list of the object's variables.  I then wanted this
list to be 
Interprited and used differently per appender in my logger.  

PART TWO:  The solution overview, in my viewpoint
________________________________________________________________________
_________________________

I am sure there are many ways I could have accomplished this, but I
settled on the following:

Every appender that I wanted to use this DoRender would need to have
pieces of it re-defined.
Changing the code seemed foolish, so I decided to just have my solution
make appenders that
Inherit from the apender I want to change.  Then, I go in and override
or add the nessasary 
Methods to make it work.  This avoids a lot of messy situations, because
changing the code
Can have un-desirable consequences.

PART THREE:  An example
________________________________________________________________________
_________________________
First of all, let me say I get angry when people give an overview of a
solution, but no example.
It just seems like a waste of time to me.  So here is an example:

First, I made the following 3 classes in my solution:


using System;
using System.Collections;

using log4net.Filter;
using log4net.helpers;
using log4net.Layout;
using log4net.spi;

namespace WindowsApplication
{
        public abstract class AppenderSkeleton :
log4net.Appender.IAppender, log4net.spi.IOptionHandler
        {
                // Added a parameter
                protected string m_xmlFormat = null;

                // This is the meat and potatoes method I added.  It
uses the xml_format string
                // and the string DoRender returs, and basically parses
the text into
                // proper looking xml.
                protected string
RenderAdvancedXmlLoggingEvent(LoggingEvent loggingEvent) 
                {
                        string x = m_xmlFormat;
                        string y = null;
                        System.Text.StringBuilder TheNewString = new
System.Text.StringBuilder();

                        int x_pos1 = 0;
                        int x_pos2 = 0;

                        int y_pos1 = 0;
                        int y_pos2 = 0;

                        int x_part = 0;

                        string x_temp = "", y_temp = "";


                        if (m_layout == null) 
                        {
                                throw new InvalidOperationException("A
layout must be set");
                        }

                        if (m_layout.IgnoresException) 
                        {
                                string exceptionStr =
loggingEvent.GetExceptionStrRep();
                                if (exceptionStr != null &&
exceptionStr.Length > 0) 
                                {
                                        // render the event and the
exception
                                        y =
m_layout.Format(loggingEvent) + exceptionStr + SystemInfo.NewLine;
                                }
                                else 
                                {
                                        // there is no exception to
render
                                        y =
m_layout.Format(loggingEvent);
                                }
                        }
                        else 
                        {
                                // The layout will render the exception
                                y = m_layout.Format(loggingEvent);
                        }

                        if ( x != null && x != "" )
                        {
                                // x = the format string, y = our
output.
                                while (true)
                                {
                                        x_pos1 = x.IndexOf(",",x_pos2);
                                        if ( x_pos1 < 0 )
                                        {
                                                try
                                                {
                                                        x_temp =
x.Substring(x_pos2,x.Length-x_pos2);
                                                }
                                                catch ( Exception ex)
                                                {
                                                        break;
                                                }
                                        }
                                        else
                                        {
                                                x_temp =
x.Substring(x_pos2,x_pos1-x_pos2);
                                        }

                                        // Append first part of x_temp
                                        x_part = x_temp.IndexOf(")(");
                                        TheNewString.Append(
x_temp.Substring(0,x_part+1).Replace("(","<")
        
.Replace(")",">").Replace("<>","") );


                                        if ( x_temp.IndexOf("()") < 0 )
                                        {

                                                y_pos1 =
y.IndexOf("[/cr\\]",y_pos2);
                                                if ( y_pos1 < 0 )
                                                        break;
                                                y_temp =
y.Substring(y_pos2,y_pos1-y_pos2);


                                                // Append y_temp section
                                                TheNewString.Append(
y_temp );

                                                y_pos2 = y_pos1+6;
                                        }

                                        // Append last part of x_temp
                                        TheNewString.Append(
x_temp.Substring(x_part+1,(x_temp.Length-x_part-1))
        
.Replace("(","<").Replace(")",">").Replace("<>","") );

                                        if ( x_pos1 == -1 )
                                                break;
                                        x_pos2 = x_pos1+1;
                                }
                        }

                        return TheNewString.ToString();
                }

                .
                .       
                .       
                .
                .       
                .

        }
}





using System;
using System.IO;

using log4net.helpers;
using log4net.Layout;
using log4net.spi;

namespace WindowsApplication
{
        /// <summary>
        /// Sends logging events to a <see cref="TextWriter"/>.
        /// </summary>
        /// <remarks>
        /// An Appender that writes to a <see cref="TextWriter"/>.
        /// </remarks>
        public class ActiveSentryTextWriterAppender :
WindowsApplication.AppenderSkeleton
        {

                // Overirde the render to call our newly added method
above,
                //  RenderAdvancedXmlLoggingEvent(loggingEvent)
                override protected void Append(LoggingEvent
loggingEvent) 
                {
        
m_qtw.Write(RenderAdvancedXmlLoggingEvent(loggingEvent));

                        if (m_immediateFlush) 
                        {
                                m_qtw.Flush();
                        } 
                } 

                .
                .       
                .       
                .
                .       
                .
        }
}




using System;
using System.IO;
using System.Text;

using log4net.helpers;
using log4net.Layout;
using log4net.spi;

namespace WindowsApplication
{
                                                
        public class ActiveSentryFileAppender :
WindowsApplication.TextWriterAppender
        {
                // Need a new accesor to get at the value in the config
file.
                public string XmlFormat
                {
                        get { return m_xmlFormat; }
                        set { m_xmlFormat = value; }
                }

                .
                .
                .
                .
                .
                .
        }
}




Then, I can use this cool new feature in my config file as follows:

<?xml version="1.0" encoding="utf-8" ?> 
<log4net>

    <logger name="SENTIX">
                <appender-ref ref="NewFileWay"/>
                <appender-ref ref="SentryADONetAppender"/>
    </logger>
    
    <logger name="CROGERS.INFECT">
                <appender-ref ref="fileAppender"/>
    </logger>
    
        <appender name="NewFileWay"
type="WindowsApplication.ActiveSentryFileAppender, WindowsApplication">
                <param name="File" value="SentixStuff.xml" />
                
                <param name="XmlFormat" value="(Log)(),\r\n
(User)(/User),\r\n   (Machine)(/Machine),
                \r\n   (IPAddress)(/IPAddress),\r\n   (Data)(/Data),
                \r\n   (TimeStamp)(/TimeStamp),\r\n
(LogID)(/LogID),\r\n()(/Log)\r\n\r\n" />
                <param name="AppendToFile" value="true" />

                <layout type="log4net.Layout.PatternLayout">
                        <param name="ConversionPattern" value="%m" />
                </layout>
        </appender>
        .
        .
        .       
        .
        .       
        .
</log4net>





Now, in any code file where I make a new logger called SENTIX, and if it
uses a DoRender which
Returns a seprerated string list, I can just redifine parts of or add to
whichever appender type
I wish to extend the usability of!  Now that is slick!


What results from the xml appender?  Here is an example:

<Log>
   <User>bryan</User>
   <Machine>HAPPYCOMP</Machine>
   <IPAddress>129.148.33.7</IPAddress>
   <Data>![CDATA[youcanrock]</Data>
   <TimeStamp>12/22/2004 1:40:54 PM</TimeStamp>
   <LogID>34856</LogID>
</Log>


That wraps it up.





-----Original Message-----
From: Woodruff, Rodney [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, December 22, 2004 8:35 AM
To: Log4NET User
Subject: RE: DoRender Question


Chase,

Is it possible to share an overview of your solution with the list for
future reference?  Thanks.

-- Rodney

-----Original Message-----
From: Chase Rogers [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, December 22, 2004 11:00 AM
To: Log4NET User
Subject: RE: DoRender Question

Thanks Nicko, found the solution!

-----Original Message-----
From: Nicko Cadell [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, December 21, 2004 6:27 PM
To: Log4NET User
Subject: RE: DoRender Question


I'm not sure if this answers your question but...

Loggers just forward LoggingEvent objects to Appenders. Appenders render
the event to some form of output. Typically an Appender will use a
Layout object to control how the event is written as text. 

Are you logging an object as the message? Do you need to have a custom
rendering of that object for each appender? Perhaps you could give a
little example.

Cheers,
Nicko

> -----Original Message-----
> From: Chase Rogers [mailto:[EMAIL PROTECTED]
> Sent: 22 December 2004 01:06
> To: [email protected]
> Subject: DoRender Question
> 
> I have a general question: is it possible to have an overridden 
> DoRender method apply to each appender in a logger, instead of having 
> it just apply
> to the logger.   
>  
> The reason i am wandering, is because we need several different text 
> representations of an object, but to do that, we need seperate 
> Renderer methods.
>  
> This is problimatic if you want one logger to call multiple appenders,

> because each appender will get the format of only one DoRender method.
>  
> Does anyone know how to make a DoRender method apply to Appenders 
> instead of loggers?
> 

Reply via email to