一、问题

开发web项目过程中,常规的console.log()只是将信息反映在了浏览器的控制台,我们经常需要输出到文本日志文件,以便开发调试和维护排查。

下面介绍log4js在vue项目中的部署与使用。

二.解决方案

1.安装log4j

// 注意:如果只执行npm install XXX,没有指定安装到那种环境下的“后缀”,就会发现node-modules中安装了,但是package.json中没有的情况。
// 1、保存到开发依赖(devDependencies):
npm install log4js @4.1.0 --save-dev
// 2、保存到生产依赖(dependencies):
npm install log4js @4.1.0 --save

2.配置部署

(1).新建配置文件

新建configs目录,并在其下新建一个log.js,该文件主要是log4j的基本配置。代码内容如下:

var path = require('path');

//日志根目录
var baseLogPath = path.resolve(__dirname, '../logs')

//错误日志目录
var errorPath = "/error";
//错误日志文件名
var errorFileName = "error";
//错误日志输出完整路径
var errorLogPath = baseLogPath + errorPath + "/" + errorFileName;
//var errorLogPath = path.resolve(__dirname, "../logs/error/error");

//响应日志目录
var responsePath = "/response";
//响应日志文件名
var responseFileName = "response";
//响应日志输出完整路径
var responseLogPath = baseLogPath + responsePath + "/" + responseFileName;
//var responseLogPath = path.resolve(__dirname, "../logs/response/response");

//响应日志目录
var infoPath = "/info";
//响应日志文件名
var infoFileName = "info";
//响应日志输出完整路径
var infoLogPath = baseLogPath + infoPath + "/" + infoFileName;
module.exports = {
  //日志格式等设置
    appenders:
    {
        "rule-console": {"type": "console"},
        "errorLogger": {
            "type": "dateFile",
            "filename": errorLogPath,
            "pattern": "-yyyy-MM-dd.log",
            "alwaysIncludePattern": true,
            "encoding":"utf-8",
            "maxLogSize": 1000,
            "numBackups": 3,
            "path":errorPath
        },
        "resLogger": {
            "type": "dateFile",
            "filename": responseLogPath,
            "pattern": "-yyyy-MM-dd.log",
            "alwaysIncludePattern": true,
            "encoding":"utf-8",
            "maxLogSize": 1000,
            "numBackups": 3,
            "path":responsePath
        },
        "infoLogger": {
            "type": "dateFile",
            "filename": infoLogPath,
            "pattern": "-yyyy-MM-dd.log",
            "alwaysIncludePattern": true,
            "encoding":"utf-8",
            "maxLogSize": 1000,
            "numBackups": 3,
            "path":infoPath
        },
    },
   //供外部调用的名称和对应设置定义
    categories: {
        "default": {"appenders": ["rule-console"], "level": "all"},
        "resLogger": {"appenders": ["resLogger"], "level": "info"},
        "errorLogger": {"appenders": ["errorLogger"], "level": "error"},
        "infoLogger": {"appenders": ["infoLogger"], "level": "info"},
        "http": {"appenders": ["resLogger"],"level": "info"}
    },
    "baseLogPath": baseLogPath 
}
/**
 1、type:console
将日志输出至控制台,这样可以方便开发人员在开发时接看到所有日志信息,在其他环境不建议设置
2、alwaysIncludePattern
如果为true,则每个文件都会按pattern命名,否则最新的文件不会按照pattern命名
3、replaceConsole
如果为true,则程序中用console.log输出到控制台的信息,也会输出到日志文件中,且格式按照log4js的格式输出,如果为false,则console.log只会输出在控制台。与type:console的appender正好相反,如果设置了type:console,则会将log4js.log日志输出至控制台。
4、category
没有看到权威的说明,我的理解category就是一个日志名字,如果没有取应该是默认的。只有当开发人员通过getLogger(category)获得相对应的日志时,才能输出到对应的appender中,否则会发送给所有默认的appender
5、logLevelFilter
没有看到什么文档说明,但实际的例子还是不少,直观理解应该就是根据日志级别进行日志过滤。

filename: __dirname + '/logs/test.log',//文件目录,当目录文件或文件夹不存在时,会自动创建
maxLogSize : 10,//文件最大存储空间,当文件内容超过文件存储空间会自动生成一个文件test.log.1的序列自增长的文件
backups : 3,//default value = 5.当文件内容超过文件存储空间时,备份文件的数量
//compress : true,//default false.是否以压缩的形式保存新文件,默认false。如果true,则新增的日志文件会保存在gz的压缩文件内,并且生成后将不被替换,false会被替换掉
encoding : 'utf-8',//default "utf-8",文件的编码
 */

其中,首行的path是引入了path模块,可以方便的设置当前路径的别名,然后将path.resolve(__dirname, '../logs')引用给变量baseLogPath ,后面不用每次都引入“../logs”这样的路径。当然你也可以不用path模块,自己收到设置路径也可以,这里只是顺便介绍一下该工具的使用。path的安装命令如下:

npm  install  path  --save

以上设置了error,response,info三种文件输出,你可以根据自己需求只输出其中一种或几种。

(2)新建工具文件logUtil.js

该类是给提供给需要输出日志的其他文件使用的,包含了自定义输出日志的格式。

var log4js = require('log4js');

var log_config = require('../configs/log');

//加载配置文件
log4js.configure(log_config);

var logUtil = {};
//调用预先定义的日志名称
var resLogger = log4js.getLogger("resLogger");
var errorLogger = log4js.getLogger("errorLogger");
var consoleLogger = log4js.getLogger("infoLogger");


//封装错误日志
logUtil.logError = function (ctx, error, resTime) {
    if (ctx && error) {
        errorLogger.error(formatError(ctx, error, resTime));
    }
};

//封装响应日志
logUtil.logResponse = function (ctx, resTime) {
    if (ctx) {
        resLogger.info(formatRes(ctx, resTime));
    }
};

logUtil.info = function (info) {
    if (info) {
        console.log(info);
        consoleLogger.info(info);
        //consoleLogger.info( formatInfo(info));
    }
};
logUtil.error = function (info) {
    if (info) {       
        consoleLogger.error( formatInfo(info));
    }
};

var formatInfo = function (info) {
    var logText = new String();
    //响应日志开始
    logText += "\n" + "***************info log start ***************" + "\n";

    //响应内容
    logText += "info detail: " + "\n" + JSON.stringify(info) + "\n";

    //响应日志结束
    logText += "*************** info log end ***************" + "\n";

    return logText;
}

//格式化响应日志
var formatRes = function (ctx, resTime) {
    var logText = new String();
    //响应日志开始
    logText += "\n" + "*************** response log start ***************" + "\n";

    //添加请求日志
    logText += formatReqLog(ctx.request, resTime);

    //响应状态码
    logText += "response status: " + ctx.status + "\n";

    //响应内容
    logText += "response body: " + "\n" + JSON.stringify(ctx.body) + "\n";

    //响应日志结束
    logText += "*************** response log end ***************" + "\n";

    return logText;

}

//格式化错误日志
var formatError = function (ctx, err, resTime) {
    var logText = new String();

    //错误信息开始
    logText += "\n" + "*************** error log start ***************" + "\n";

    //添加请求日志
    logText += formatReqLog(ctx.request, resTime);

    //错误名称
    logText += "err name: " + err.name + "\n";
    //错误信息
    logText += "err message: " + err.message + "\n";
    //错误详情
    logText += "err stack: " + err.stack + "\n";

    //错误信息结束
    logText += "*************** error log end ***************" + "\n";

    return logText;
};

//格式化请求日志
var formatReqLog = function (req, resTime) {

    var logText = new String();

    var method = req.method;
    //访问方法
    logText += "request method: " + method + "\n";

    //请求原始地址
    logText += "request originalUrl:  " + req.originalUrl + "\n";

    //客户端ip
    logText += "request client ip:  " + req.ip + "\n";

    //开始时间
    var startTime;
    //请求参数
    if (method === 'GET') {
        logText += "request query:  " + JSON.stringify(req.query) + "\n";
        // startTime = req.query.requestStartTime;
    } else {
        logText += "request body: " + "\n" + JSON.stringify(req.body) + "\n";
        // startTime = req.body.requestStartTime;
    }
    //服务器响应时间
    logText += "response time: " + resTime + "\n";

    return logText;
}

module.exports = logUtil;

(3).如何使用

以下是Demo.js文件中的调用log方式。引用工具类logUtil后,在需要输出日志的地方可以直接使用

logUitl.info("")的方式进行输出。

const logUtil = require('../utils/logUtil');

....

	//获取设备的信息
	let getDeviceInfo = async()=>{
		let estr='获取设备的信息===';
		logUtil.info(estr);
		await namedQuery('CustomsPushService/getDeviceStatus',{},result=>{
			deviceInfoData = result;
			logUtil.info(estr+'总记录数:'+deviceInfoData.length);
			logUtil.info(deviceInfoData);
		});
	}

例如输出info.-2021-11-25.log日志内容如下:

Logo

前往低代码交流专区

更多推荐