Friday, May 14, 2010
Thursday, May 06, 2010
Repurposing test code for production
For various reasons I often wrap the well-known logback logging library; more precisely, I wrap the SLF4J API it implements.
However, this has a strong drawback: filename and line numbers in the log which should tell me the origin of the log calls instead show me my wrapper class. From logback's perspective the wrapper is the caller; from my perspective the wrapper should be invisible.
The culprit is
The hack:
I replace the static method in logback with my own when my wrapper class is loaded. I even get a handle (it) to the original method so I may forward appropriately.
This is not my first try at a solution to wrapping logback. Nor my second. Nor my third. But it is the only one so far which:
Do watch out for:
However, this has a strong drawback: filename and line numbers in the log which should tell me the origin of the log calls instead show me my wrapper class. From logback's perspective the wrapper is the caller; from my perspective the wrapper should be invisible.
The culprit is
CallerData.isDirectlyInvokingClass(String, String)
. It tells logback if a given stack frame is internal to logback or from the calling application. It is static
and logback has no hooks for changing its behavior. What to do?The hack:
public class Wrapper { static { new MockUpEnter the clever jmockit library sitting at the high end of the testing mock library pile up (or deep end, if you prefer). Jmockit is not the easiest library to use, but is has more code-fu per line than most other swiss-army knives.() { CallerData it; @Mock(reentrant = true) public boolean isDirectlyInvokingClass( final String currentClass, final String fqnOfInvokingClass) { return it.isDirectlyInvokingClass( currentClass, fqnOfInvokingClass) || currentClass.equals(Wrapper.class.getName()); } }; } // Rest of class }
I replace the static method in logback with my own when my wrapper class is loaded. I even get a handle (it) to the original method so I may forward appropriately.
This is not my first try at a solution to wrapping logback. Nor my second. Nor my third. But it is the only one so far which:
- Works
- Looks like Java
- Is compact and limited to the wrapper class
- Can be explained to others (mostly)
- Can be maintained (by some)
Do watch out for:
- Running the application right in the presence of jmockit
- The obligatory AOP warning for the "it" trick
Subscribe to:
Posts (Atom)