当前位置: 首页 > 后端技术 > Node.js

一个node系统的日志管理

时间:2023-04-03 17:33:04 Node.js

好久没研究节点系统的日志管理了。在需求不饱和的时候,想通过学习群里成熟的节点系统,模仿搭建一个“健全”的节点系统。一般来说,第一步必须是如何配置基本信息才能使系统运行。但。..就是不会日志管理,想研究logger的使用方法,所以。.我会写第一篇文章,如何做这个系统的日志管理。我用的node框架是express,日志管理工具是log4js。什么时候需要记录什么信息?我总结了下几条可能需要记录的信息,可以根据实际情况增减1、前端请求。(方便排错)2.返回的response。3.系统间的交互。一个成熟的项目不应该只有一个节点系统。我认为节点更多地充当中间层。node能处理的问题,node能处理的话,java童鞋不嫌麻烦,但是一些不适合node处理的问题,比如CPU密集型或者逻辑复杂的,就必须要java童鞋处理了。虽然多了一个http请求,但是这些时间其实可以忽略不计。所以node调用各种系统接口的时候,我觉得打印body和response还是很有必要的。除了帮助排查问题,关键时候也能不背锅。3.其他手动记录器。如何使用?1、一个req请求贯穿整个请求。前端请求和返回的响应与req请求相关。如果这个log4js挂载在req上,那么我们使用起来会很方便。Express中间件可以帮助我们实现这个功能。Usage:req.logger.info(msg)2.node系统与其他java系统交互。一个成熟的系统肯定会将这种请求交互封装成一个类,这样我们只要在这个类的请求方法中进行logger,我们就可以写在一个地方,每次请求都会自动logger,对用户来说是无所谓且方便的。logger的分类log4js支持ALL、TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF8,但一般使用info和error两种。虽然同一个文件可以存放不同类型的日志,但是将信息类型和错误类型分开存放有几个好处:1.可以监控错误日志类型,及时告警。2.可改善储存时间。不同的是,info类型保存近15天,error类型保存近1个月。3、如果节点系统与多个系统交互,比如A系统有账户相关功能,B系统有文章相关功能,C系统有商品相关功能等,此时也可以登录按系统分类:系统A的日志在一个文件夹,系统B的日志在一个文件夹。并根据日志的多少,分年、月、日、时存储。对日志进行分类,都是为了方便排查问题!日志文件具有以下结构:systemA--error--2018-09-26.log--info--2018-09-26.logsystemB--error--2018-09-26.log--info--2018-09-26-17.log--2018-09-26-18.log实施说了这么多,马上实施吧。首先配置log4js。//simpleType.js这个js定义了有哪些系统类型(有哪些文件夹)module.exports=['systemA','systemB','systemC','systemD']//logger.js这个js初始化配置并初始化constpath=require('path')constfs=require('fs')constlog4js=require('log4js')constcategory=require('./simpleTypes')letlogger_conf={appenders:{console:{type:'console'}},replaceConsole:true,//控制台日志类别:{default:{appenders:['console'],level:'info'}}}constDEFAULT_PATTERN='yyyy-MM-dd-hh.log'if(process.env.UAE_MODE){/生产环境category.forEach(c=>{letdirPath=path.join(__dirname,`../logs/${c}`)只有日志文件if(!fs.existsSync(dirPath))fs.mkdirSync(dirPath);让infoPath=路径。加入(dirPath,“信息/”);让errorPath=path.join(dirPath,'error/');['Info','Error'].forEach(type=>{//其实我觉得这里的配置有点Error,请指出logger_conf.appenders[`${c}${type}`]={类型:'dateFile',模式:DEFAULT_PATTERN,文件名:infoPath,alwaysIncludePattern:true,类别:`${c}${type}`}logger_conf.categories[`${c}${type}`]={appenders:[`${c}${type}`,'console'],level:type.toLowerCase()}})})}if(logger_conf.appenders){for(logger_conf.appenders中的varkey){if(logger_conf.appenders[key].filename)checkFile(logger_conf.appenders[key].filename)//必须有文件夹,否则会报错}}log4js.configure(logger_conf)functioncheckFile(dir){if(!fs.existsSync(dir)){fs.mkdirSync(dir);}}module.exports=log4js;//对外暴露一个log4js实例配置,即使用第一个req挂载使用方法:req.systemAInfo.info('reqloggermsg')//middleware/logger.jsmiddleware文件夹专门存放中间件,后续文章会讲constlog4js=require('../logger/logger')constsimpleTypes=require('../logger/simpleTypes')module.exports=function(req){simpleTypes.forEach(system=>{['Info','Error'].forEach(type=>{varlog=`${system}${type}`req[log]=log4js.getLogger(log)})})}//index.jsapp.use('*',function(req,res,next){reqLogger(req)//通过express中间件挂载next()到req})至于系统层面,每个系统类继承一个Base类,在Base类中实现//Base.jsconstrequest=require('request')constlog4js=require('../logger/logger')module.exports=classBase{constructor(id){this.id=id;}request(opts,cb){letinfoLogger=log4js.getLogger(`${this.id}Info`)leterrorLogger=log4js.getLogger(`${this.id}Error`)opts=this._requestFilter(opts)//各个系统的认证letbody=JSON.stringify(opts)infoLogger.info(body)request(opts,(err,res,body)=>{if(err)errorLogger.error(JSON.stringify(err))elseif(body&&body.error)errorLogger.error(JSON.stringify(body.error))else{infoLogger.info(JSON.stringify(body))cb(err,body)}})}_requestFilter(opts){returnJSON.parse(JSON.stringify(opts))}}//systemA.jsconstBase=require('./Base')classsystemAextendsBase{constructor(){super('systemA')}_requestFilter(){//systemA的鉴权,下篇}}mudole.exports=systemA好了,一个日志管理就初步形成了