On Mon, 31 May 2010 22:48:25 -0700
 Ralph Goers <ralph.go...@dslextreme.com> wrote:

On May 31, 2010, at 10:31 PM, Jacob Kjome wrote:

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

Thanks for the context. I guess I should subscribe to SLF4J User's - I only subscribe to the dev list.

FWIW, in SLF4J ILoggerFactory plays the same role as LoggerContext in my Log4J2 API. Logback handles different types of Contexts as described at http://logback.qos.ch/manual/loggingSeparation.html. My intention is to do something similar. However, neither SLF4J or Logback provide links to an external context as far as I am aware.


Logback's Logger Context is equivalent to Log4j's Logger Repository, just as Logback's ContextSelector is equivalent to Log4j's RepositorySelector.  See another article written by Ceki back in 2002....

http://articles.qos.ch/sc.html




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.

Another Jira issue to open. In 2.0 it needs to be possible to let every webapp have its own LoggerContext even though the Log4J code might be shared. Logback currently provides this functionality.

As has Log4j for a very long time, again, using a Logger Repository Selector.

Personally, I think this is one of the huge flaws in J2EE - that the components that are in the container are exposed to the webapps running in them, but I can't fix that.


Do you know of an application framework in any language that doesn't have this "flaw"?  Just curious.  I'm not sure it can rightly be called a "flaw" if it cannot possibly be avoided.  I'm not saying it can't.  I just think that if it could, it would have by someone in some language by now.



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.

In general, the approach you took makes sense.


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?

If it were then I would suggest that it be incorporated via a ContextAwareMessage, not an additional Object on the API. This is similar to the problem I ran into with StructuredData, having Appenders have to run through all the parameters doing instanceof is a hack.


Ageed, if you mean that generic code should not be using instanceof.  Only code that has business using a particular type of context object should bother referencing it.  For instance, a ServletContextLogAppender class could properly use instanceof to determine whether [one of] the current context logger object is ServletContext to determine if it is usable.

BTW, can you describe what the logging call would look like using a "ConextAwareMessage"?  And would this be able to supply more than one external context?


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.

I know what you mean, but in my version of 2.0 Logger Repositories don't exist. The LoggerContext contains the Map of all the loggers obtained by getLogger() and a reference to the configuration. So the LoggerContext is equivalent to what I think you mean by Logger Repositories.


If LoggerContext is indeed the equivalent of Logger Repository, then I think we're good to go.



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?

The main issue I have with this implementation is that it is too specific as its only purpose is to write to the ServletContext's log method. What if it is desired to access the ServletContext init parameters? The approach of using the ServletContextListener is correct but the context needs to be accessible to the Configuration, as well as Filters and Layouts in addition to Appenders. The code I added to my branch exposes getExternalContext to the LoggerContext interface, but could just as easily not be in the interface but only be present in the core implementation.


As long as ExternalContext is able to maintain more than one contextual object at a time.  That said, I think this is more of an implementation detail than an API detail.  For instance, if the Configuration needs to be ServletContext-aware, then one would create a ServletContextConfiguration class.  The base Configuration shouldn't need to care about any context at all.  And all of this could be provided by ThreadLocals, avoiding the need for any API-specifics.  Or it could be provided to said configuration object at configuration time.  And given that the LoggerContext has access to the Configuration, it could obtain the context from it if it wanted to (.i.e. a ServletContextLoggerContext class).

Then again, if you can come up with a flexible API that supports multiple contexts at any given time and avoids instanceof hacks in generic, otherwise non-context-aware code, then I'm open to seeing that in Log4j 2.0.  However, I just can't picture such a thing at the present time.

Ralph


Jake


---------------------------------------------------------------------
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