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