Skip to content

Instantly share code, notes, and snippets.

@shkschneider
Last active November 21, 2021 03:51
Show Gist options
  • Save shkschneider/4a9849468b80deb172a9 to your computer and use it in GitHub Desktop.
Save shkschneider/4a9849468b80deb172a9 to your computer and use it in GitHub Desktop.
Android Log helper (automatic class, method and line) replacing android.util.Log
package me.shkschneider.skeleton.helper;
import android.text.TextUtils;
import android.util.Log;
/**
* Improved android.util.Log.
*
* Logs class and method automatically:
* [MyApplication onCreate():34] Hello, world!
* [MyClass myMethod():42] my log msg
*
* Install:
* $ find -name "*.java" -type f -exec sed -i 's/import android.util.Log/import me.shkschneider.skeleton.helper.Log/g' {} \;
*
* Better to use with adb -s com.example.myapp
*/
public class Log {
protected Log() {
// Empty
}
private static final int VERBOSE = Log.VERBOSE;
private static final int DEBUG = Log.DEBUG;
private static final int INFO = Log.INFO;
private static final int WARN = Log.WARN;
private static final int ERROR = Log.ERROR;
private static final int WTF = Log.ASSERT;
// Used to identify the source of a log message.
// It usually identifies the class or activity where the log call occurs.
protected static String TAG = "LogHelper";
// Here I prefer to use the application's packageName
protected static void log(final int level, final String msg, final Throwable throwable) {
final StackTraceElement[] elements = new Throwable().getStackTrace();
String callerClassName = "?";
String callerMethodName = "?";
String callerLineNumber = "?";
if (elements.length >= 4) {
callerClassName = elements[3].getClassName();
callerClassName = callerClassName.substring(callerClassName.lastIndexOf('.') + 1);
if (callerClassName.indexOf("$") > 0) {
callerClassName = callerClassName.substring(0, callerClassName.indexOf("$"));
}
callerMethodName = elements[3].getMethodName();
callerMethodName = callerMethodName.substring(callerMethodName.lastIndexOf('_') + 1);
if (callerMethodName.equals("<init>")) {
callerMethodName = callerClassName;
}
callerLineNumber = String.valueOf(elements[3].getLineNumber());
}
final String stack = "[" + callerClassName + "." + callerMethodName + "():" + callerLineNumber + "]" + (TextUtils.isEmpty(msg) ? "" : " ");
switch (level) {
case VERBOSE:
android.util.Log.v(TAG, stack + msg, throwable);
break ;
case DEBUG:
android.util.Log.d(TAG, stack + msg, throwable);
break ;
case INFO:
android.util.Log.i(TAG, stack + msg, throwable);
break ;
case WARN:
android.util.Log.w(TAG, stack + msg, throwable);
break ;
case ERROR:
android.util.Log.e(TAG, stack + msg, throwable);
break ;
case WTF:
android.util.Log.wtf(TAG, stack + msg, throwable);
break ;
default:
break ;
}
}
public static void d(@NonNull final String msg) {
log(DEBUG, msg, null);
}
public static void d(final String msg, @NonNull final Throwable throwable) {
log(DEBUG, msg, throwable);
}
public static void v(@NonNull final String msg) {
log(VERBOSE, msg, null);
}
public static void v(final String msg, @NonNull final Throwable throwable) {
log(VERBOSE, msg, throwable);
}
public static void i(@NonNull final String msg) {
log(INFO, msg, null);
}
public static void i(final String msg, @NonNull final Throwable throwable) {
log(INFO, msg, throwable);
}
public static void w(@NonNull final String msg) {
log(WARN, msg, null);
}
public static void w(final String msg, @NonNull final Throwable throwable) {
log(WARN, msg, throwable);
}
public static void e(@NonNull final String msg) {
log(ERROR, msg, null);
}
public static void e(final String msg, @NonNull final Throwable throwable) {
log(ERROR, msg, throwable);
}
public static void wtf(@NonNull final String msg) {
log(WTF, msg, null);
}
public static void wtf(final String msg, @NonNull final Throwable throwable) {
log(WTF, msg, throwable);
}
@Deprecated
public static void wtf(@NonNull final Throwable throwable) {
log(WTF, null, throwable);
}
}
@adrien-aubel
Copy link

Isn't creating a Throwable kind of expensive? Maybe an annotation processor could be a good alternative!

@shkschneider
Copy link
Author

Thanks for the feedback!
I was trying not to use annotations and was happy to see this code working, but indeed getting the StackTrace on production logging could be expensive: https://stackoverflow.com/a/10625065/603270
I'll look into it.

@shkschneider
Copy link
Author

Referenced by https://github.com/zserge/log, which is nice BTW

@shkschneider
Copy link
Author

Improvements: class now substitutes to android.util.Log and accepts Throwables.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment