有什么理由不总是记录堆栈跟踪?
今天我们的应用程序遇到了一个令人沮丧的问题,该问题归结为抛出 ArrayIndexOutOfBounds 异常。异常的类型几乎是所有记录的内容,这是相当无用的(但是,哦,亲爱的遗留应用程序,我们仍然最喜欢你)。我已经重新部署了应用程序,并进行了一项更改,该更改记录了异常处理的堆栈跟踪(并立即找到了问题的根本原因),并想知道为什么以前没有人这样做。您通常会记录堆栈跟踪吗?您有什么理由不这样做吗?
如果您能解释(为什么,而不是如何)必须在 java 中跳圈以获得堆栈跟踪的字符串表示形式的基本原理,那就加分了!
Encountered a frustrating problem in our application today which came down to an ArrayIndexOutOfBounds
exception being thrown. The exception's type was just about all that was logged which is fairly useless (but, oh dear legacy app, we still love you, mostly). I've redeployed the application with a change which logs the stack trace on exception handling (and immediately found the root cause of the problem) and wondered why no one else did this before. Do you generally log the stack trace and is there any reason you wouldn't do this?
Bonus points if you can explain (why, not how) the rationale behind having to jump hoops in java to get a string representation of a stack trace!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
某些日志可能包含敏感数据,日志设施不一定足够安全,无法在生产中跟踪该数据。
某些日志可能包含
记录太多可能会导致太多信息,即系统管理员根本没有任何信息。如果他们的日志充满了调试消息,他们将无法识别可疑模式。 (几年前,我看到一个系统出于安全原因记录所有系统调用。日志太多,当一些非特权用户开始成为 root 时,没有人看到它。)
最好的办法是使用适当的日志级别记录所有内容,并且能够在生产中设置日志级别(至少在 Java 中不是一个大问题)。
Some logs might contain sensitive data, log facilities are not necessarily secure enough to track that data in production.
Logging to much can result in too much information, i.e. no information at all for the sysadmins. If their logs are filled up with debug messages, they won't be able to recognize suspicious patterns. (Years ago I saw a system logging all system calls for security reasons. There were so many logs, that nobody saw it when some unprivileged users started to become root.)
Best thing to do to log everything with appropriate log levels, and be able to set log levels in production (at least in Java not that a big issue).
另请参阅这些问题
Java 日志记录和一般情况:最佳实践?< /a>
从多个线程进行 Java 日志记录的最佳实践?
这里需要考虑的重要事项
和时间
Please see these questions also
Logging in Java and in general: Best Practices?
Best practices for Java logging from multiple threads?
Important things here to consider
and time
我通常会记录堆栈跟踪,因为它包含用于故障排除/调试问题的信息。这是仅次于小型转储的最佳想法,通常只需通过代码检查和识别问题即可找到解决方案。
顺便说一句,我同意 sibidiba 的观点,即完整堆栈公开了有关应用程序内部结构的潜在信息泄露:函数名称以及堆栈调用序列可以向受过教育的读者传达很多信息。这就是为什么有些产品只在堆栈上记录符号地址,并依赖开发人员从内部 pdb 将地址解析为名称的原因。
但我认为将文本记录到包含 1 行错误和 14 行堆栈的文件中会使浏览错误日志变得非常困难。它还会导致高并发应用程序出现问题,因为日志文件上的锁定保持时间更长(或更糟糕的是,日志文件会交错)。我自己多次遇到这些问题,以及在支持和排除我自己的应用程序部署方面的其他问题,导致我实际上在 bugcollect.com。在设计错误收集策略时,我选择每次收集堆栈转储,并将堆栈用作存储桶键的一部分(将同一堆栈上发生的错误分组到同一存储桶中)。
I generally do log the stack trace, because it has information for troubleshooting/debugging the problem. It's the best think next to a minidump and often leads to a solution simply by code inspection and identifying the problem.
BTW, I agree with sibidiba about the potential information disclosure about your app internals a full stack exposes: the function names, along with the stack call sequence, can tell a lot to an educated reader. This is the reason why some products only log the symbol address on the stack, and rely on the devs to resolve the address to the name from internal pdbs.
But in I reckon that logging text into files containing 1 line of error and 14 lines of stack makes it very difficult to navigate the error logs. It also causes problem on high concurency apps because the lock on the log file is held longer (or worse, the log files get interleaved). Having encountered these problems my self many times, along with other issues in supporting and troubleshooting deployments of my own apps, led me to actually create a service for logging errors at bugcollect.com. When designing the error collection policies I chose to collect the stack dumps every time, and to use the stacks as part of the bucket keys (to group errors that happen on the same stack into same bucket).
当开发人员日志记录过于随意并且系统管理员发现应用程序一旦处于生产负载下时,就会破坏并用巨大的日志文件填充硬盘,从而常常会突破对日志记录的限制。然后,很难让他们相信您已经看到了自己的方式错误,并且已经充分减少了日志记录(或调整了日志级别),但确实需要那些剩余的日志条目。
Restrictions on logging are often pushed through when developers log too liberally and sysadmins discover that the app, once put under a production load, thrashes and fills the HD with huge log files. It can then be hard to convince them that you've seen the error of your ways and have reduced logging (or adjusted log levels) sufficiently but really need those remaining log entries.
对于我们来说,这非常简单:如果抛出意外异常,我们会记录堆栈跟踪以及尽可能告知的消息。
我的猜测是,在问题中编写原始代码的开发人员根本没有足够的经验来知道仅凭消息是不够的。我也这么想,有一次。
将堆栈跟踪作为字符串获取是很复杂的原因是因为 JRE 中没有 StringPrintWriter - 我相信思路是它们提供了许多正交构建块,然后您可以根据需要组合这些构建块。您必须自己组装所需的 PrintWriter。
For us it is very simple: If there is an unexpected exception thrown, we log the stack trace along with as telling a message as possible.
My guess is that the developer who wrote the original code in the question, simply wasn't experienced enough to know that it is not enough with just the message. I thought so too, once.
The reason why it is convoluted to get a stack trace as a string is because there is no StringPrintWriter in the JRE - I believe the line of thinking has been that they provide a lot of orthogonal building blocks which you then combine as needed. You have to assemble the needed PrintWriter yourself.
难道你不应该只记录可抛出的内容而不是通过循环来打印堆栈跟踪吗?像这样:log.error(“部署失败!”,ex)。给定一个 throwable,Log4J 将打印通过 getMessage() 获得的错误消息和堆栈跟踪。
Shouldn't you just log the throwable instead of going through hoops to print the stacktrace? Like this: log.error("Failed to deploy!", ex). Given a throwable, Log4J will print both the error message obtained via getMessage() and the stack trace.
我见过很多代码记录这样的异常:
因为 log4j 接受一个 Object 作为第一个参数,所以它将记录异常的字符串表示形式,这通常只是类的名称。这通常只是开发人员的疏忽。最好像这样记录和错误:
..这样,如果配置正确,日志框架将记录堆栈跟踪。
What I've seen a lot is code logging an exception like this:
Because log4j accepts an Object as the first argument, it will log the String representation of the Exception, which is often only the name of the class. This is usually just an oversight on the developer's part. It's better to log and error like this:
..so that if configured properly, the logging framework will log the stack trace.