背景
经常会为log定位而烦恼。比如:同一个类,一样的log输出,无法定位到Log输出的行。
方案
1.java StackTraceElement
通过java StackTraceElement获取类名,以及log输出行
2. 具体实现
@NonNullprivate static String getSourcePoint(){final StackTraceElement[] stackTrace = new Throwable().getStackTrace();assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";final StackTraceElement st = stackTrace[CALL_STACK_INDEX];StringBuilder sb = new StringBuilder(80);final String fileName = st.getFileName();if (fileName != null){sb.append(fileName);final int lineNumber = st.getLineNumber();if (lineNumber >= 0)sb.append(':').append(lineNumber);sb.append(' ');}sb.append(st.getMethodName()).append("()");return sb.toString();}
3. logger.java实现
package com.app.test.util.log;import android.util.Log;import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.app.test.BuildConfig;
import net.jcip.annotations.ThreadSafe;@ThreadSafe
public final class Logger
{private static final String TAG = Logger.class.getSimpleName();private static final String CORE_TAG = "APP";private static final String FILENAME = "app.log";public static void v(String tag){log(Log.VERBOSE, tag, "", null);}public static void v(String tag, String msg){log(Log.VERBOSE, tag, msg, null);}public static void v(String tag, String msg, Throwable tr){log(Log.VERBOSE, tag, msg, tr);}public static void d(String tag){log(Log.DEBUG, tag, "", null);}public static void d(String tag, String msg){log(Log.DEBUG, tag, msg, null);}public static void d(String tag, String msg, Throwable tr){log(Log.DEBUG, tag, msg, tr);}public static void i(String tag){log(Log.INFO, tag, "", null);}public static void i(String tag, String msg){log(Log.INFO, tag, msg, null);}public static void i(String tag, String msg, Throwable tr){log(Log.INFO, tag, msg, tr);}public static void w(String tag, String msg){log(Log.WARN, tag, msg, null);}public static void w(String tag, String msg, Throwable tr){log(Log.WARN, tag, msg, tr);}public static void e(String tag, String msg){log(Log.ERROR, tag, msg, null);}public static void e(String tag, String msg, Throwable tr){log(Log.ERROR, tag, msg, tr);}// Index of stacktrace depth where the original log method call resides.private static final int CALL_STACK_INDEX = 3;@NonNullprivate static String getSourcePoint(){final StackTraceElement[] stackTrace = new Throwable().getStackTrace();assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";final StackTraceElement st = stackTrace[CALL_STACK_INDEX];StringBuilder sb = new StringBuilder(80);final String fileName = st.getFileName();if (fileName != null){sb.append(fileName);final int lineNumber = st.getLineNumber();if (lineNumber >= 0)sb.append(':').append(lineNumber);sb.append(' ');}sb.append(st.getMethodName()).append("()");return sb.toString();}// Also called from JNI to proxy native code logging (with tag == null).@Keepprivate static void log(int level, @Nullable String tag, @NonNull String msg, @Nullable Throwable tr){if (BuildConfig.DEBUG || level >= Log.INFO){final StringBuilder sb = new StringBuilder(180);// Add source point info for file logging, debug builds and ERRORs if its not from core.if (tag != null && (BuildConfig.DEBUG || level == Log.ERROR))sb.append(getSourcePoint()).append(": ");sb.append(msg);if (tr != null)sb.append('\n').append(Log.getStackTraceString(tr));if (tag == null)tag = CORE_TAG;if (logsFolder == null || BuildConfig.DEBUG)Log.println(level, tag, sb.toString());}}private static char getLevelChar(int level){switch (level){case Log.VERBOSE:return 'V';case Log.DEBUG:return 'D';case Log.INFO:return 'I';case Log.WARN:return 'W';case Log.ERROR:return 'E';}assert false : "Unknown log level " + level;return '_';}
}
4. 结果:
如上图,可以看到log输出java的类名,以及行。
总结
略