Javascript 如何使用 node.js 中的堆栈跟踪控制台.记录错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42528677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to console.log an error with stack trace in node.js?
提问by drmrbrewer
I've been trying to debug my node app to find the source of an error in my log that shows up only as "Error: Can't set headers after they are sent", with no trace information or any context.
我一直在尝试调试我的节点应用程序以在我的日志中找到错误的来源,该错误仅显示为“ Error: Can't set headers after they are sent”,没有跟踪信息或任何上下文。
As it happens, I think I've now fixed this... I am using connect-timeoutand I was continuing processing a callback passed to an asynchronous network operation, which callback would eventually try to do a res.send(), despite req.timedouthaving been set to 'true' by connect-timeoutduring the network operation.
碰巧,我想我现在已经解决了这个问题......我正在使用connect-timeout并且我正在继续处理传递给异步网络操作的回调,该回调最终会尝试执行 a res.send(),尽管req.timedout已被设置为“true”connect-timeout在网络运行过程中。
BUT I still can't understand why my log wasn't showing trace information for this error. Anywhere that an error is returned in my code I log it to the console with:
但是我仍然无法理解为什么我的日志没有显示此错误的跟踪信息。在我的代码中返回错误的任何地方,我都会将其记录到控制台:
console.log(err);
If there is trace information available in the errobject, and this seems to be placed in err.stack, shouldn't the above statement dump the whole contentof err(including err.stack) to the console log? My understanding is that I wouldn't be losing any information by doing the above, compared e.g. to:
如果在现有的跟踪信息err的对象,这似乎被放置在err.stack,不应该上述声明转储全部内容的err(包括err.stack)到控制台日志?我的理解是,通过执行上述操作,我不会丢失任何信息,例如与:
console.log(err.stack);
But posts like this oneseem to suggest otherwise (though the linked post has now been updated).
但是像这样的帖子似乎另有暗示(尽管链接的帖子现已更新)。
I actually go further, and add some relevant text to help locate the error:
我实际上更进一步,并添加了一些相关文本来帮助定位错误:
console.log('error in dodgyFunction:', err);
But despite this, I was still only getting "Error: Can't set headers after they are sent", without any of the context I'd put it. Would this be because this console error message is output within an external library (like express)? I thought that external libraries should send errors back to the main code to be dealt with accordingly?
但尽管如此,我仍然只得到“ Error: Can't set headers after they are sent”,没有我所说的任何上下文。这是因为此控制台错误消息是在外部库(如express)中输出的吗?我认为外部库应该将错误发送回主代码以进行相应处理?
Edit: here's an example of where I put my error and timeout checking, at the top of the callback function passed to the async operation:
编辑:这是我将错误和超时检查放在传递给异步操作的回调函数顶部的示例:
var execFile = require('child_process').execFile;
execFile('dodgycommand', options, function(error, stdout, stderr) {
if (req.timedout) {
console.log('timeout detected whilst running dodgycommand, so aborting...');
return;
}
if (error) {
console.log('error running dodgycommand:', error);
res.sendStatus(400);
return;
}
// ... it's safe to continue ...
}
I basically follow this same pattern throughout.
我基本上遵循相同的模式。
回答by drmrbrewer
I've just worked out what was going on, and I hope this will help others to avoid this beginner's error.
我刚刚弄清楚发生了什么,我希望这会帮助其他人避免这个初学者的错误。
For some of my error logging I was using something like the following, using string concatenation to construct the error message:
对于我的一些错误日志记录,我使用了如下内容,使用字符串连接来构造错误消息:
console.log('error in function abc: ' + err + ' whilst doing xyz');
whereas elsewhere I was using something like the following, just passing the pieces of the error message as separate arguments to console.log:
而在其他地方,我使用的是以下内容,只是将错误消息的片段作为单独的参数传递给console.log:
console.log('error in function xyz:', err, 'whilst doing abc');
I now see that these give different results!
我现在看到这些会产生不同的结果!
The former must stringify errso that it can be concatenated with the other parts of the message, and according to this, in doing so it just uses the message part.
前者必须字符串化,err以便它可以与消息的其他部分连接,根据this,这样做时它只使用消息部分。
However, in the latter form the errobject must be processed by console.logunadulterated, and dumped as a whole.
但是,在后一种形式中,err对象必须经过console.log纯正处理,并作为一个整体进行转储。
This explains why I was sometimes not seeing the whole content of the error, as I was expecting, and other times I was.
这解释了为什么有时我没有看到错误的全部内容,正如我所期望的,而其他时候我却看到了。
As for console log messages put there by other libraries, something else to check is that you're not filtering out the 'stack' parts of the log messages in your log viewer... turns out that I was(in order to save on log quota... am using papertrail)... d'oh. I was doing so by filtering out any lines starting with ____at(four spaces followed by 'at'), for example ____at Request.self.callback.
至于其他库放在那里的控制台日志消息,要检查的另一件事是您没有过滤掉日志查看器中日志消息的“堆栈”部分......结果我是(为了节省日志配额......我正在使用papertrail)......天啊。我这样做是通过过滤掉以____at(四个空格后跟“at”)开头的任何行,例如____at Request.self.callback。
回答by Paul
Your pattern looks generally common, though I'll say that as a rule I don't like it, more on that in a second.
你的模式看起来很常见,但我会说作为一项规则我不喜欢它,稍后会更多。
As for your main question, it's really hard to answer it based on what you've provided. If you show the actual code rather than the "I generally follow this pattern", it might help. But it's equally possible that the error was being thrown somewhere that you weren't expecting, and so your console.logwasn't getting called at all.
至于你的主要问题,根据你提供的内容真的很难回答。如果您显示实际代码而不是“我通常遵循此模式”,它可能会有所帮助。但是同样有可能错误被抛出到你没有预料到的地方,所以你console.log根本没有被调用。
Seems like you're looking for best practices, so I'll give you what I think is the best I have found so far.
看起来您正在寻找最佳实践,所以我会给您我认为迄今为止我发现的最佳实践。
First, don't use console.logfor logging. It's not horrible, but you can do much, much better. My favorite is to use morganas middleware for logging request information, and debugfor application logging.
首先,不要console.log用于日志记录。这并不可怕,但你可以做得更好,更好。我最喜欢使用morgan作为中间件记录请求信息,并调试应用程序日志。
With debugyou can set up custom log levels and listen to whatever level you want with whatever level of granularity you want. It's all controlled by setting the DEBUG environment variable, and in production you can redirect to file or whatever other destination you want. Further, many node modules (including Express and Connect) use Debug as their logger under the hood, so by tweaking your DEBUG variable you can see as much or little of their inner logging as you want. veryuseful for figuring out what went wrong where.
随着debug您可以设置自定义日志级别,听你想和你想要的粒度任何级别的任何水平。这一切都通过设置 DEBUG 环境变量来控制,在生产中,您可以重定向到文件或您想要的任何其他目的地。此外,许多节点模块(包括 Express 和 Connect)在后台使用 Debug 作为它们的记录器,因此通过调整 DEBUG 变量,您可以根据需要查看或多或少的内部日志记录。 对于找出哪里出了问题非常有用。
Second, as I said I don't use the pattern you have at all when it comes to routing. I've found it's easy to accidentally send headers more than once if I am not careful, so my middleware always return next()and responses are only sent in actual handlers that I can be sure fire only once. When it comes to error, I always pass next(e)which I can then handle in an error handler function. I also created the praeterlibrary to provide standard errors based on web status codes and a generic error handler.
其次,正如我所说,在路由方面我根本不使用您拥有的模式。我发现如果我不小心,很容易意外地多次发送标头,所以我的中间件总是返回next()并且响应只在我可以确定只触发一次的实际处理程序中发送。当涉及到错误时,我总是通过next(e)它然后我可以在错误处理函数中处理它。我还创建了praeter库,以提供基于 Web 状态代码和通用错误处理程序的标准错误。
The pattern looks something like this:
该模式看起来像这样:
// middleware function to put something on the request object
app.use((req, res, next) => {
MyModel.doSomething((e, thing) => {
if (e) return next(e);
if (!thing) return next(new NotFound()); // NotFound is an error in praeter that equates to a 404.
req.thing = thing;
return next();
});
});
Then later
然后后来
// log in here is a reference to my debug configured log object
app.use((err, req, res, next) => {
log.error(err);
log.error(err.stack);
return res.status(err.statusCode || 500).send(err.message)
});
Note this is a simple example of a final error handler. I often have several of these where I might handle different error codes differently, depending on application needs.
请注意,这是最终错误处理程序的简单示例。我经常有几个这样的地方,我可能会根据应用程序的需要以不同的方式处理不同的错误代码。
回答by Zanon
I've installed nnow and I can confirm the following:
我现在已经安装了n,我可以确认以下内容:
Node 4.0.0
节点 4.0.0
Using console.log(err)prints only the error message.
使用console.log(err)仅打印错误消息。
Node 7.7.0(latest)
节点 7.7.0(最新)
Using console.log(err)prints the error message and the full stack.
使用console.log(err)打印错误消息和完整堆栈。
I've confirmed that this behavior changed on version 6.0.0. So, if you use an older version, I suggest that you update your Node.js or use console.log(err.stack)instead to print the full stack.
我已经确认此行为在 6.0.0 版上发生了变化。因此,如果您使用旧版本,我建议您更新 Node.js 或使用console.log(err.stack)打印完整堆栈。

