避免 printStackTrace();改用记录器调用

Posted

技术标签:

【中文标题】避免 printStackTrace();改用记录器调用【英文标题】:Avoid printStackTrace(); use a logger call instead 【发布时间】:2012-05-15 16:43:24 【问题描述】:

在我的应用程序中,我正在通过 PMD 运行我的代码。它向我显示了这条消息:

这是什么意思?

【问题讨论】:

另见When to log a stacktrace for a caught exception 【参考方案1】:

这意味着你应该使用像logback或log4j这样的日志框架,而不是直接打印异常:

e.printStackTrace();

您应该使用此框架的 API 记录它们:

log.error("Ops!", e);

日志框架为您提供了很大的灵活性,例如您可以选择是否要登录到控制台或文件 - 或者如果您发现某些消息在某些环境中不再相关,则可以跳过它们。

【讨论】:

【参考方案2】:

如果您在异常情况下调用printStackTrace(),则跟踪将写入System.err,并且很难将其路由到其他地方(或过滤它)。建议您不要这样做,而是使用日志框架(或多个日志框架的包装器,如 Apache Commons Logging)并使用该框架(例如 logger.error("some exception message", e))记录异常。

这样做可以让您:

一次将日志语句写入不同的位置,例如控制台和文件 按严重性(错误、警告、信息、调试等)和来源(通常基于包或类)过滤日志语句 无需更改代码即可对日志格式产生一定影响 等

【讨论】:

【参考方案3】:

生产质量计划应使用多种日志记录替代方案之一(例如 log4j、logback、java.util.logging)来报告错误和其他诊断。这有很多优点:

日志消息转到可配置的位置。 最终用户看不到消息,除非您配置日志记录以便他/她看到。 您可以使用不同的记录器和记录级别等来控制记录的记录量少或多。 您可以使用不同的附加程序格式来控制日志记录的外观。 您可以轻松地将日志输出插入到更大的监控/日志框架中。 以上所有操作都可以在不更改代码的情况下完成;即通过编辑已部署应用程序的日志记录配置文件。

相比之下,如果您只使用 printStackTrace,部署者/最终用户几乎没有任何控制权,并且日志消息可能会丢失或在不适当的情况下显示给最终用户。 (没有什么比随机堆栈跟踪更能吓到胆小的用户了。)

【讨论】:

【参考方案4】:

在 Simple 中,e.printStackTrace() 不是一个好习惯,因为它只是将堆栈跟踪打印到标准错误。因此,您无法真正控制此输出的去向。

【讨论】:

【参考方案5】:

几乎每个日志框架都提供了一种方法,我们可以在该方法中将可抛出对象与消息一起传递。喜欢:

public trace(Marker marker, String msg, Throwable t);

它们打印可抛出对象的堆栈跟踪。

【讨论】:

这没有回答问题。【参考方案6】:

让我们从公司概念谈起。日志为您提供灵活的级别(请参阅Difference between logger.info and logger.debug)。不同的人希望看到不同的级别,例如 QA、开发人员、业务人员。但是 e.printStackTrace() 将打印出所有内容。另外,如果这个方法会被调用,同样的错误可能会打印多次。那么贵公司的 Devops 或 Tech-Ops 人员可能会发疯,因为他们会收到相同的错误提醒。 我认为更好的替代品可能是log.error("errors happend in XXX", e) 这也会打印出比 e.printStackTrace() 更容易阅读的全部信息

【讨论】:

【参考方案7】:

主要原因是 Proguard 会从生产环境中移除 Log 调用。因为通过记录或打印 StackTrace,可以通过例如 Logcat Reader 应用程序在 android 手机中查看它们(堆栈跟踪或日志中的信息)。因此,这对安全性来说是一种不好的做法。此外,我们不会在生产过程中访问它们,最好从生产中删除。由于 ProGuard 移除所有 Log 调用而不是 stackTrace,所以最好在 catch 块中使用 Log,并让 Proguard 将它们从生产中移除。

【讨论】:

以上是关于避免 printStackTrace();改用记录器调用的主要内容,如果未能解决你的问题,请参考以下文章

java问题,动态修改java类里面的一个方法

执行几个 mongoose 查询:如何改用 Promise?

表插入排序算法

Yii2 RESTful API,带有数据访问对象而不是活动记录

e.printStackTrace()打印在哪里以及如何e.printStackTrace()的内容打印在日志中

sql server数据库性能优化之2-避免使用CTE公用表达式的递归by zhang502219048