Click here to Skip to main content
13,899,680 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

47.5K views
1.8K downloads
16 bookmarked
Posted 23 Jul 2010
Licenced CPOL

WCF Appender for log4net

, 23 Jul 2010
Rate this:
Please Sign up or sign in to vote.
Easy way to set log4net appender for WCF
Log_Result.JPG

Introduction

One of the things that is really important at Log4Net is the ability to set a custom appender in a simple and easy way, so it would meet your needs. Most of the logs are writing to database so typically it's easy to query them later, but what if you want to obtain the logs from Q/A team in your work directly to your home online over the internet? Imagine that you tell them: "run the section with the bug again" while on the screen you see the log at real time...

Background

When I wanted to write custom appender for WCF service, I thought to myself , "it's simple", and tried to find a simple example of WCF appender on the internet. But to my surprise, I found few samples and they were very complicated and not so easy, so I started to examine how to write custom appender, and I encountered this good post and realized how easy it is. And after I implemented it, I'm here to share this with you...

This post is for beginners. Intentionally, the code is as short as possible and clear. It's not the best way to do it (in the real app, you will write it with more detailed message, formatting message, and use threading for service and more...), but the purpose of this post is to show the base steps and make it as clear as possible.

Also, on purpose I avoided using automatic 'Add Service Reference' way to set proxy to service, because I want to show exactly what is going on and so you can easily change or adjust the code to understand the sample.

So, How to Write Custom Appender?(or What's Really In This Class...)

In order to write custom appender, there are two ways: the first is to implement the log4net.Appender.IAppender interface, but the second way much more simple and in most cases you'll find it appropriate to your needs. In the second way, you need to derive your custom appender's class from the abstract class log4net.Appender.AppenderSkeleton and implement one method called Append. Here is my class:

public class WcfAppender : AppenderSkeleton
{
}

This class is used as Wcf appender and so it will contain the whole infrastructure to communicate with the service. Fortunately, it's only one static field that holds the channel to the log service:

static IServiceLogger Service;  

As I mentioned, this class needs to implement the 'Append' method:

protected override void Append(LoggingEvent loggingEvent)
{
    string message = string.Format("{0}, {1}", loggingEvent.Level.DisplayName,
                     loggingEvent.RenderedMessage);
    Service.NewLog(message);
}

The loggingEvent contains all the data collected by the loggers, here I choose the data I want and make it to one string and send it to WCF service (in the real app, it makes more sense to send Log class or something like that instead of compress all data to one string).

Now we have the WCF appender class. Not simple??? But the work is not yet done. We need to tell the log4net to instantiate this class as our appender, and that is done through App.config file.

Configure the App.config

We can configure as many loggers as we want, but for this sample we set only one:

<logger name="WcfLogger">
   <appender-ref ref="WcfAppender" />
</logger>

The logger is responsible to collect all the messages and pass them to appenders. Appender is responsible to write the messages to a specific location. Logger can pass the messages to many appenders but we set only one appender for this logger. We can set as many appenders as we want, but in this sample we used only one appender:

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

The 'type' tells the log4net which class is used as that appender. When logger wants to pass the messages to appender named WcfAppender, it checks which class needs to instantiate (in this case WcfAppenderLog4net.WcfAppender) and which assembly holds it (in this case 'WcfAppenderLog4net') and instantiate that appender.

For some reason, when we using log4net, it didn't know where to look for its default configuration unless we tell it explicitly:

log4net.Config.XmlConfigurator.Configure(new System.IO.FileInfo ("..//..//App.config"));

That line tells the log4net where its config file exist. (If we go up two directories from the EXE file, debug -> bin -> we'll get to the directory of App.config.) (There are more ways to do so, like in AssemblyInfo).

WCF Parts

Without 'add service reference' way, that creates proxy for us, we can simply set our setting for WCF service. In WCF we need three parts, address, binding, and contract to establish the service. When the app starts up, it creates and rises the service of WCF logger:

ServiceHost sh = new ServiceHost(typeof(ServiceLogger));
string address = "http://localhost:8080/WcfAppenderService";
BasicHttpBinding binding = new BasicHttpBinding();
Type contract = typeof(IServiceLogger);
sh.AddServiceEndpoint(contract,binding,address);
sh.Open(); 

The logger knows that it should pass the messages to appender named WcfAppender (as configured at App.config) and needs to instantiate this appender class. In the constructor of this class, we initialize and get the channel to the service, so the appender can send data to the service. It's simple:

static IServiceLogger Service;
EndpointAddress address = new EndpointAddress
	(new Uri("http://localhost:8080/WcfAppenderService"));
BasicHttpBinding binding = new BasicHttpBinding();
Service = ChannelFactory<IServiceLogger>.CreateChannel(binding,address);

The Sample App

In the sample app, we are trying in the loop to divide numbers and send the result to logger as information. When we try to divide by zero, we get an exception and send it as error. I hope this article will help to understand in writing WCF appender. If you find some way better, please tell me and I'll mark this correction.

History

  • 23rd July, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

yossharel
Software Developer
Israel Israel
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionWorked out of the box Pin
Member 1150318613hrs 56mins ago
memberMember 1150318613hrs 56mins ago 
GeneralMy vote of 4 Pin
falander24-Oct-11 3:34
memberfalander24-Oct-11 3:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190306.1 | Last Updated 23 Jul 2010
Article Copyright 2010 by yossharel
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid