Skip to content

Instantly share code, notes, and snippets.

@jan-krueger
Last active October 27, 2015 17:30
Show Gist options
  • Save jan-krueger/cbacc575ce587fb97596 to your computer and use it in GitHub Desktop.
Save jan-krueger/cbacc575ce587fb97596 to your computer and use it in GitHub Desktop.
Simple Logger
package de.YonasCode.SweetUtils.Debugger;
import java.lang.reflect.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
/**
* Created by Yonas on 21.06.2015.
*/
public class Debugger<T> implements InvocationHandler {
private T clazz;
private static Pattern[] pattern = {
Pattern.compile("^((.*)?([a-zA-Z0-9\\.]+)((;)?@)([a-zA-Z0-9]+))"),
Pattern.compile("^(java.util|java.lang).*")
};
public Debugger(T clazz) {
this.clazz = clazz;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
StringBuffer buffer = new StringBuffer();
buffer.append(clazz.getClass().getSimpleName());
buffer.append(Debugger.modifiersToString(clazz.getClass().getModifiers()));
buffer.append(method.getName());
buffer.append("(");
for(int i = 0; args != null && i < args.length; i++) {
String argument = (args[i] == null ? "null" : Debugger.getSimpleName(args[i].toString()));
buffer.append(argument);
if(i < (args.length - 1)) {
buffer.append(", ");
}
}
buffer.append(")");
Object result = null;
String exceptionName = null;
String exceptionMessage = null;
long executionTime = -1;
try {
executionTime = System.nanoTime();
//invoke the method
result = method.invoke(clazz, args);
executionTime = System.nanoTime() - executionTime;
} catch(Exception exception) {
//get information (name, message) from the exception
executionTime = System.nanoTime() - executionTime;
exceptionName = exception.getCause().getClass().getSimpleName();
exceptionMessage = exception.getCause().getLocalizedMessage();
}
//execution time
if(TimeUnit.NANOSECONDS.toMillis(executionTime) == 0) {
buffer.append("\n -> " + executionTime + "ns ");
} else {
buffer.append("\n -> " + TimeUnit.NANOSECONDS.toMillis(executionTime) + "ms ");
}
//where?
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement stackTraceElement = (stackTraceElements.length >= 4 ? stackTraceElements[3] : null);
if(!(stackTraceElement == null)) {
buffer.append("\n -> " + String.format(
"Called in %s#%s (%s) at line %d",
Debugger.getSimpleName(stackTraceElement.getClassName()),
stackTraceElement.getMethodName(),
stackTraceElement.getFileName(),
stackTraceElement.getLineNumber()
));
}
//result
String className = null;
StringBuilder resultString = new StringBuilder();
if(!(result == null)) {
//called when it's a normal java class
if(result.getClass().getName().matches(Debugger.pattern[1].pattern())) {
className = result.getClass().getSimpleName();
resultString = resultString.append(Debugger.getSimpleName(result.toString()));
} else { //called when it's a "custom" class
className = result.getClass().getSimpleName();
if(className.isEmpty()) {
className = result.getClass().getName();
}
Field[] fields = result.getClass().getDeclaredFields();
for(int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
String fieldName = field.getName();
String fieldValue = Debugger.getSimpleName(field.get(result).toString());
resultString.append(fieldName + " = " + fieldValue);
if(i < (fields.length - 1)) {
resultString.append(", ");
}
}
}
} else if(method.getReturnType().equals(Void.TYPE)) { //called when the return type is "void"
resultString.append("void");
} else if(!(exceptionName == null)) { //called when the invoke "throws" an exception
className = exceptionName;
resultString.append(exceptionMessage);
} else { //called when the method returns "null" but the return type is not "void"
resultString.append("null");
}
buffer.append(String.format("\n -> (%s) %s", className, resultString));
//print out the result
System.out.println(buffer);
return result;
}
public static String modifiersToString(int modifiers) {
if(Modifier.isPublic(modifiers)) {
return "+";
}
if(Modifier.isProtected(modifiers)) {
return "#";
}
if(Modifier.isPrivate(modifiers)) {
return "-";
}
return "";
}
public static <V> V factory(Class type, V value) {
return (V) Proxy.newProxyInstance(
Debugger.class.getClassLoader(),
new Class[]{ type },
new Debugger<V>( value )
);
}
private static String getSimpleName(String clazz) {
if(!(clazz.matches(Debugger.pattern[0].pattern()))) {
try {
return Class.forName(clazz).getSimpleName();
} catch (ClassNotFoundException e) {
return clazz;
}
}
boolean isArray = false;
int start = -1, end = -1;
char[] chars = clazz.toCharArray();
for(int x = chars.length - 1; x >= 0; x--) {
if(chars[x] == '@' || (chars[x] == ';' && chars[x+1] == '@')) {
end = x;
isArray = (chars[x] == ';' && chars[x+1] == '@');
}
if(end != -1 && chars[x] == '.') {
start = x+1;
break;
}
}
if(start == -1 || end == -1) {
return clazz;
}
String sequence = clazz.substring(start, end);
return (isArray ? sequence + "[]" : sequence);
}
}
package de.YonasCode.SweetUtils;
import de.YonasCode.SweetUtils.Debugger.Debugger;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
List<String> names = Debugger.factory(List.class, new ArrayList<String>());
names.add("Yonas");
names.add("Susen");
names.add("Mike");
names.size();
names.get(1);
names.toArray(null);
names.subList(0, 2);
names.listIterator();
}
}
You can call the Debugger#factory() method. The first argument is the interface class and the second one the instance of a class that implements this class e.g.:
Debbuger.factory(List.class, new ArrayList<String>());
--------------------------
ArrayList#add(Yonas)
-> 11703ns
-> Called in Example#<init> (Example.java) at line 21
-> (Boolean) true
ArrayList#add(Susen)
-> 4973ns
-> Called in Example#<init> (Example.java) at line 22
-> (Boolean) true
ArrayList#add(Mike)
-> 4389ns
-> Called in Example#<init> (Example.java) at line 23
-> (Boolean) true
ArrayList#size()
-> 5851ns
-> Called in Example#<init> (Example.java) at line 25
-> (Integer) 3
ArrayList#get(1)
-> 4682ns
-> Called in Example#<init> (Example.java) at line 27
-> (String) Susen
ArrayList#toArray(null)
-> 65536ns
-> Called in Example#<init> (Example.java) at line 29
-> (NullPointerException) null
ArrayList#subList(0, 2)
-> 129315ns
-> Called in Example#<init> (Example.java) at line 30
-> (SubList) [Yonas, Susen]
ArrayList#listIterator()
-> 19017ns
-> Called in Example#<init> (Example.java) at line 31
-> (ListItr) ArrayList$ListItr
--------------------------
Above you can find one example.
---------------------------
Note: Please keep in minde that I wrote this little helper while I fall asleep so don't expect too much... :D
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment