Introduction
I had a recent task where I wanted to log events in a section of our code to our content management system. I leveraged log4net, created a custom appender,
and was logging successfully in no time.
I used this detailed tutorial to get a better grasp on log4net and
I would consider reading it a prerequisite before going through this article. Custom appenders were out of scope of that article so I thought I'd try to give an example here.
Using the code
Here are the portions of my web.config with the log4net definitions. As you can see, I have a logger node which instructs that all code
in the ACM.Certification
namespace will use the ACMAppender
appender for logging with the minimum logging level of INFO. Above the logger node, I have
my appender definition node which identifies the type (ACM.ACMAppender
) used for the appender.
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
<log4net debug="false">
<appender name="ACMAppender" type="ACM.ACMAppender">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<logger name="ACM.Certification" additivity="false">
<level value="INFO" />
<appender-ref ref="ACMAppender" />
</logger>
</log4net>
Here is my ACMAppender
class which simply implements the abstract class AppenderSkeleton
. It also uses the RenderLoggingEvent()
helper method which renders the logging event as a string using the ConversionPattern defined in the web.config above. The LogService
object
is the custom logging class for my content management system. You would replace the contents of the Append()
method with whatever
custom logging you'd want for your implementation.
public class ACMAppender : AppenderSkeleton
{
protected override void Append(LoggingEvent loggingEvent)
{
LogLevel logLevel = LogLevel.Err;
switch (loggingEvent.Level.Name)
{
case "DEBUG":
logLevel = LogLevel.Debug;
break;
case "WARN":
case "INFO":
logLevel = LogLevel.Info;
break;
case "ERROR":
logLevel = LogLevel.Err;
break;
case "FATAL":
logLevel = LogLevel.Critical;
break;
}
LogService.Log(LogNameEnum.Exception, LogCategoryEnum.BusinessLogic, logLevel, RenderLoggingEvent(loggingEvent));
}
}
And here is an example of how it's used in my code. After instantiating an ILog
object, logging is as simple as calling
the Error()
(or whatever type of log you want to record) method on the object.
public class Service : IHttpHandler
{
protected static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void ProcessRequest(HttpContext context)
{
try
{
}
catch (Exception ex)
{
log.Error(ex);
}
}
}
Hope this helps!