Android日志优化:获取调用Logger类的类名作为TAG
问题
我正在写一个仅在Debug构建时输出日志的Logger类,目前TAG是硬编码字符串。希望将TAG设置为调用Logger方法的类名(例如在Splash.kt中调用时,TAG显示Splash.kt)。参考Jake Wharton的Timber库通过栈轨迹实现,但未能成功获取调用类名,仅得到Logger类自身的名称,求可行实现方法。
现有Logger类代码:
import me.entri.entrime.BuildConfig import me.entri.entrime.utils.Constants object Logger { private val TAG = Constants.LOGGING_TAG @JvmStatic fun d(message : Any?){...} // 其余日志方法省略 }
测试调用示例:
try{ val error = 4384/0 }catch(e : Exception){ Logger.e("message") }
解决方案
核心是正确遍历栈轨迹,跳过Logger类自身的栈帧,定位到真正的调用方栈帧。直接取栈顶元素会拿到Logger类内部方法的栈信息,因此需要循环过滤掉当前Logger类及系统相关的栈元素。
修改后的Logger类实现:
import me.entri.entrime.BuildConfig import android.util.Log object Logger { private val isDebug = BuildConfig.DEBUG @JvmStatic fun d(message: Any?) { if (isDebug) { val tag = getCallerClassName() Log.d(tag, message.toString()) } } @JvmStatic fun e(message: Any?, throwable: Throwable? = null) { if (isDebug) { val tag = getCallerClassName() if (throwable != null) { Log.e(tag, message.toString(), throwable) } else { Log.e(tag, message.toString()) } } } // 获取调用方类名 private fun getCallerClassName(): String { val stackTrace = Thread.currentThread().stackTrace // 遍历栈帧,排除Logger自身和系统类 for (element in stackTrace) { val className = element.className if (!className.startsWith(Logger::class.java.name) && !className.startsWith("java.lang.Thread") && !className.startsWith("android.util.Log")) { // 提取类名后缀并添加.kt标识 return className.substringAfterLast(".") + ".kt" } } // 兜底返回默认TAG return "UnknownLogger" } }
说明
getCallerClassName方法通过遍历线程栈轨迹,过滤掉Logger类、Thread类等系统相关栈帧,找到第一个真正的调用方类,提取类名后缀并加上.kt后缀,符合需求。- 仅当
BuildConfig.DEBUG为true时才输出日志,满足Debug构建专属日志的要求。 - 其他日志级别方法(如v、i、w)可参照d、e方法的逻辑扩展。
内容的提问来源于stack exchange,提问作者Saneen K P
相关产品推荐
相关产品推荐

