Geeks With Blogs
Adrian Hara Working through the .NET maze not straightforward. The problem is that many (all?) of log4net's classes are not serializable. This includes the implementations of the ILog interface, which means that if you plan on using log4net loggers in your SharePoint workflow code like so...

private ILog logger = LogManager.GetLogger(typeof(Foo));'re out of luck. As soon as the workflow is dehydrated, you'll get a nice exception stating that type X (probably LogImpl) is not serializable.


One solution to this problem is to recreate the logger each time the workflow is rehydrated or, more simply put, lazy-initialize the value of the logger: if it's null, create it, if not, return it. Although this could be done separately wherever you need it in the project (via perhaps a private property of each class), I thought it would be nicer to abstract this away in a little library. I called it SPLog4net (how imaginative!) and you can find it on CodePlex.


The library has two classes (ok, three, including the msdn copy/pasted TraceProvider):

1. LoggerWrapper  - this class implements the ILog log4net interface and acts as a thin wrapper over a real log4net logger. Its main purpose is to lazy-initialize the log4net logger if it's not yet initialized. The usage pattern is very similar to the usual log4net usage pattern:

log4net standard -             private ILog logger = LogManager.GetLogger(typeof(Foo));

LoggerWrapper -                private ILog logger = new LoggerWrapper(typeof(Foo));

    The other little thing that the logger wrapper does is it prefixes each log message with a...umm... prefix. The idea is that, being in SharePoint, you might want to log messages to the ULS log (more on that in a minute). But, as you probably know, the ULS log files are not the most user-friendly things around. So, if you use a utility to view them, such as the excellent SPTraceView, you might want to take advantage of its message filtering feature and have it only display messages starting with a certain.... ahem... prefix :)

2. UlsLogAppender - to be honest I think it's quite strange such a thing doesn't yet exist (I couldn't find it on google anyway ;)), so I wrote it. This class represents a log4net appender that writes to the SharePoint ULS log. You might want to take a look at the source and tweak it, because it has a method which converts the log4net severity levels to SharePoint severity levels and the said method is... well... not totally complete. (which means I only mapped severals level which I thought of use, but you might need more). To use it just make sure you have it in the GAC (or application bin) and added to the log4net config file (or section in the web.config file of your web application).


Naturally, you can use the two independently and not only from a workflow.


Hope this helps someone and please let me know if I'm either reinventing the wheel or inventing a square one ;)

Posted on Thursday, September 11, 2008 9:19 AM | Back to top

Comments on this post: Using log4net in a SharePoint 2007 (WSS or MOSS) workflow ...

# re: Using log4net in a SharePoint 2007 (WSS or MOSS) workflow ...
Requesting Gravatar...
Hi Adrian

I have tried to implement the ULSAppender in a SharePoint2010 application, log4net it seems to work fine, and i can step through my code all the way to the TraceEvent (advapi32.dll) - however nothing is persisted in my log file.

Apparantly the TraceLog example on MSDN does not work on 2010:

Do you have a take on this?

Kind regards
Left by Morten Andreasen on Jan 05, 2010 6:11 AM

# re: Using log4net in a SharePoint 2007 (WSS or MOSS) workflow ...
Requesting Gravatar...

Sorry, but I haven't had a chance to work on sharepoint2010 yet. But please let me know if you find a solution...

Left by Adrian Hara on Jan 05, 2010 6:23 AM

Your comment:
 (will show your gravatar)

Copyright © Adrian Hara | Powered by: | Join free