一、问题
开发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日志内容如下:
|