logging-log4net-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ron Grabowski <rongrabow...@yahoo.com>
Subject RE: LayoutSkeleton Help
Date Fri, 16 Sep 2005 00:01:32 GMT
I was able to reproduce your exception text outputing after the xml was
written. I fixed it by setting the IgnoresException propety to false:

public class GSIEventLayout : LayoutSkeleton
{
 public override void ActivateOptions()
 {
  IgnoresException = false;
 }

 public override void Format(TextWriter writer, LoggingEvent
loggingEvent)
 {
  writer.Write("<GSIEventLog>");
  writer.Write(Environment.NewLine);
  writer.Write(" <Domain>{0}</Domain>", loggingEvent.Domain);
  writer.Write(Environment.NewLine);
  writer.Write("</GSIEventLog>");
  writer.WriteLine();
 }
}

Layouts are optional and not all appenders require them. Appenders
should know how to process both messages and exceptions. If a layout
does not deal with an exception (IgnoreException=true), then the
appender will process it.

Log4net has the ability to define custom renderers for objects via the
renderer node in the log4net config file:

 <log4net>
  <renderer 
   renderingClass="Company.Project.Logging.SqlExceptionRenderer" 
   renderedClass="System.Data.SqlClient.SqlException" />
  ...
 </log4net>

Its possible that someone would want to render certain exceptions in a
special way. For example someone may want to only output the ErrorCode
property of an HttpException instead of calling ToString on it.

When you extend LayoutSkeleton, the default behavior is for your layout
to not process the exception and let the appender handle it. In the
case of a RollingFileAppender, the base AppenderSkeleton checks if
there are any custom renderers setup and if so delegates the rendering
of the exception. If there aren't any custom renderers,
AppenderSkeleton uses the DefaultRenderer which basically calls
ToString on the exception. That's what is generating the exception
message in your log file.

Why does the constructor of the commonly used PatternLayout layout keep
the default value of IgnoresException=true? Doesn't this mean that the
exception message will appear after PatternLayout outputs its text? The
short answer is that the ExceptionPatternConverter takes responsibility
for handling the exception which in turn notifies the parent layout and
in turn notifies the parent appender. The part I'm still fuzzy on is
how the ExceptionPatternConverter's IgnoreException property gets
bubbled back up to the layout then to the appender which then knows to
_not_ output the exception.

--- Jon Finley <jdf@gksys.com> wrote:

> Sure thing:
> 
> 		<appender name="RollingLogFileAppender2"
> type="log4net.Appender.RollingFileAppender">
> 			<param name="File" value="Test1-log2.txt" />
> 			<param name="AppendToFile" value="true" />
> 			<param name="MaxSizeRollBackups" value="5" />
> 			<param name="MaximumFileSize" value="2MB" />
> 			<param name="RollingStyle" value="Size" />
> 			<param name="StaticLogFileName" value="true" />
> 			<layout type="log4net.Ext.GSI.GSIEventLayout" />
> 		</appender>
> 
> The complete layout class is:
> using System;
> using System.IO;
> using log4net.Core; 
> using log4net.Layout; 
> 
> namespace log4net.Ext.GSI
> {
> 	public class GSIEventLayout : LayoutSkeleton
> 	{
> 		private PatternLayout m_nestedLayout;
> 
> 		public override void ActivateOptions()
> 		{
> 			this.IgnoresException = true;
> 			this.Footer = "";
> 			this.Header = "";
> 		}
> 
> 		public override void Format(TextWriter writer, LoggingEvent
> loggingEvent)
> 		{
> 			writer.Write("<GSIEventLog>");
> 	        writer.Write("<Domain>" + loggingEvent.Domain +
> "</Domain>");
> 		    writer.Write("<ClassName>" +
> loggingEvent.LocationInformation.ClassName + "</ClassName>");
> 	        writer.Write("<RenderedMessage>" +
> loggingEvent.RenderedMessage + "</message>");
> 			writer.Write("<HostName>" +
> loggingEvent.LookupProperty("log4net:HostName").ToString()  +
> "</HostName>");
> 			writer.Write("<Identity>" + loggingEvent.UserName +
> "</Identity>");
> 			writer.Write("<LoggerName>" +
> loggingEvent.LoggerName + "</LoggerName>");
> 			writer.Write("<ThreadName>" +
> loggingEvent.ThreadName + "</ThreadName>");
> 			writer.Write("<TimeStamp>" + loggingEvent.TimeStamp
> + "</TimeStamp>");
> 			writer.Write("<EventId>" +
> loggingEvent.LookupProperty("EventId").ToString() + "</EventId>");
> 			writer.Write("<Message2>" +
> loggingEvent.LookupProperty("Message").ToString() + "</Message2>");
> 			writer.Write("<AppUser>" +
> loggingEvent.LookupProperty("AppUser").ToString() + "</AppUser>");
> 			writer.Write("<SourceId>" +
> loggingEvent.LookupProperty("SourceId").ToString() + "</SourceId>");
> 	        writer.Write("<ExMessage>" +
> loggingEvent.ExceptionObject.Message + "</ExMessage>");
> 		    writer.Write("<ExStackTrace>" +
> loggingEvent.ExceptionObject.StackTrace + "</ExStackTrace>");
> 			writer.Write("</GSIEventLog>");
> 
> 			writer.WriteLine();
> 		}
> 
> 		public PatternLayout PatternLayout 
> 		{
> 			get { return m_nestedLayout; }
> 			set { m_nestedLayout = value; }
> 		}
> 	}
> }
>  
> 
> -----Original Message-----
> From: Ron Grabowski [mailto:rongrabowski@yahoo.com] 
> Sent: Thursday, September 15, 2005 4:04 PM
> To: Log4NET User
> Subject: RE: LayoutSkeleton Help
> 
> Could you post the complete appender node that is using this layout? 
> 
> --- Jon Finley <jdf@gksys.com> wrote:
> 
> > That line is loading the exception text inside the appropriate XML 
> > element.
> > 
> > Using UltraEdit to view the results.
> > 
> > If every element from the layout is removed, the only thing that
> shows 
> > up is the exception text.
> > 
> > If elements are removed one at a time, I see the correct XML but
> still 
> > get the exception text appended to the output.
> > 
> > Jon
> > 
> > -----Original Message-----
> > From: Ron Grabowski [mailto:rongrabowski@yahoo.com]
> > Sent: Thursday, September 15, 2005 3:41 PM
> > To: Log4NET User
> > Subject: RE: LayoutSkeleton Help
> > 
> > What about this line:
> > 
> >  writer.Write("<RenderedMessage>" + loggingEvent.RenderedMessage + 
> > "</message>");
> > 
> > Are you viewing the output in a browser or with a program like 
> > Notepad?
> > 
> > Have you tried removing all the elements and adding each one back
> one 
> > by one starting from the bottom?
> > 
> > --- Jon Finley <jdf@gksys.com> wrote:
> > 
> > > No, same issue Leo.  Thanks for the catch though, I'm sure it
> saved
> > me
> > > from some troubleshooting down the road. ;-)
> > >  
> > > Jon
> > > 
> > > 
> > >   _____
> > > 
> > > From: Hart, Leo [mailto:Leo.Hart@FMR.COM]
> > > Sent: Thursday, September 15, 2005 3:16 PM
> > > To: Log4NET User
> > > Subject: RE: LayoutSkeleton Help
> > > 
> > > 
> > > It looks like you are missing a "<" in this line:
> > > 
> > > writer.Write("<ClassName>" +
> > > loggingEvent.LocationInformation.ClassName + "/ClassName>");
> > > 
> > > Does that fix the problem?
> > >  
> > > 
> > > -----Original Message-----
> > > From: Jon Finley [mailto:jdf@gksys.com]
> > > Sent: Thursday, September 15, 2005 4:13 PM
> > > To: 'Log4NET User'
> > > Subject: LayoutSkeleton Help
> > > 
> > > 
> > > 
> > > Hi,
> > > 
> > > I have a very simple Layout based on LayoutSkeleton that
> generates
> > XML
> > > using the LoggingEvent values.  However; the exception text
> always 
> > > prints at the end of the XML.  Is there a way to turn this off?
> > > 
> > > My Format routine is as follows:
> > > 
> > >                 public override void Format(TextWriter writer, 
> > > LoggingEvent
> > > loggingEvent)
> > >                 {
> > >                         writer.Write("<GSIEventLog>");
> > >                 writer.Write("<Domain>" + loggingEvent.Domain + 
> > > "</Domain>");
> > >                     writer.Write("<ClassName>" + 
> > > loggingEvent.LocationInformation.ClassName + "/ClassName>");
> > >                 writer.Write("<RenderedMessage>" + 
> > > loggingEvent.RenderedMessage + "</message>");
> > >                         writer.Write("<HostName>" +
> > > loggingEvent.LookupProperty("log4net:HostName").ToString()  + 
> > > "</HostName>");
> > >                         writer.Write("<Identity>" + 
> > > loggingEvent.UserName + "</Identity>");
> > >                         writer.Write("<LoggerName>" + 
> > > loggingEvent.LoggerName + "</LoggerName>");
> > >                         writer.Write("<ThreadName>" + 
> > > loggingEvent.ThreadName + "</ThreadName>");
> > >                         writer.Write("<TimeStamp>" + 
> > > loggingEvent.TimeStamp
> > > + "</TimeStamp>");
> > >                         writer.Write("<EventId>" +
> > > loggingEvent.LookupProperty("EventId").ToString() +
> "</EventId>");
> > >                         writer.Write("<Message2>" +
> > > loggingEvent.LookupProperty("Message").ToString() +
> "</Message2>");
> > >                         writer.Write("<AppUser>" +
> > > loggingEvent.LookupProperty("AppUser").ToString() +
> "</AppUser>");
> > >                         writer.Write("<SourceId>" +
> > > loggingEvent.LookupProperty("SourceId").ToString() +
> 
=== message truncated ===


Mime
View raw message