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/[email protected]/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