I tried this, since the changes are small enough, and it works. Here are the patches for review.
Shash ----- Original Message ----- From: "Shash Chatterjee" <[EMAIL PROTECTED]> To: "Avalon Developers List" <[EMAIL PROTECTED]> Sent: Saturday, February 01, 2003 8:49 AM Subject: LogKit and Excalibur Logger Hi! Since new releases are being discussed, I thought I'd bring this up. There is a known issue with the "method" formatter in LogKit's ExtendedPatterFormatter. The method shown is always the "caller" of Logger.class, which when used with a facade such as Excalibur Logger is *not* the user method, but always LogKitLogger. A while back, Peter Donald suggested a workaround, which works great. The workaround is to modify Excalibur Logger's FormatterFactory to support a custom formatter type, and then to implement that custom formatter with a modified version of ExtendedPatterFormatter that passes in, for instance, LogKitLogger.class instead of Logkit.class when calling StackIntrospector.getCallerMethod(...). The one issue with this approach is we (Keel) have to carry a modified Logkit class, make sure it is ahead in the classpath from the rest of Avalon, etc. etc. I'd like to propose a backwards-compatible fix. If this sounds like an acceptable idea, I'll go ahead and test/submit a patch. Here goes: LogKit changes: - Create an ExtendedPatternFormatter constructor that takes an offset to the stack depth. In other words, this would specify looking for a class that is "offset" levels away from Logger.class on the stack. - Create a StackIntrospector.getCallerClass(Class, offset) - Modify ExtendedPatternFormatter to get the caller-class of Logger.class with an offset. If new constructor mentioned above is not used, offset is 0 and behaves like it does now. - Then use that to pass to StackIntrospector.getCallerMethod(...). Excalibur Logger changes: - Modify the "extended" type handling in FormatterFactory to call the new constructor above, with offset +1. Let me know if this is acceptable or not, before I delve into it. Thanks, Shash
Index: FormatterFactory.java =================================================================== RCS file: /home/cvspublic/jakarta-avalon-excalibur/logger/src/java/org/apache/avalon/excalibur/logger/factory/FormatterFactory.java,v retrieving revision 1.2 diff -u -r1.2 FormatterFactory.java --- FormatterFactory.java 7 Aug 2002 13:37:00 -0000 1.2 +++ FormatterFactory.java 1 Feb 2003 16:38:21 -0000 @@ -82,7 +82,12 @@ if( "extended".equals( type ) ) { - return new ExtendedPatternFormatter( format ); + //Normally ExtendPatternFormatter would look for callers + //of Logger.class. But when Excalibur Logger provides a + //facade, the user class/method is actually one-level depper. + //We therefore create the pattern-formatter with an + //additional depth-offset of 1, + return new ExtendedPatternFormatter( format, 1 ); } if( "raw".equals( type ) )
Index: StackIntrospector.java =================================================================== RCS file: /home/cvspublic/jakarta-avalon-logkit/src/java/org/apache/log/util/StackIntrospector.java,v retrieving revision 1.6 diff -u -r1.6 StackIntrospector.java --- StackIntrospector.java 20 May 2002 10:12:50 -0000 1.6 +++ StackIntrospector.java 1 Feb 2003 16:40:24 -0000 @@ -82,21 +82,36 @@ public static final Class getCallerClass( final Class clazz ) throws SecurityException { - final Class[] stack = getCallStack().get(); + return getCallerClass(clazz, 0); + } - // Traverse the call stack in reverse order until we find clazz - for( int i = stack.length - 1; i >= 0; i-- ) - { - if( clazz.isAssignableFrom( stack[ i ] ) ) - { - // Found : the caller is the previous stack element - return stack[ i + 1 ]; - } - } - //Unable to locate class in call stack - return null; - } + /** + * Find the caller of the passed in Class. + * May return null if caller not found on execution stack + * + * @param clazz the Class to search for on stack to find caller of + * @param stackDepthOffset Offset call-stack depth to find caller + * @return the Class of object that called parrameter class + * @exception SecurityException if an existing SecurityManager disallows +construction + * of another SecurityManager and thus blocks method results + */ + public static Class getCallerClass(final Class clazz, int stackDepthOffset) { + final Class[] stack = getCallStack().get(); + + // Traverse the call stack in reverse order until we find clazz + for( int i = stack.length - 1; i >= 0; i-- ) + { + if( clazz.isAssignableFrom( stack[ i ] ) ) + { + // Found : the caller is the previous stack element + return stack[ i + 1 + stackDepthOffset]; + } + } + + //Unable to locate class in call stack + return null; + } /** * Get the method path name for the method from which the LogEvent was
Index: ExtendedPatternFormatter.java =================================================================== RCS file: /home/cvspublic/jakarta-avalon-logkit/src/java/org/apache/log/format/ExtendedPatternFormatter.java,v retrieving revision 1.6 diff -u -r1.6 ExtendedPatternFormatter.java --- ExtendedPatternFormatter.java 1 Oct 2002 00:00:35 -0000 1.6 +++ ExtendedPatternFormatter.java 1 Feb 2003 16:40:42 -0000 @@ -34,12 +34,20 @@ private static final String TYPE_METHOD_STR = "method"; private static final String TYPE_THREAD_STR = "thread"; + + private int m_callStackOffset = 0; public ExtendedPatternFormatter( final String format ) { super( format ); } + public ExtendedPatternFormatter( final String format, final int +callStackOffset ) + { + super( format ); + m_callStackOffset = callStackOffset; + } + /** * Retrieve the type-id for a particular string. * @@ -100,7 +108,15 @@ } } - final String result = StackIntrospector.getCallerMethod( Logger.class ); + //Determine callee of user's class. If offset is 0, we need to find + // Logger.class. If offset is 1, We need to find caller of +Logger.class, etc. + final Class clazz = StackIntrospector.getCallerClass( Logger.class, +m_callStackOffset - 1); + if (null == clazz) + { + return "UnknownMethod"; + } + + final String result = StackIntrospector.getCallerMethod( clazz ); if( null == result ) { return "UnknownMethod";
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]