按日期创建log文件、error和res分别在两个文件夹
// /config/log4js_config.jsmodule.exports = {appenders: {// 默认日志console: {type: 'console',},//错误日志errorLogger: {// category: 'errorLogger', //logger名称type: 'dateFile', //日志类型filename: 'logs/error/error', // 日志输出位置alwaysIncludePattern: true, // 是否总是有后缀名pattern: 'yyyy-MM-dd.log', // 后缀},//响应日志resLogger: {// category: 'resLogger',type: 'dateFile',filename: 'logs/response/response',alwaysIncludePattern: true,pattern: 'yyyy-MM-dd.log',},},//设置logger名称对应的的日志等级categories: {default: {appenders: ['console'],level: 'All',},errorLogger: {appenders: ['errorLogger'],level: 'error',},resLogger: {appenders: ['resLogger'],level: 'all',},},};
封装打印内容
// /utils/log_util.jsconst log4js = require('log4js');const loggerConfig = require('../config/log4js_config');// 加载配置文件log4js.configure(loggerConfig);const logger = {};const errorLogger = log4js.getLogger('errorLogger');const resLogger = log4js.getLogger('resLogger');// 封装错误日志logger.logError = (error, resTime, requestBody) => {if (error) {errorLogger.error(formatError(error, resTime, requestBody));}};// 封装响应日志logger.logResponse = (response, resTime, requestBody) => {if (response) {resLogger.info(formatRes(response, resTime, requestBody));}};// 封装控制台打印logger.log = title => {return log4js.getLogger(title);};// 格式化响应日志const formatRes = (response, resTime, requestBody) => {let logText = '';// 响应日志开始logText += '\n' + '*************** response log start ***************' + '\n';// 添加请求日志logText += formatReqLog(response.request, resTime, requestBody);// 响应状态码logText += 'response statusCode: ' + response.statusCode + '\n';// 响应内容logText += 'response body: ' + '\n' + JSON.stringify(response.body) + '\n';// 响应日志结束logText += '*************** response log end ***************' + '\n';return logText;};// 格式化错误日志const formatError = (err, resTime, requestBody) => {let logText = '';// 错误信息开始logText += '\n' + '*************** error log start ***************' + '\n';// 添加请求日志logText += formatReqLog(err.options, resTime, requestBody);// 错误名称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;};// 格式化请求日志const formatReqLog = (req, resTime, requestBody) => {let logText = '';const method = req.method;// 访问方法logText += 'request method: ' + method + '\n';// 请求原始地址logText += 'request originalUrl: ' + (req.uri && req.uri.href || req.uri) + '\n';// 请求参数if (method === 'GET') {logText += 'request query: ' + JSON.stringify(req.uri.query) + '\n';} else {logText += 'request body: ' + '\n' + JSON.stringify(requestBody) + '\n';}// 服务器响应时间logText += 'response time: ' + resTime + 'ms' + '\n';return logText;};module.exports = logger;
request时使用(同时也是node端请求封装)
// /utils/request.jsconst rp = require('request-promise');const axios = require('axios');const config = require('../config/constants');const logger = require('./log_util');const requestConfig = {baseUrl: config.baseUrl,resolveWithFullResponse: false};const rpWithLogger = (options, bodyKey) => {const startTime = new Date();let ms = 0;return rp(options).then(res => {ms = new Date() - startTime;logger.logResponse(res, ms, options[bodyKey]);return res.body;},err => {ms = new Date() - startTime;logger.logError(err, ms, options[bodyKey]);return { code: 504, msg: '网关超时', err };});};exports.get = (uri, param = {}, opts) => {const options = {uri,method: 'GET',qs: param,...requestConfig,...opts};return rpWithLogger(options, 'param');};exports.post = (uri, body, opts) => {const options = {uri,method: 'POST',body: body,...requestConfig,...opts,json: true,resolveWithFullResponse: true};return rpWithLogger(options, 'body');};exports.upload = (uri, formData, opts) => {const options = {uri,method: 'POST',formData: formData,...requestConfig,...opts};return rp(options);};exports.download = (uri, param = {}, opts) => {// 此处用 axios 请求,定义 responseType 为 stream 进行下载return axios.get(config.baseUrl + uri, {responseType: 'stream', // 注意此处要用 streamparams: param,data: {},...opts});};
配置内容需根据需求自行修改,当然不修改也能用。
完整koa模板示例:https://www.yuque.com/xiebugde/mbz0hg/tg5c7c
