Skip to content

Instantly share code, notes, and snippets.

@jmcd
Last active August 29, 2015 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmcd/5fa3d39e0eb2d9c67ebf to your computer and use it in GitHub Desktop.
Save jmcd/5fa3d39e0eb2d9c67ebf to your computer and use it in GitHub Desktop.
Android Log Wrapper to: [1] automatically (and probably expensively) add class/method tracing to debug messages and [2] ability to hack in loggint to other places (e.g. a dirty log to a TextView)
class Foo {
private void bar() {
L.dt("hello world!"); // Logs with tag "Foo" and message "bar hello world"
}
}
final TextView tv = (TextView) this.findViewById(R.id.textView);
tv.setMovementMethod(new ScrollingMovementMethod());
L.PRINTLNS.add(new L.Println() {
@Override
public int invoke(int priority, final String tag, final String msg) {
if (MainActivity.this.debugStartTime == -1) {
MainActivity.this.debugStartTime = System.currentTimeMillis();
}
final long time = System.currentTimeMillis() - MainActivity.this.debugStartTime;
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
tv.append(String.format("[%d] %s.%s\n", time, tag, msg));
}
});
return 0;
}
});
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public final class L {
public static final String MAGICAL_EXPENSIVE_AUTO_TAG = "JPgpKvpxrnB1zrs8WnGqVNTeK0NgMyY8SXnMEaXPnTY=";
public final static List<Println> PRINTLNS = new ArrayList<>();
private final static String[] NAMES_OF_EXCLUDED_CLASSES = new String[]{L.class.getName()};
private static ThreadLocal<StackTraceElement> callerStackTraceElement;
static {
PRINTLNS.add(new Println() {
@Override
public int invoke(int priority, String tag, String msg) {
return Log.println(priority, tag, msg);
}
});
}
public static int v(String tag, String msg) {
return println(Log.VERBOSE, tag, msg);
}
public static int v(String tag, String msg, Throwable tr) {
return println(Log.VERBOSE, tag, msg + '\n' + Log.getStackTraceString(tr));
}
public static int d(String tag, String msg) {
return println(Log.DEBUG, tag, msg);
}
public static int d(String tag, String msg, Throwable tr) {
return println(Log.DEBUG, tag, msg + '\n' + Log.getStackTraceString(tr));
}
public static int i(String tag, String msg) {
return println(Log.INFO, tag, msg);
}
public static int i(String tag, String msg, Throwable tr) {
return println(Log.INFO, tag, msg + '\n' + Log.getStackTraceString(tr));
}
public static int w(String tag, String msg) {
return println(Log.WARN, tag, msg);
}
public static int w(String tag, String msg, Throwable tr) {
return println(Log.WARN, tag, msg + '\n' + Log.getStackTraceString(tr));
}
public static int w(String tag, Throwable tr) {
return println(Log.WARN, tag, Log.getStackTraceString(tr));
}
public static int e(String tag, String msg) {
return println(Log.ERROR, tag, msg);
}
public static int e(String tag, String msg, Throwable tr) {
return println(Log.ERROR, tag, msg + '\n' + Log.getStackTraceString(tr));
}
public static int dt() {
return dt(null);
}
public static int dt(String msg) {
SetCaller();
try {
String s = callerStackTraceElement.get().getMethodName();
if (msg != null) {
s += " " + msg;
}
return d(MAGICAL_EXPENSIVE_AUTO_TAG, s);
} finally {
UnsetCaller();
}
}
private static void SetCaller() {
final StackTraceElement ste = CallerClassTool.getCallerStackTraceElement(NAMES_OF_EXCLUDED_CLASSES);
callerStackTraceElement = new ThreadLocal<>();
callerStackTraceElement.set(ste);
}
private static void UnsetCaller() {
callerStackTraceElement.remove();
callerStackTraceElement = null;
}
private static String SimpleClassName() {
String className = callerStackTraceElement.get().getClassName();
int i = className.lastIndexOf('.');
if (i != -1) {
className = className.substring(i + 1);
}
return className;
}
public static int println(int priority, String tag, String msg) {
if (tag.equals(MAGICAL_EXPENSIVE_AUTO_TAG)) {
tag = SimpleClassName();
}
int numberOfBytesWritten = 0;
for (Println pln : PRINTLNS) {
numberOfBytesWritten += pln.invoke(priority, tag, msg);
}
return numberOfBytesWritten;
}
public interface Println {
int invoke(int priority, String tag, String msg);
}
}
public class CallerClassTool {
public static StackTraceElement getCallerStackTraceElement(String[] namesOfExcludedClasses) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String callerClassName = null;
for (int i = 1; i < stackTrace.length; i++) {
StackTraceElement ste = stackTrace[i];
String className = ste.getClassName();
if (className.indexOf("java.lang.Thread") == 0) {
continue;
}
if (className.equals(CallerClassTool.class.getName())) {
continue;
}
for (String excl : namesOfExcludedClasses) {
if (className.equals(excl)) {
continue;
}
}
if (callerClassName == null) {
callerClassName = className;
} else if (!callerClassName.equals(className)) {
return ste;
}
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment