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



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

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

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

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

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

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

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

logger.error(e) { 
"Exception caught in handleIllegalArgumentsException" 
}

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

由于Kotlin 1.4 Throwable有一个扩展方法,允许您将Stack Trace作为String获取,这基本上是按照其他答案的建议执行的。


/**
* 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()}") 

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

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

如果你想要字符串本身(用于进一步操作(,你可以使用@mМи

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记录堆叠比赛时得到的第一个建议,我认为这可能会帮助其他人。

Stacktrace始终是多行的,而传统的日志记录消息应该是单行的。因此,您需要首先将其保存到String变量中,然后以某种方式替换换行符号(例如用|符号(:

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)