【问题标题】:Node.js: log ignored errorsNode.js:记录忽略的错误
【发布时间】:2016-03-07 00:06:46
【问题描述】:

node.js 中是否有任何方法可以记录所有异常?

process.on('uncaughtException') 对我来说还不够,因为我需要记录所有捕获和未捕获的异常,即使代码中某处有一个 catch 只是忽略/吞下了错误。

你们觉得node.js有可能吗?

【问题讨论】:

  • 创建一个新的控制台并将两个输出流定向到文件。如果您正在处理错误,那么只需添加 console.error( // 您的错误...然后您将记录所有错误。请参阅 Node.js 文档 Console.
  • 我知道我可以记录 node.js 代码中的所有异常,但现在我正在寻找一种解决方案来捕获所有异常,而无需触及引发异常的代码部分。
  • 如果您发现错误并忽略它们,您将无法追踪它们。
  • 是否可以修改 node.js 源代码?
  • 如果应用程序正在捕获异常并将它们丢弃(想到这让我感到恶心)并且这是一个您无法控制的第 3 方应用程序,除非哈利波特编写了编译器,否则它是需要一些魔法才能记录这些错误 - 远远超出我的麻瓜能力。

标签: javascript node.js


【解决方案1】:

实现此目的的一个 hacky 方法是使用调试上下文:

const vm = require('vm');

const Debug = vm.runInDebugContext('Debug'); // Obtain Debug object

Debug.setListener((type, _, e) => { // listen for all debug events
  if (type == Debug.DebugEvent.Exception) {
    console.log(e.exception().stack) // e is an event object
  }
});

Debug.setBreakOnException(); // this is required for Exception event to fire

try {
  throw new Error('bla');
} catch(e) {
  // ha
}

警告:不要将此代码留在生产环境中,仅用于调试。

显然,它不会调用异步错误,因为它们实际上并没有被抛出,它们只是被创建以传递给回调。

另一种方法是替换可能的错误构造函数:

const OldError = Error;
const MyError = function(message) {
  const err = new OldError(message);
  OldError.captureStackTrace(err, MyError); // remove top frame from stack trace

  console.log(err.stack);

  return err;
}

MyError.prototype = Error.prototype; // Fix instanceof
global.Error = MyError;

try {
  throw new Error('bla');
} catch(e) {
}


new Error('blabla');

这样你也可以处理异步错误,但不会看到除了实例Error之外的东西是否被抛出。

如果你只对 Promise 感兴趣并且你正在使用原生 v8 Promise,那么你可以试试这个:

const vm = require('vm');

const Debug = vm.runInDebugContext('Debug');

Debug.setListener((type, _, e) => {
  if (type == Debug.DebugEvent.PromiseEvent) {
    if (e.status() === -1) { // 0=pending, 1=resolved, -1=rejected
      console.log(e.value().value().stack);
    }
  }
});



Promise.reject(new Error('test'))
  .catch(() => {});

它可能会产生一些重复,因为它会捕获子承诺拒绝以及原始承诺拒绝。

【讨论】:

    【解决方案2】:

    您可以附加一个调试器,如 node-inspector,并在 node-inspector 中激活选项 。这不会记录异常,但会暂停执行,这足以找到 3rd 方模块中的怪癖。

    如果您使用 WebStorm,您可以将未捕获的异常记录到控制台或文件中。启动 WebStorm 调试器后打开断点对话框并根据 激活“JavaScript 异常断点”和断点操作的“任何异常”设置@

    【讨论】:

      【解决方案3】:

      如果您吞下异常,您将无法跟踪它们。 如果您认为您正在使用的模块忽略了异常,那么您正在使用错误的模块或者您没有正确使用它。

      如果您使用 Express,正确的方法是使用 next(err) 重定向所有异常和错误。

      异常将被传递给错误处理程序(注意函数中的四个参数),您可以在那里记录它们:

      router.get('/', function (req, res, next) {
          // your logic
      
          if(err) {
              return next(err);
          }
      
      
          return next();
      });
      
      
      // Error handler
      app.use(function(err, req, res, next) {
      
          console.log(err.stack);
      
          res.status(err.status || 500).json({
              error: {
                  code: err.code,
                  message: err.message
              }
          });
      
          next(err);
      });
      

      【讨论】:

      • 它不会记录任何被捕获和忽略的错误。
      • 当然,如果你忽略它,你怎么能记录它呢?
      • 你不能。如果异常被忽略,它就会被丢弃。这就是为什么忽略或吞下异常是不好的。我不明白为什么你不能避免忽略异常。
      • @zangw 我猜是因为这不是问题的具体答案,但问题本身是不可能回答的。无论如何,您仍然可以调试模块并查看它在哪里吞下了异常(这对我来说似乎很奇怪,也许您使用了错误的模块或不正确。它是哪个模块?您可以发布一些代码吗?)。
      • 根据我的经验,这些错误几乎从来都不是由于模块或库中的错误,而是由于对它们的“错误”使用。也许你应该在你有问题的地方添加代码并问“这个承诺没有得到解决,为什么?”
      猜你喜欢
      • 1970-01-01
      • 2011-09-22
      • 2018-10-18
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 2017-08-23
      • 2013-03-15
      • 2018-04-15
      相关资源
      最近更新 更多