如何使用 kotlin.logging 记录堆栈跟踪?

Posted

技术标签:

【中文标题】如何使用 kotlin.logging 记录堆栈跟踪?【英文标题】:How to log stack trace using kotlin.logging? 【发布时间】:2021-02-07 02:29:04 【问题描述】:

我正在使用 kotlin.logging 作为应用程序的日志记录框架。

我希望能够以更易读的方式(可能是 JSON 格式)记录堆栈跟踪:

我正在执行以下操作,但会导致格式非常冗长/不可读:

logger.error("Exception caught in handleIllegalArgumentsException: $e", e.printStackTrace())

仅记录 Throwable 异常时(见下文),它不显示堆栈跟踪:

logger.error("Exception caught in handleIllegalArgumentsException: $e") 

【问题讨论】:

【参考方案1】:

您应该能够使用以下方式获取堆栈跟踪。

logger.error(e) "Exception caught in handleIllegalArgumentsException

【讨论】:

缺少结束报价【参考方案2】:

对于通过谷歌搜索到达这里的人:

由于 Kotlin 1.4 Throwable 有一个扩展方法,允许您将堆栈跟踪作为字符串获取,这基本上可以满足其他答案的建议。


/**
 * Returns the detailed description of this throwable with its stack trace.
 *
 * The detailed description includes:
 * - the short description (see [Throwable.toString]) of this throwable;
 * - the complete stack trace;
 * - detailed descriptions of the exceptions that were [suppressed][suppressedExceptions] in order to deliver this exception;
 * - the detailed description of each throwable in the [Throwable.cause] chain.
 */
@SinceKotlin("1.4")
public actual fun Throwable.stackTraceToString(): String 
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    printStackTrace(pw)
    pw.flush()
    return sw.toString()

这意味着原来的e.printStackTrace()只需更改为e.stackTraceToString()

像这样:

logger.error("Exception caught in handleIllegalArgumentsException: $e.stackTraceToString()") 

【讨论】:

【参考方案3】:

Stacktrace 始终是多行的,而传统的日志记录消息应该是单行的。 所以你需要先save it to a String variable,然后以某种方式替换换行符号(例如用|符号):

logger.error 
    val stacktrace = StringWriter().also  e.printStackTrace(PrintWriter(it)) .toString().trim()
    val singleLineStackTrace = stacktrace.lines().map  it.trim() .joinToString(separator = "|")
    "Exception caught in handleIllegalArgumentsException: $singleLineStackTrace"

那么日志将如下所示:

[main] ERROR Logging - Exception caught in handleIllegalArgumentsException: java.lang.IllegalArgumentException: !!!!|at LoggingKt.main(logging.kt:12)|at LoggingKt.main(logging.kt)

【讨论】:

【参考方案4】:

如果您希望记录器打印异常堆栈跟踪:

try 
    ...
 catch (e: Exception) 
    logger.error("Exception caught:", e)

如果您想要字符串本身(用于进一步操作),您可以使用@Михаил Нафталь 建议的内容:

try 
    ...
 catch (e: Exception) 
    val stacktrace = StringWriter().also  e.printStackTrace(PrintWriter(it)) .toString().trim()
    logger.error("Exception caught: $stacktrace")

这两种方法都会在日志中打印整个堆栈跟踪,例如:

16:41:50.528 [main] ERROR org.myorg.MyClass - Exception caught:
java.lang.IllegalArgumentException: Argument X was not allowed.
    at org.myorg.MyClass.func (MyClass.kt:124)
    at java.base/java.lang.Thread.run(Thread.java:834)
    etc...

我知道它不是回答问题文本中的问题,而是回答问题标题。由于这篇文章是我在谷歌上搜索如何使用 Kotlin 记录堆栈跟踪时得到的第一个建议,我认为这可能对其他人有所帮助。

【讨论】:

以上是关于如何使用 kotlin.logging 记录堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Winston 3 记录完整的堆栈跟踪?

使用 Vala 进行日志记录

如何使用Windows x64记录堆栈帧

如何记录两个断点之间的调用堆栈?

如何记录 Python 3 异常,但没有其堆栈跟踪?

登录Julia时如何捕获完整的堆栈跟踪信息