I was surprised that it was hard to find a lot of previous discussion
or previous bugs on the issue. If anybody else has links to relevant
discussions, please add them. Here are some that I found:
Recent log4j-user discussion (assume existence of problem): http://
marc.theaimsgroup.com/?l=log4j-user&m=111253143214177&w=2
Commons-dev patch submission to http://marc.theaimsgroup.com/?
l=jakarta-commons-dev&m=107472058005673&w=2
Commons-dev thread (followups appear as distinct topics) http://
marc.theaimsgroup.com/?l=jakarta-commons-dev&m=106865687610260&w=2
As far as I can reconstruct, Apache Geronimo wanted a distinct level
lower than debug and had trace() added to Jakarta Commons Logging.
Without that change, I believe that most code that used JCL could be
converted to use log4j simply by changing the package names and
switching Log and Logger. The JCL bridge to log4j just treated trace
as a synonym for debug where the JDK 1.4 logging maps debug() to
Level.FINER and trace to Level.FINEST.
So trace is a special case due to its "endorsement" by JCL. There
are a couple of distinct issues:
JCL/log4j client code compatibility:
Switching JCL code that uses org.apache.commons.logging.Log.trace()
to log4j would require adding an explicit org.apache.log4j.Logger.
JCL mapping of trace calls to level lower than Level.DEBUG
The major roadblock is the lack of a public constructor for
o.a.l.Level. I think the approach used in tests/java/org/apache/
log4j/xml/XLevel.java is problematic since adding a custom
implementation class would cause problems for SocketAppender et al to
fail if the class is not available. A derived class definition could
be used to bypass the access control on the constructor and would
might be an appropriate way to address the issue:
class final CustomLevelFactory extends org.apache.log4j.Level {
/**
* Private, non-functional constructor.
*/
private CustomLevelFactory() {
super(-1, "", -1);
throw new NotImplementedException();
}
//
// since we are in extension of Level we can access the
protected constructor
public static final org.apache.log4j.Level createLevel(
final int severity,
final String name,
final int syslogLevel) {
return new Level(severity, name, syslogLevel);
}
}
class Log4JLogger {
private static final Level TRACE = CustomLevelFactory.createLevel
(5000, "TRACE", 7);
public void trace(Object message) {
getLogger().log(FQCN, TRACE, message, null );
}
}
In a perfect world (aka 2.0), Category would disappear and Level
would be final with a public constructor. That would make life
easier in general but CustomLevelFactory would need to be changed to
not extend Level and call the public constructor.
The final area would be in parsing configuration files that contain
"TRACE" (or any other place were you need to convert a Level name
back to an object), but the only place that I can think of right now
are in the configuration parsers. The code might be made more
general so that if it encounters a name like "5000" it will parse it
as an integer and fabricate a level with that value which would be
sufficient for configuration purposes.
To recap my non-exhaustive analysis:
trace() is special since it is in JCL.
JCL should be able to map trace() to a distinct level than debug() by
using hacky CustomLevelFactory to create an instance of Level with a
custom name and value.
Other custom levels should be available using the CustomLevelFactory
approach without any code changes (excluding configuration).
Setting a threshold to a custom level would require modifying the
configuration code or Level.toLevel to fabricate a new level if the
argument is a string representation of an integer which would allow
stuff like:
<root>
<level value="5000"/>
</root>
Or providing a mechanism to inform the configurators of new levels to
recognize:
JoranConfigurator config = new JoranConfigurator();
const.addLevel(MyCustomLevels.TRACE);
config.configure(...);
which would allow you to do:
<root>
<level value="TRACE"/>
</root>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]