Using a special annotation referring the SVN revision number and a custom renderer for throwabl's in log4j may help. The annotation may look like:
@Target({ ElementType.TYPE })The annotated class:
@Retention(RetentionPolicy.RUNTIME)
public @interface Revision {
public String value();
}
@Revision("$Revision: 42 $")Note that the String "$Revision: 42 $" can be set by the SVN keyword substitution.
public class ExampleClass {
public static void main(String[] args) { Logger logger = Logger.getLogger("xxx.example.ExampleClass");logger.warn("Example exception: ",new Exception());}}
And the renderer that has to be configured for log4j:
public static final class RevisionDecoratingThrowableRenderer implements ThrowableRenderer {Certainly things can be optimized a bit, but the principle should get clear.
public String[] doRender(final Throwable throwable) {
StackTraceElement[] elements = throwable.getStackTrace();
String[] lines = new String[elements.length + 1];
lines[0] = throwable.toString();
for (int i = 0; i < elements.length; i++) {
lines[i + 1] = renderLine(elements[i]);
}
return lines;
}
private String renderLine(final StackTraceElement element) {
StringBuilder b = new StringBuilder("\tat ");
b.append(element);
b.append(computeRevisionSuffix(element));
return b.toString();
}
protected String computeRevisionSuffix(final StackTraceElement element) {
String className = element.getClassName();
Class<?> clazz;
try {
clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e1) {
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e2) {
try {
clazz = getClass().getClassLoader().loadClass(className);
} catch (Throwable t) {
return "";
}
}
}
Revision va = clazz.getAnnotation(Revision.class);
if (va != null) {
return '[' + (va.value().replaceAll("\\$", "")) + ']';
}
return "";
}
}
Keine Kommentare:
Kommentar veröffentlichen