记录nodejs使用express搭建一个api服务器程序(3)-封装非常好用的日志输出功能log4js

此文章是我自己用来记录如何搭建一个以express为基础的api服务器框架的过程,并不是什么新手教程,并不会每一步都写得非常详细,如果您要阅读此文,需要一点nodejs和编写代码的基础知识

文接上篇 链接: 地址 https://blog.csdn.net/goodboy31985/article/details/106236505
在上文基础上,修改和完善api服务器的框架

使用express搭建一个api服务器,处理http请求-增加好用的日志功能

用log4js包 来增强和优化日志

我们在进行开发和日常维护的时候,都需要大量用到日志功能,一些必要的信息和错误可以打在日志中,供我们排查问题,但是nodejs本身提供的日志功能偏弱,
比如我在代码中想要输出一行信息,并且打印一个错误,此时运行代码,控制台会出现以下的log信息
在这里插入图片描述
在这里插入图片描述
日志中既没有时间,普通的log也没有代码位置,而且也无法方便得打印到日志文件中.

因此,我们需要一个强大且方便的工具来增强日志功能
强烈建议使用log4js 这个包来增强日志功能,下面是我封装好log4js后的输出日志
在这里插入图片描述
同样的代码,现在有了时间戳,文件位置,函数名,提供的信息比之前多了很多,并且同时将日志信息打印到了文件中,方便以后查看
在这里插入图片描述
并且log4js 还可以区分不同的日志级别,比如开发时候需要打印debug,但是项目上线以后只需要打印info或者是error等,只需要将打印级别作为运行时候的参数,就可以不动任何代码的情况下,适应不同的使用场景

封装log4js包,重写console.log的功能

  1. 使用npm命令 下载log4js的包
    npm install --save log4js
  2. 新建一个LogHelper类,用来封装log4js的功能,并重写console.log
    在这里插入图片描述
    文件内容
// 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习惯和代码,可以做到完全无感
只需要在项目入口最前端,加入初始化
在这里插入图片描述
本节内容主要是封装了一个好用的日志功能,方便我们的调试和运维,下节我们将为此框架增加更多的功能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章