I thought it might be useful to interject with some history about Log4j and
ServletContext logging.  Please see this recent thread on the slf4j-user list 
for
some pertinent details explaining how this is actually possible today with Log4j
1.2...

http://marc.info/?t=127359183200004&r=1&w=2


Now that you are familiar with that, let's address the LoggerContext stuff.  I
agree with Ralph's objections to Curt's proposal (though possibly not for the 
same
reasons).  However, I'm not necessarily in agreement with Ralph either.  First,
some basic questions....

Can there be only one LoggerContext as is implied by
LogManager.setContext(LoggerContext)?  Why not support multiple contexts at any
given time?  And just because a context has been set, does that imply that the
context itself logs (as opposed to merely providing some contextual information)
or that all logging should go to that context when it is set regardless of
configured appenders?  And what if LogManager exists at the container level,
meaning that Log4j is being shared by all apps?  We can't use the context of one
app for all apps, e.g., we can't be using a single webapp's ServletContext to 
log
for all apps.  The context should be scoped to the current Logger Repository, 
not
the classloader of the LogManager.

In any case, isn't this what an Appender is for?  To me, unless a logging
configuration specifies that logging information for a given logger ought to go 
to
an appender that directs logging to the servlet context, then it shouldn't go to
the servlet context regardless of any supplied context.  It should go to 
whatever
appender it is configured to go to.


Here are my requirements...

1.  I would only agree with a context (zero or more) being able to be supplied 
to
a Logger method if it is made absolutely clear that just because a context is
provided, does not imply that context will have any effect on logging, as it 
would
depend on whether the current configured appenders recognize, and make use of, 
the
context.  If an appender is assigned to the logger in question AND it supports 
the
provided context, then it would be utilized, otherwise not.  That said, I'm not
sure that it's worth the API pollution nor amount of confusion that this would
inevitably create for users?

2.  It MUST be possible to set the context in some other more general way.  Why?
Because, in the case of a ServletContext, it is only available to application
classes that participate in the servlet lifecycle, not general library classes.
All classes that log must be able to participate.

3.  It must work for ANY number of Logger Repositories, not just the default 
one.


The solution that Aleksei Valikov came up with, and I implemented in the Log4j
sandbox [1][2], implements #2 and #3 above using plain old Log4j 1.2.  A few
things could be improved upon, such as the static ServletContext registration
concept and the requirement that appender configuration must provide the context
path.  Fallback to a non-context dependent appender would be beneficial as well.
The first two issues could be ameliorated by using a servlet Filter to register 
a
ThreadLocal for the request request/response lifecyle.  The last could be
addressed simply by an update to the appender to allow for a fallback appender 
to
be configured.


As has been shown, all of this can be done *without* the concept of an API-level
LoggerContext and, in fact, with the current production version of Log4j.  I
strongly suggest that this LoggerContext stuff be thought through a bit more
before polluting the API with the concept.  I'm not against the concept in
general.  I just want to make sure that it isn't being implemented the wrong way
for the wrong reasons.


Thoughts?

[1]
http://svn.apache.org/repos/asf/logging/sandbox/log4j/log4j_sandbox/tags/LOG4J_SANDBOX_ALPHA3/src/java/org/apache/log4j/servlet/ServletContextLogAppender.java
[2]
http://svn.apache.org/repos/asf/logging/sandbox/log4j/log4j_sandbox/tags/LOG4J_SANDBOX_ALPHA3/src/java/org/apache/log4j/servlet/ServletContextLogAppenderListener.java


Jake

On 5/31/2010 5:56 PM, Ralph Goers wrote:
> 
> On May 31, 2010, at 3:53 PM, Curt Arnold wrote:
> 
>>
>> On May 31, 2010, at 3:28 PM, Thorbjørn Ravn Andersen wrote:
>>
>>> Den 30/05/10 23.12, Curt Arnold skrev:
>>>> I don't have this in code or in the JIRA, but I have mentioned in recent 
>>>> threads the idea of a user-supplied context object in logging calls. 
>>>> Currently log4j has a thread associated context (the MDC and NDC) and 
>>>> there are JVM level context (line ending separator), but there is no 
>>>> concept of a user-supplied context unless embedded in the message 
>>>> parameter.
>>>> In this case, the logging call is operating in the "context" of the 
>>>> servlet request, and you could do pass the servlet as the user-context 
>>>> object.  A servlet appender could check if the user context object was a 
>>>> Servlet and if so delegate to its log method.  We could also add patterns 
>>>> for %ipaddr, %ipport, etc, that would attempt to recognize the 
>>>> user-context object and extract that info if it could recognize the type.
>>>>
>>> I am unsure of what you describe. Could you write some pseudocode showing 
>>> what you mean?
>>>
>>
>> I'm working way below the client API at the moment, but the general idea is 
>> that in addition to MDC and NDC (aka the thread-associated context), the 
>> stack trace (aka the caller context), you can provide context with an 
>> explicit context parameter on the logging call. 
>>
>> If the current logj4 API was extended to add user-supplied context, you'd 
>> have:
>>
>> Logger.info(Object message, Throwable thrown, Object context);
> 
> I would object to this - see my other post.  I could tolerate this if it was 
> 
> Logger.into(Object message, Throwable thrown, Context context);
> 
> But since the Context is likely to have the same life expectancy as the 
> LoggerContext it makes more sense to just tie those together. 
> 
> public class LoggerContextListener implements ServletContextListener {
>   public void contextInitialized(ServletContextEvent event) {
>       LogManager.setContext(new 
> ServletLoggerContext(event.getServletContext()));
>   }
> 
> }
> 
> public class ServletLoggerContext extends LoggerContext {
> 
>       private ServletContext context; 
>       
>       public ServletLoggerContext(ServletContext context) {
>               super();
>               this.context = context;
>         }
> 
>       public Object getExternalContext() {
>               return this.context;
>         }
> }
> 
> 
> 
> Ralph
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
> For additional commands, e-mail: log4j-dev-h...@logging.apache.org
> 
> 
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to