Line number information should be put into the log messages by processing classes and enhancing the byte code.
#Ant task definition and usage can be like below. Feel free to customize according to your requirements
<taskdefname="enhanceLogs"classname="your.lovely.company.LoggerEnhancement"classpathref="lib.ant.path"/>
<enhanceLogs classesDir="${classesDir}"loggerJarsDirectory="${logging.jars.dir}"/>
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javassist.
import javassist.ClassPool;
import javassist.CtClass;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import org.apache.tools.ant.
import org.apache.tools.ant.Task;
public class LoggerEnhancement extends Task {
public String classesDir;
public String loggerJarsDirectory;
public String getLoggerJarsDirectory() {
returnthis.loggerJarsDirectory
}
public voidsetLoggerJarsDirectory(fin
this.loggerJarsDirectory= loggerJarsDirectory;
}
public String getClassesDir() {
returnthis.classesDir;
}
public voidsetClassesDir(final String classesDir) {
this.classesDir= classesDir;
}
@Override
public voidexecute() throws BuildException {
try{
this.enhanceClasses();
} catch(final Exception e) {
e.printStackTrace();
throw new BuildException(e);
}
}
private voidenhanceClasses() throws FileNotFoundException, Exception {
finalList
for(final File file : classFiles) {
String qualifiedClassName = file.toString().substring(this
qualifiedClassName = qualifiedClassName.replaceAll(
this.enhanceClassFile(
}
}
private voidenhanceClassFile(final String className) throws Exception {
finalClassPool pool = ClassPool.getDefault();
pool.appendClassPath(this.clas
pool.appendClassPath(this.logg
pool.appendClassPath(this.logg
finalCtClass compiledClass = pool.get(className);
if(compiledClass == null) {
System.err.println("Class " + className + " not found");
} else{
final LoggerEnhancementExpEditor exp = new LoggerEnhancementExpEditor();
exp.setClaz(compiledClass);
compiledClass.instrument(exp);
compiledClass.writeFile(this.c
}
}
private List
finalList
finalFile startingDirectory = new File(classesDir);
finalList
System.out.println(" -- Processing classes under directory:" + classesDir);
for(final File file : files) {
if (file.isFile() && file.getName().endsWith(".
result.add(file);
}
}
returnresult;
}
private List
this.validateDirectory(
finalList
Collections.sort(result);
returnresult;
}
private List
finalList
finalFile[] filesAndDirs = aStartingDir.listFiles();
finalList
for(final File file : filesDirs) {
result.add(file);
if (!file.isFile()) {
final List
result.addAll(deeperList);
}
}
returnresult;
}
private voidvalidateDirectory(final File aDirectory) throws FileNotFoundException {
if(aDirectory == null) {
throw new IllegalArgumentException("
}
if(!aDirectory.exists()) {
throw new FileNotFoundException("
}
if(!aDirectory.isDirectory()) {
throw new IllegalArgumentException("Is not a directory: " + aDirectory);
}
if(!aDirectory.canRead()) {
throw new IllegalArgumentException("
}
}
static classLoggerEnhancementExpEdito
privateCtClass claz;
publicCtClass getClaz() {
return this.claz;
}
publicvoid setClaz(final CtClass claz) {
this.claz= claz;
}
@Override
publicvoid edit(final MethodCall m) throws CannotCompileException {
if (this.isLoggerMethodCall(m)) {
try {
System.out.println(" -- Enhancing log line: "
+ this.getClaz().getName()
+ "."
+ m.where().getName()
+ "("
+ this.getClaz().getSimpleName()
+ ".java:"
+ m.getLineNumber()
+ ")");
m.replace("{ $1 = $1 +\", "
+ this.getClaz().getName()
+ "."
+ m.where().getName()
+ "("
+ this.getClaz().getSimpleName()
+ ".java:"
+ m.getLineNumber()
+ ") "
+ "\"; $_ = $proceed($$); }");
} catch (final Exception e) {
throw new CannotCompileException(e);
}
}
}
privateboolean isLoggerMethodCall(final MethodCall m) {
return this.isSlf4jLoggerMethod(m) || this.isLog4jLoggerMethod(m);
}
privateboolean isSlf4jLoggerMethod(final MethodCall m) {
return m.getClassName().equals("org.
}
privateboolean isLog4jLoggerMethod(final MethodCall m) {
return m.getClassName().equals("org.
}
privateboolean isALogMethod(final MethodCall m) {
boolean result = false;
final String[] slf4LogLevels = { "trace", "debug", "info", "warn", "error", "fatal" };
final String methodName = m.getMethodName();
for (final String logLevel : slf4LogLevels) {
if (methodName.equals(logLevel)) {
result = true;
}
}
return result;
}
}
}
No comments:
Post a Comment