简体   繁体   English

Nodejs在生产中调试错误

[英]Nodejs debug errors in production

I have a nodejs script running in production 我有一个在生产中运行的nodejs脚本

I unlikely (once in thousand times) get errors like this: 我不太可能(曾经一千次)得到这样的错误:

TypeError: value is out of bounds
    at checkInt (buffer.js:1009:11)
    at Buffer.writeUInt16LE (buffer.js:1067:5)
    at Object.foo.bar (/fake/path/name.js:123:1);
    at Object.foo.bar2 (/fake/path/name2.js:123:1);
    at Object.foo.bar3 (/fake/path/name3.js:123:1);

Causing the production server to crash... 导致生产服务器崩溃......

Great I have a stacktrace! 太棒了我有一个堆栈跟踪! But I want to know what it's current data is for each call or all the data? 但我想知道每个电话或所有数据的当前数据是什么?

What are some great tools or code to use to for error logging(with it's current data) on production code? 有什么好的工具或代码可用于生产代码的错误记录(使用它的当前数据)?

I highly recommend in using either Winston or Bunyan . 我强烈建议使用WinstonBunyan The selection of npm package is a decision of your application. 选择npm包是您的应用程序的决定。

You can benchmark the available npm packages by going through the stats in the available in npm pages. 您可以通过浏览npm页面中可用的统计信息来对可用的npm包进行基准测试。 The stats are basically the following. 统计数据基本上如下。

  1. downloads in the last day 在最后一天下载
  2. downloads in the last week 在上周下载
  3. downloads in the last month 上个月的下载量
  4. open issues and open pull requests. 打开问题和打开拉取请求。

Having higher number of downloads recently will indicate that there is a great support for the module you are using in the long run. 最近有更多的下载量表明从长远来看,您正在使用的模块有很大的支持。 So that is important. 所以这很重要。

Both Winstan and Bunyan being best logging npm packages in the market, the main difference is that, Winstan is really awesome and flexible for normal logging purposes. Winstan和Bunyan都是市场上最好的npm软件包,主要区别在于,Winstan对于正常的日志记录来说非常棒和灵活。 Of course Winstan offers a great deal of logging capabilities. 当然,Winstan提供了大量的日志记录功能。 But how ever, to make use of these capabilities, some effort need to put on compared to Bunyan. 但是,与Bunyan相比,要想利用这些功能,需要付出一些努力。

Bunyan on the other hand is specially support the fact of " analysing logs ". 另一方面,Bunyan特别支持“ 分析日志 ”的事实。 So basically Bunyan is for logs processing. 所以基本上Bunyan用于日志处理。 So if you want to analyse your logs, log files it is highly recommend to use Bunyan. 因此,如果您想分析日志,日志文件,强烈建议您使用Bunyan。 Tweaking logs with Bunyan is fairly easy vis-a-vis to Winstan. 使用Bunyan调整日志对Winstan来说相当容易。

I did a thorough comparison between Bunyan and Winstan. 我对Bunyan和Winstan进行了彻底的比较。 Please do check the link below to view how the Winstan and Bunyan can use depending on the scope, use-case and necessity of the logging to the Node application. 请查看下面的链接,查看Winstan和Bunyan如何使用,具体取决于记录到Node应用程序的范围,用例和必要性。 link : https://docs.google.com/document/d/1pD9PLyxlcHVxxOvserNLO9tAz-QA_Co-xo6cWLhLghc/edit?usp=sharing 链接: https//docs.google.com/document/d/1pD9PLyxlcHVxxOvserNLO9tAz-QA_Co-xo6cWLhLghc/edit?usp=sharing

Also in the Production environment , make sure to use the logging levels wisely. 同样在生产环境中 ,请确保明智地使用日志记录级别。 The mostly used logging levels in production environment are: 生产环境中最常用的日志记录级别是:

  • error 错误
  • info 信息
  • debug 调试

Yoou can use Winston or Pino 你可以使用WinstonPino

With winston you can load many modules for log where you want and maybe store logs online. 使用winston,您可以在需要的地方加载许多模块,也可以在线存储日志。 I never use pino, but i have read good things about it. 我从不使用皮诺,但我已经读过很好的东西。

Set env variables for choose where output your log, for example you wont to show output on stdout only if you are in develop and store online only if the app is in production. 设置env变量以选择输出日志的位置,例如,只有在开发时才会显示stdout上的输出,并且仅当应用程序处于生产状态时才在线存储。

A good way to handle the asynchronous functions in node.js is by using the decofun debug tool . 处理node.js异步函数的一种好方法是使用decofun调试工具

The main feature of it is to parse the code and the names of the anonymous functions according to their context. 它的主要特征是根据其上下文解析代码和匿名函数的名称。

You can deanonymise any anonymous function by running it with deco filename.js 您可以通过使用deco filename.js运行它来任何匿名函数进行解除 匿名

A simple example would be as mentioned in the documentation 一个简单的例子就像文档中提到的那样

function gravy() {
   return function returnedᅠfromᅠgravyᅠㅣlineᅠ2 () {
       return {
         prop: function asᅠpropertyᅠpropᅠㅣlineᅠ4 () {
           setTimeout(function passedᅠintoᅠsetTimeoutᅠㅣlineᅠ5 () {
             console.trace('Getting a trace...');  
           }, 10)

         }
       }
   }
}
Trace: Getting a trace...
    at passedᅠintoᅠsetTimeoutᅠㅣlineᅠ5 [as _onTimeout] (/home/ubuntu/workspace/node_modules/decofun/examples/loadable/index.js:6:22)
    at Timer.listOnTimeout (timers.js:92:15)

Since it comes with embedded cute-stack library which normalises the path to the current directory 因为它带有嵌入式可爱堆栈库,可以规范化当前目录的路径

By applying the command deco examples/loadable --cute table the output would be shown as 通过应用命令deco examples/loadable --cute table ,输出将显示为

在此输入图像描述

The best thing i like about it is that it transforms the functions based upon their calls to the original one as seen in the example from this 喜欢它的是它根据它们对原始函数的调用来转换函数 ,如下例所示

   function one (a, cb) {

}


one('blah', function () {

})

function two () {
  return function () { }
}


function three () {
  return {
    shoe: function () {}
  }
}

function four () {
  return function () { 
    return function () {

    }
  }
}

function five () {
  return function () {
    return function () {
      return function () {
        foo('blue', function () {

        })
      }
    }
  }
}


var six = function () {

}


var seven = function (err, cb) {

  return function () {
    cb(function () {

    })
  }

}

var o = {};
o.eight = function (cb) { }


o.eight(function () { })

o.eight.nine = function () {}
o.eight.nine(function () { })

var o2;

o2 = function () { }


;(function () {}())

!function () { }()



function toodeep () {
  return function () {
    return function () {
      return function () {

        return function () {
          return function () {
            return function () {

              return function () {
                return function () {
                  return function () {

                    return function () {

                    }                     

                  }
                }
              } 

            }
          }
        }        
      }
    }
  }
}

into this 进入这个

function one (a, cb) {

}


one('blah', function passedᅠintoᅠoneᅠㅣlineᅠ6 () {

})

function two () {
  return function returnedᅠfromᅠtwoᅠㅣlineᅠ11 () { }
}


function three () {
  return {
    shoe: function asᅠpropertyᅠshoeᅠㅣlineᅠ17 () {}
  }
}

function four () {
  return function returnedᅠfromᅠfourᅠㅣlineᅠ22 () { 
    return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfourᅠᐳᅠㅣlineᅠ23 () {

    }
  }
}

function five () {
  return function returnedᅠfromᅠfiveᅠㅣlineᅠ30 () {
    return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠㅣlineᅠ31 () {
      return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠᐳᅠㅣlineᅠ32 () {
        foo('blue', function passedᅠintoᅠfooᅠㅣlineᅠ33 () {

        })
      }
    }
  }
}


var six = function asᅠvarᅠsixᅠㅣlineᅠ42 () {

}


var seven = function asᅠvarᅠsevenᅠㅣlineᅠ47 (err, cb) {

  return function returnedᅠfromᅠᐸᅠasᅠvarᅠsevenᅠᐳᅠㅣlineᅠ49 () {
    cb(function passedᅠintoᅠcbᅠㅣlineᅠ50 () {

    })
  }

}

var o = {};
o.eight = function asᅠpropertyᅠeightᅠㅣlineᅠ58 (cb) { }


o.eight(function passedᅠintoᅠoːeightᅠㅣlineᅠ61 () { })

o.eight.nine = function asᅠpropertyᅠnineᅠㅣlineᅠ63 () {}
o.eight.nine(function passedᅠintoᅠeightːnineᅠㅣlineᅠ64 () { })

var o2;

o2 = function asᅠvarᅠo2ᅠㅣlineᅠ68 () { }


;(function IIFEᅠㅣlineᅠ71 () {}())

!function IIFEᅠㅣlineᅠ73 () { }()



function toodeep () {
  return function returnedᅠfromᅠtoodeepᅠㅣlineᅠ78 () {
    return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠㅣlineᅠ79 () {
      return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠㅣlineᅠ80 () {

        return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ82 () {
          return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ83 () {
            return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ84 () {

              return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ86 () {
                return function () {
                  return function () {

                    return function () {

                    }                     

                  }
                }
              } 

            }
          }
        }        
      }
    }
  }
}

Hope this might help a bit! 希望这可能会有所帮助! Cheers! 干杯!

I am using pm2 which is a process manager for node.js and also rollbar error reporting. 我使用的是pm2 ,它是node.js的进程管理器,也是rollbar错误报告。 I think you should define some metrics for the part of your code which this error comes from. 我认为您应该为代码中出现此错误的部分指标。

For any uncaughtException the server will stop in order to make the server keep on running even when there is an uncaught exception what i have done is created a separate collection for storing error, save error once an uncaught exception occurs and returns. 对于任何uncaughtException,服务器将停止以使服务器继续运行,即使存在未捕获的异常,我所做的是创建一个单独的集合来存储错误,一旦发生未捕获的异常并保存错误并返回。

Collection 采集

var ErrorSchema = new mongoose.Schema({
  err_Message:{type:String},
  err_Stack:{type:String},
  date:{type:Date}
});

Controller 调节器

process.on('uncaughtException', function (err) {
    console.log(err);
    console.error((new Date).toUTCString() + ' uncaughtException:', err.message);
    console.error(err.stack);

    var newError = new Error;
    newError.err_Message = err.message;
    newError.err_Stack = err.stack;
    newError.date = moment();
    newError.save(function(saveErr,errData){
        if(!saveErr)
            console.log('New Error is saved');
        else
            console.log('Error in saving error');
    });
    //process.exit(1)
});

The above methods stores the uncaught exception in the Error collection and the process/server does not stops. 上述方法将未捕获的异常存储在Error集合中,并且进程/服务器不会停止。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM