此文章是我自己用来记录如何搭建一个以express为基础的api服务器框架的过程,并不是什么新手教程,并不会每一步都写得非常详细,如果您要阅读此文,需要一点nodejs和编写代码的基础知识
文接上篇 链接: 地址 https://blog.csdn.net/goodboy31985/article/details/106236505
在上文基础上,修改和完善api服务器的框架
使用express搭建一个api服务器,处理http请求-增加好用的日志功能
- 用log4js包 来增强和优化日志
- 封装log4js包,重写console.log的功能
用log4js包 来增强和优化日志
我们在进行开发和日常维护的时候,都需要大量用到日志功能,一些必要的信息和错误可以打在日志中,供我们排查问题,但是nodejs本身提供的日志功能偏弱,
比如我在代码中想要输出一行信息,并且打印一个错误,此时运行代码,控制台会出现以下的log信息
日志中既没有时间,普通的log也没有代码位置,而且也无法方便得打印到日志文件中.
因此,我们需要一个强大且方便的工具来增强日志功能
强烈建议使用log4js 这个包来增强日志功能,下面是我封装好log4js后的输出日志
同样的代码,现在有了时间戳,文件位置,函数名,提供的信息比之前多了很多,并且同时将日志信息打印到了文件中,方便以后查看
并且log4js 还可以区分不同的日志级别,比如开发时候需要打印debug,但是项目上线以后只需要打印info或者是error等,只需要将打印级别作为运行时候的参数,就可以不动任何代码的情况下,适应不同的使用场景
封装log4js包,重写console.log的功能
- 使用npm命令 下载log4js的包
npm install --save log4js - 新建一个LogHelper类,用来封装log4js的功能,并重写console.log
文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | // lib/common/LogHelper.ts import log4js, { configure, getLogger } from "log4js" import path from 'path' import { rootDir } from "../../start"; export class LogHelper { static logger: log4js.Logger; //trace debug info warn error fatal //输出级别 static logLevel: string = 'trace'; static logLevelDefine:any = { "trace": 1, "debug": 2, "info": 3, "warn": 4, "error": 5, "fatal":6, } static Init() { //可以用环境变量的形式,向程序传递不同的打印级别,适应不同的场景 if (process.env.LOG_LEVEL) { LogHelper.logLevel = process.env.LOG_LEVEL; } configure({ pm2: process.env.NODE_ENV === 'production',//如果使用pm2运行nodejs,可以设置运行环境为 production pm2InstanceVar: 'INSTANCE_ID', disableClustering: true, //配置不同的输出目的地-这里同时打印到文件 和 控制台 appenders: { logFile: { type: 'file', filename: path.join(rootDir, '../logs/', new Date().toLocaleDateString()+'.log'), //设置文件储存路径,这里用日期作为文件名 maxLogSize: 500000, backups: 5, replaceConsole: true }, console: { type: 'console', replaceConsole: true }, }, //配置不同的logger类别 //trace debug info warn error fatal categories: { default: { appenders: ['console', 'logFile'], level: LogHelper.logLevel }, }, }); LogHelper.logger = getLogger("default"); // log4js.shutdown( // function () // { // LogHelper.info("Server Stop"); // LogHelper.info(""); // }); //重写系统的log debug warn等,代替系统原来的打印功能 console.log = function (message: any, ...args: any[]) { //首先判断打印级别 if (LogHelper.logLevelDefine[LogHelper.logLevel]>LogHelper.logLevelDefine.debug) { return; } //为了拿到文件名,行数,函数名等信息,需要解析堆栈信息 let stackInfoStr = LogHelper.stackInfo(); //重新拼装内容,文件名+行数+方法名 let info = `[${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})]`; //调用log4js的打印 LogHelper.logger.debug(info, message, ...args); }; console.debug = function (message: any, ...args: any[]) { if (LogHelper.logLevelDefine[LogHelper.logLevel] > LogHelper.logLevelDefine.debug) { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `[${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})]`; LogHelper.logger.debug(info, message, ...args); }; console.warn = function (message: any, ...args: any[]) { if (LogHelper.logLevelDefine[LogHelper.logLevel] > LogHelper.logLevelDefine.warn) { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `[${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})]`; LogHelper.logger.warn(info, message, ...args); }; console.error = function (message: any, ...args: any[]) { if (LogHelper.logLevelDefine[LogHelper.logLevel] > LogHelper.logLevelDefine.error) { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `[${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})]`; LogHelper.logger.error(info, message, ...args); }; console.info = function (message: any, ...args: any[]) { if (LogHelper.logLevelDefine[LogHelper.logLevel] > LogHelper.logLevelDefine.info) { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `[${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})]`; LogHelper.logger.info(info, message, ...args); }; } //获取堆栈内容 static stackInfo(num:number=0) { var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/i; var stackReg2 = /at\s+()(.*):(\d*):(\d*)/i; let err = new Error(); var stacklist = err.stack.split('\n').slice(3); var s = stacklist[num]; var sp = stackReg.exec(s) || stackReg2.exec(s); var data: any = {}; if (sp && sp.length === 5) { data.method = sp[1]; data.path = sp[2]; data.line = sp[3]; data.pos = sp[4]; data.file = path.basename(data.path); } return data; } } |
这样我们就封装好了一个LogHelper,由于我们重写的系统的log函数,因此,不需要改变我们原有的log习惯和代码,可以做到完全无感
只需要在项目入口最前端,加入初始化
本节内容主要是封装了一个好用的日志功能,方便我们的调试和运维,下节我们将为此框架增加更多的功能