Allow LogitcalThreadContextProperties to be stored in HttpContext.Items instead 
of CallContext
----------------------------------------------------------------------------------------------

         Key: LOG4NET-80
         URL: http://issues.apache.org/jira/browse/LOG4NET-80
     Project: Log4net
        Type: Improvement

  Components: Other  
    Versions: 1.2.10    
    Reporter: Ron Grabowski
    Priority: Minor


According to these posts:

 http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html
 http://forum.springframework.net/showthread.php?t=572

and this thread on the mailing list:

 http://www.mail-archive.com/log4net-dev@logging.apache.org/msg01236.html

it might be a good idea to investigate storing LogicalThreadContext values 
inside the HttpContext.Items if log4net is being used within an ASP.Net 
application. Other projects such as IBatisNet, Spring.Net, Castle Project's 
Active Record, etc. do this. In a nutshell, IIS may change the thread on which 
a request is processed on durings the request's lifetime. Accoring to the post 
on springframework.net, a worse case scenerio is for each ASP.Net page 
lifecycle event to be switched to a different thread. Even though HttpContext 
uses CallContext internally its supposedly does other things to make it a safer 
place for storing per-request values.

I haven't studied the other projects implementations in depth but the basic 
idea is to replace this code in LogicalThreadContextProperties:

 PropertiesDictionary properties = 
(PropertiesDictionary)CallContext.GetData(SLOT_NAME);

with this:

 PropertiesDictionary properties = 
(PropertiesDictionary)contextAccessor.GetData();

where contextAccessor is CallContextAccessor:IContextAccess, 
HttpContextAccessor:IContextAccessor, etc.:

 internal LogicalThreadContextProperties(IContextAccessor contextAccessor)
 {
  this.contextAccessor = contextAccessor;
 }

The decision on which IContextAccessor to use could come from a factory:

 public class DefaultContextAccessorFactory : IContextAccessorFactory
 {
  private const string SLOT_NAME = 
"log4net.Util.LogicalThreadContextProperties";
 
  public IContextAccessor CreateContextAccessor()
  {
   // another implementation might _always_ use CallContext instead
   // of first testing for HttpContext
   if (HttpContext.Current != null)
   {
    return new HttpContextAccessor(SLOT_NAME);
   }
   else
   {
    return new CallContextAccessor(SLOT_NAME);
   }
  } 
 }

I haven't figured out a good way for LogicalThreadContext to know which factory 
to be initialized with. This was my first attempt:

 static LogicalThreadContext()
 {
  // we should retrieve the IContextAccessorFactory from the configuration 
system...
  IContextAccessorFactory contextFactory = new DefaultContextAccessorFactory();
                        
  s_properties = new 
LogicalThreadContextProperties(contextFactory.CreateContextAccessor());

  s_stacks = new ThreadContextStacks(s_properties);
 }

The problem is that IContextAccessorFactory should be coming from the 
configuration system some how. Contexts don't know about ILoggerRepository and 
vice versa. Maybe its acceptable for LogicalThreadContext's static constructor 
to always use the DefaultContextAccessorFactory when its initialized and the 
user can specify another factory via a setter. 

Has anyone actually run into a problem with requests being switched to 
different threads? I mostly understand the reasoning for it but I can't imagine 
it being a regular occurance.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to