JavaScript

超轻量级php框架startmvc

node错误处理与日志记录的实现

更新时间:2020-08-09 18:36:01 作者:startmvc
node项目中的错误处理node中Error对象的使用使用captureStackTrace方法加入自带的错误信息//Error

node项目中的错误处理

node中Error对象的使用

使用captureStackTrace方法加入自带的错误信息


// Error对象自带的属性
Error.captureStackTrace

// 如何使用captureStackTrace
var obj = {
 message: 'something is wrong'
}

Error.captureStackTrace(obj)

throw obj // 此时会抛出obj对象的message内信息

使用try catch捕获错误

直接把代码写在try catch中即可捕获错误信息


try{
 throw new Error('oh no')
}catch(e){
 console.log(e)
}

在异步代码中,直接try catch是无法捕获错误信息的,可以使用如下方法


function foo(params, cb){
 const error = new Error('something is wrong')
 if(error) cb(error)
}

以上使用callback方式来做错误处理比较容易麻烦,容易出错,现在node已经支持async await所以尽量使用它们准没错


async function foo(){
 try{
 await bar()
 }catch(e){
 console.log(e)
 }
}

async function bar(){
 throw new Error('async function got wrong)
}

foo()

基本错误类型

在项目会有多个地方对错误信息进行处理,所以先写一个基本错误类型,方便使用


// 基本错误类型
class HttpBaseError extends Error {
 constructor(httpStatusCode, httpMsg, errCode, msg) {
 super(`HTTP ERROR: ${msg}`);
 this.httpStatusCode = httpStatusCode;
 this.httpMsg = httpMsg;
 this.errCode = errCode;
 }
}

try {
// 直接抛出定义好的错误即可
 throw new HttpBaseError(404, '资源不存在', 10000, 'resouse is not found');
} catch (e) {
 console.log(e.message);
 console.log(e.httpStatusCode);
 console.log(e.httpMsg);
 console.log(e.errCode);
}

特定错误类型

除了基本类型,不同情况下会有不同错误信息,需要用一个特定的错误类型来处理特定的错误信息


// 一个参数错误类型
const ERROR_CODE = 40000 // 错误码
class HttpRequestParamError extends HttpBaseError {
 constructor(paramName, desc, msg) {
 super(200, desc, ERROR_CODE, `${paramName} wrong: ${msg}`)
 }
}

这样,在参数错误的地方就能非常方便的调用这个错误类型来返回错误

抛错的逻辑

错误处理中,model,controller中的错误,有些是不能直接返回给用户的,应该只返回给model或controller的调用者。

使用错误处理

正常接口,controller,model的错误,使用设定好的错误类型进行处理,例如前面写的HttpRequestParamError,在所有所有路由的最后,需要使用一个error handler来对所有的错误进行集中处理


// error handler
function handler(options) {
 return function (err, req, res, next) {
 if (err instanceof HttpRequestParamError) { // 这里对不同的错误做不同的处理
 console.log('http request error')
 res.statusCode = err.httpStatusCode
 res.json({
 code: err.errCode,
 msg: err.httpMsg
 })
 } else {
 // 设定之外的错误,把管理权向外移交
 next(err)
 }
 }
}

除了可预知的错误,还有未知的类型的错误,此时需要一个unknow error handler进行剩余错误的处理


function unKnowErrorHandler(options) {
 return function (err, req, res, next) {
 console.log(err)
 res.json({
 code: 99999,
 msg: 'unKnow error'
 })
 }
}

node中的日志

平时使用console来debug是没有问题的,但是在线上环境,我们并不能有效的看到console,使用日志系统可以更好的方便线上的debug,记录信息等

winston的使用

winston是node中常用的日志插件


const winston = require('winston')

const logger = winston.createLogger({
 transports: [
 new winston.transports.Console(),
 new winston.transports.File({
 name: 'info_logger', // log名称
 filename: 'logs/info.log', // 日志记录文件地址
 level: 'info' // 设置log的类型
 }),
 // 第二个logger,记录error级别的log
 new winston.transports.File({
 name: 'error_logger',
 filename: 'logs/error.log',
 level: 'error'
 })
 ]
});

// error级别比info要高,error.log文件只会记录error日志
logger.error('first error log with winston')
// info文件内会记录info级别的log和比info级别高的log,比如error
logger.info('first info log with winston')

日志滚动(log rotation)

在产生大量数据的应用当中,日志的输出是大量的,这是就需要对日志进行拆分处理,例如按照每天的频率来分别记录日志。

winston并不自带log rotation,需要引入winston-daily-rotate-file库


const {
 createLogger,
 format,
 transports
} = require('winston');
const {
 combine,
 timestamp,
 label,
 prettyPrint
} = format;
require('winston-daily-rotate-file')


var transport = new(transports.DailyRotateFile)({
 filename: './logs/app-%DATE%.log',
 datePattern: 'YYYY-MM-DD-HH',
 maxSize: '20m',
 maxFiles: '14d',
 format: combine(
 label({
 label: 'right meow!'
 }),
 timestamp(),
 prettyPrint()
 ),
});
transport.on('rotate', function (oldFilename, newFilename) {});

var logger = createLogger({
 transports: [
 transport
 ]
});

logger.info('Hello World!');

运行日志文件,此时在logs目录下就生成了今天的日志

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

node 错误处理 node 日志 node 错误日志