• 03-Android App logger策略


    背景

    经常会为log定位而烦恼。比如:同一个类,一样的log输出,无法定位到Log输出的行。

    方案

    1.java StackTraceElement

    通过java StackTraceElement获取类名,以及log输出行

    2. 具体实现
    1. @NonNull
    2. private static String getSourcePoint()
    3. {
    4. final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    5. assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";
    6. final StackTraceElement st = stackTrace[CALL_STACK_INDEX];
    7. StringBuilder sb = new StringBuilder(80);
    8. final String fileName = st.getFileName();
    9. if (fileName != null)
    10. {
    11. sb.append(fileName);
    12. final int lineNumber = st.getLineNumber();
    13. if (lineNumber >= 0)
    14. sb.append(':').append(lineNumber);
    15. sb.append(' ');
    16. }
    17. sb.append(st.getMethodName()).append("()");
    18. return sb.toString();
    19. }
    3. logger.java实现
    1. package com.app.test.util.log;
    2. import android.util.Log;
    3. import androidx.annotation.Keep;
    4. import androidx.annotation.NonNull;
    5. import androidx.annotation.Nullable;
    6. import com.app.test.BuildConfig;
    7. import net.jcip.annotations.ThreadSafe;
    8. @ThreadSafe
    9. public final class Logger
    10. {
    11. private static final String TAG = Logger.class.getSimpleName();
    12. private static final String CORE_TAG = "APP";
    13. private static final String FILENAME = "app.log";
    14. public static void v(String tag)
    15. {
    16. log(Log.VERBOSE, tag, "", null);
    17. }
    18. public static void v(String tag, String msg)
    19. {
    20. log(Log.VERBOSE, tag, msg, null);
    21. }
    22. public static void v(String tag, String msg, Throwable tr)
    23. {
    24. log(Log.VERBOSE, tag, msg, tr);
    25. }
    26. public static void d(String tag)
    27. {
    28. log(Log.DEBUG, tag, "", null);
    29. }
    30. public static void d(String tag, String msg)
    31. {
    32. log(Log.DEBUG, tag, msg, null);
    33. }
    34. public static void d(String tag, String msg, Throwable tr)
    35. {
    36. log(Log.DEBUG, tag, msg, tr);
    37. }
    38. public static void i(String tag)
    39. {
    40. log(Log.INFO, tag, "", null);
    41. }
    42. public static void i(String tag, String msg)
    43. {
    44. log(Log.INFO, tag, msg, null);
    45. }
    46. public static void i(String tag, String msg, Throwable tr)
    47. {
    48. log(Log.INFO, tag, msg, tr);
    49. }
    50. public static void w(String tag, String msg)
    51. {
    52. log(Log.WARN, tag, msg, null);
    53. }
    54. public static void w(String tag, String msg, Throwable tr)
    55. {
    56. log(Log.WARN, tag, msg, tr);
    57. }
    58. public static void e(String tag, String msg)
    59. {
    60. log(Log.ERROR, tag, msg, null);
    61. }
    62. public static void e(String tag, String msg, Throwable tr)
    63. {
    64. log(Log.ERROR, tag, msg, tr);
    65. }
    66. // Index of stacktrace depth where the original log method call resides.
    67. private static final int CALL_STACK_INDEX = 3;
    68. @NonNull
    69. private static String getSourcePoint()
    70. {
    71. final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    72. assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";
    73. final StackTraceElement st = stackTrace[CALL_STACK_INDEX];
    74. StringBuilder sb = new StringBuilder(80);
    75. final String fileName = st.getFileName();
    76. if (fileName != null)
    77. {
    78. sb.append(fileName);
    79. final int lineNumber = st.getLineNumber();
    80. if (lineNumber >= 0)
    81. sb.append(':').append(lineNumber);
    82. sb.append(' ');
    83. }
    84. sb.append(st.getMethodName()).append("()");
    85. return sb.toString();
    86. }
    87. // Also called from JNI to proxy native code logging (with tag == null).
    88. @Keep
    89. private static void log(int level, @Nullable String tag, @NonNull String msg, @Nullable Throwable tr)
    90. {
    91. if (BuildConfig.DEBUG || level >= Log.INFO)
    92. {
    93. final StringBuilder sb = new StringBuilder(180);
    94. // Add source point info for file logging, debug builds and ERRORs if its not from core.
    95. if (tag != null && (BuildConfig.DEBUG || level == Log.ERROR))
    96. sb.append(getSourcePoint()).append(": ");
    97. sb.append(msg);
    98. if (tr != null)
    99. sb.append('\n').append(Log.getStackTraceString(tr));
    100. if (tag == null)
    101. tag = CORE_TAG;
    102. if (logsFolder == null || BuildConfig.DEBUG)
    103. Log.println(level, tag, sb.toString());
    104. }
    105. }
    106. private static char getLevelChar(int level)
    107. {
    108. switch (level)
    109. {
    110. case Log.VERBOSE:
    111. return 'V';
    112. case Log.DEBUG:
    113. return 'D';
    114. case Log.INFO:
    115. return 'I';
    116. case Log.WARN:
    117. return 'W';
    118. case Log.ERROR:
    119. return 'E';
    120. }
    121. assert false : "Unknown log level " + level;
    122. return '_';
    123. }
    124. }
    4. 结果:

    如上图,可以看到log输出java的类名,以及行。 

    总结

  • 相关阅读:
    智能合约安全分析,Vyper 重入锁漏洞全路径分析
    Win32 - 窗口
    CMake个人理解和使用
    MySQL内部存储代码常用实现方式
    C++ Primer学习笔记-----第一章:开始
    建立Logistic模型进行分析--课后习题3(多元统计分析)
    rsync下行同步+inotify实时同步部署
    02 - QT 自定义控件封装
    Python + HDF5 因子计算与 DolphinDB 一体化因子计算方案对比
    一文彻底搞懂 JS 闭包
  • 原文地址:https://blog.csdn.net/liaochaoyun/article/details/133939428