0
votes

We're trying to use log4net log processes requested to a WCF service. For that, our goal was to log in different files depending of some arguments of the request. For that, we have used Context properties of log4net, setting the context of it in every call to the service, but, because of possible concurrency issues, we can't use "GlobalContext".

Thinking(it seems that thinking wrong) that wcf uses one thread per call, we set ThreadContext properties when the request was received, such as this:

GlobalContext.Properties("fulldate") = Now.ToString("yyyyMMdd")
GlobalContext.Properties("date") = Now.ToString("yyyyMM")

ThreadContext.Properties("center") = center //it comes with the request header

XmlConfigurator.Configure()

And the appender is defined in the config file like this:

<appender name="IntAppender" type="log4net.Appender.FileAppender"> 
<file type="log4net.Util.PatternString" value="c:\\Logs\\%property{center}\\%property{date}\\%property{fulldate}\\theLog.log" /> 
<datePattern value=".yyyyMMdd.'log'" /> 
<appendToFile value="true" /> 
<layout type="log4net.Layout.PatternLayout"> 
  <conversionPattern value="%date [%thread] %-5level - [%ndc] %message%newline" /> 
</layout> 

But sometimes, logs that should be in one center's log is in an another center's log, and it seems that the problem is how WCF manages threads. I don't want to set the service to be instanced per request. Can you point me a link or doc of how WCF manages threads? I haven't been able to find one. And is it possible to accomplish what I'm trying to do? That is, to log all request of one center in that center's log file.

Thanks.

1

1 Answers

2
votes

That won't work, and it's nothing to do with WCF's thread model.

Log4net shares your single defined appender between loggers, and thus between threads. When one thread changes the file value on the file appender, this applies to all threads so it's a race condition to see what log the error actually ends up in!

To accomplish this you need to have one file appender per log file, per "center". If the centers are known beforehand you could set them up in config, or otherwise it's easy enough to set them up programatically