Java中打印日志的坑(不打印堆栈信息)

Posted 石头StoneWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中打印日志的坑(不打印堆栈信息)相关的知识,希望对你有一定的参考价值。

背景

打印日志的大坑。很多同事不打印堆栈信息直接这么写

log.error("exception occur! param1:{},param2:{}", param1, param2);

log.error("exception occur! param1:{}", e.getMessage());

log.error("exception occur! param1:{}", e.toString());

这真的是个大坑,没有堆栈信息有时候很难排查问题。

首先 getMessage() 是异常的信息,只是很简短的信息,比如 /by zero 这个就是除零异常 getMessage() 得到的。

其次,e.toString() 会让人以为返回了完整的堆栈信息(以字串形式),但其实不是,返回的跟 getMessage() 几乎是一样的。

toString() 的源码

public String toString() {
    String s = getClass().getName();
    String message = getLocalizedMessage();
    return (message != null) ? (s + ": " + message) : s;
}

public String getLocalizedMessage() {
    return getMessage();
}

public String getMessage() {
    return detailMessage;
}

可以看到 getMessage()e.toString() 其实区别要么是完全一样,要么是前面加了个类名和冒号和空格(s + ": ")

解决

一定要杜绝上面的写法。虽然lombok的 @Slf4j 提供的log,其打印日志的方法比较蛋疼,如果要打印 异常e就没法使用占位符 {},但是我们可以使用拼接的方式,参数多的时候用String.format 也是可以的

正例

log.error("exception occur! tenantId:" + tenantId, e);
// 或者
log.error(String.format("exception occur! tenantId:%s",tenantId), e);

注意,使用 String.format() 的时候,如果占位符 %s 的数量和填充进去的参数的数量不一致会发生运行时异常,这个比较坑。

补充细节:

一定要注意,如果参数数量不一致,会有提醒的。如下的黄底提醒

如果用log,参数不匹配,也会有黄底警告:

补充

打印日志用英文,比较节省,另外也不怕乱码。注意别用了中文逗号!

我觉得可能 log 缺少一个方法,比如

log.info("abc,param1:{},param2:{}", e, param1, param2);

由于缺少这个方法,所以如果想要打印 异常e 的堆栈就得放弃使用 {} 这种占位符

以上是关于Java中打印日志的坑(不打印堆栈信息)的主要内容,如果未能解决你的问题,请参考以下文章

Java编码常见的Log日志打印问题

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情

手机调试Android程序出异常时不打印堆栈信息

EasyNVR日志中堆栈信息打印为字节代码排查及优化

Log4j打印错误异常的详细堆栈信息

Slf4j打印异常的堆栈信息