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]

Reply via email to