| From | Sent On | Attachments |
|---|---|---|
| Simon Kitching | Feb 19, 2006 3:29 pm | |
| Boris Unckel | Feb 20, 2006 1:37 am | |
| V. Karthik Kumar | Feb 20, 2006 2:05 am | |
| Emmanuel Bourg | Mar 1, 2006 2:18 am | |
| Craig McClanahan | Mar 1, 2006 9:05 am | |
| Emmanuel Bourg | Mar 1, 2006 9:22 am | |
| Simon Kitching | Mar 1, 2006 11:11 am | |
| Emmanuel Bourg | Mar 2, 2006 1:20 am | |
| Boris Unckel | Mar 2, 2006 3:35 am | |
| Emmanuel Bourg | Mar 2, 2006 6:25 am | |
| Boris Unckel | Mar 2, 2006 6:30 am |
| Subject: | [logging] JCL2.0 design - API | |
|---|---|---|
| From: | Simon Kitching (skit...@apache.org) | |
| Date: | Feb 19, 2006 3:29:18 pm | |
| List: | org.apache.commons.dev | |
Hi,
I'd like to kick off discussions on what a Jakarta Commons Logging 2.x release might look like. This thread is on the topic of the JCL API.
Is the current core JCL api ok, or should we change it?
== LogFactory as factory for Log instances
Currently, JCL uses a LogFactory to create Log instances: Log log = LogFactory.getLog("fff");
By contrast, Log4j has the factory method on the Log class:
Logger log = Logger.getLog("fff");
Having one less class is a *little* nicer for users I think. However it does reduce the flexibility of the system a little and changing this is a major difference from JCL 1.x.
My choice would be: keep LogFactory and LogFactory.getLog as the mechanism for obtaining Log instances.
== LogFactory getAttributeNames/[get|set|remove]Attribute
Currently, "attributes" can be set on a LogFactory instance. Some attributes control the behaviour of the LogFactory class, some are used by concrete LogFactory implementations.
I'd be interested in trying to do away with these methods. I don't believe that a logging bridge like JCL should be configurable from the application code; that effectively destroys the point of a logging bridge.
== LogFactory.getFactory
I'd be keen on getting rid of this method completely (at least from the public API); I don't see why applications should have any need to access the factory instance.
== LogFactory.getInstance
Calling LogFactory.getFactory().getInstance(param) is equivalent to LogFactory.getLog(param).
I'd like to do away with the getInstance methods.
== LogFactory release/releaseAll
I would tentatively like to keep release, but change its meaning somewhat. Currently, it is used to delete any commons-logging-specific resources, but not clean up the underlying library. There are corner cases where explicitly releasing resources is still necessary so I think we need to keep this method. In addition, there are logging libraries that really need to be explicitly shut down before app exit; I'd like to expand the LogFactory.release method to have that responsibility. That would of course need new APIs to the underlying logging-lib-specific code.
I think the releaseAll method should *definitely* go. It's extremely dangerous to allow one webapp to release logging resources for all webapps. Right now, with JCL in a shared classpath, a call to this method can stuff up logging for all webapps in that container.
== Per-library LogFactory implementation
Originally, JCL had multiple LogFactory subclasses. In later releases things moved to having just one (LogFactoryImpl) which used reflection and various other tricks to handle all possible logging implementations.
I would like to move back to having a separate LogFactory implementation per concrete logging library. A bridge to a particular library is therefore a (LogFactory, Log) implementation pair. A LogFactory implementation that performs "discovery" could be implemented as a "decorator" over whatever LogFactory implementation it "discovers".
== Log class methods
Log provides *test* methods and *output* methods:
Log.isDebugEnabled() Log.debug(msg) Log.debug(msg, throwable)
I don't see anything wrong with this API, and would like to keep it exactly as is.
SLF4J uses a different approach for the log message. While JCL users need to build a string, SLF4j allows parameterised messages: slf4jlog.debug("Event {0} occurred at {1}", eventType, eventPlace);
This is nice in some ways; the final message string doesn't need to be composed until after the logging threshold is tested, so "code guards" become unnecessary. However it does mean an ugly set of API declarations where java1.5 varargs aren't supported: Log.debug(String template); Log.debug(String template, Object arg1); Log.debug(String template, Object arg1, Object arg2); Log.debug(String template, Object arg1, Object arg2, Object arg3);
A variant like this: Log.debug(String template, Object[] args); is possible, but the creating and building of an Object[] parameter probably means a "code guard" is now needed anyway.
And finally, all this is *different* from the existing 1.x api. I think any benefits are marginal, and so would prefer to just stay with the existing API.
Note that there is a bytecode-modification tool that can be run on code to automatically insert the necessary JCL code guards into .class files anyway, so they don't need to be explicitly present in the source if people prefer not to.
== Package name
Currently, JCL code is in "org.apache.commons.logging". Should we keep this package name for JCL2 or use something like "org.apache.commons.logging2"?
For the digester2 project I've been fiddling with, I've been convinced that "o.a.c.digester2" is the appropriate package name, because the API has significant changes; the new code is nowhere near a "drop in replacement" for the prior version.
However in this case, if we agree to keep the Log API intact, and only remove rarely-used methods from the LogFactory interface then the result will be that 99% or more of existing code that uses JCL1.x could use JCL2.x without even needing recompilation. I'd therefore suggest that we keep the same package name.
== Final Notes
One alternative to removing methods from the LogFactory interface is instead to define them as no-ops, or to have them throw UnsupportedOperationException. The cost is some extra baggage, but we could put clear comments saying that all implementations of LogFactory should simply ignore the method. It might be worth doing this for the sake of backwards compatibility...
Cheers,
Simon





