本文将介绍笔者log4j时的一些笔记,以期协助读者规避一些问题。
logjs// src/config/log4js.config.js
/**
* 内置两种布局:my:console(针对控制台、终端)、my:basic(针对文件)
*
* 代码:
const log4js = require('log4js')
const log4jsConfig = require('@/config/log4js.config')
log4js.configure(log4jsConfig)
*/
const path = require('path')
const log4js = require('log4js')
const { Logger } = require('s-utils')
// 配置应用名(英文)数组,根据配置的应用名,生成 appenders 、categories
const appNames = ['nginx', 'tomcat']
/**
* 添加控制台的简单布局
*/
log4js.addLayout('my:console', function (config) {
return function (event) {
const { type, message } = event.data[0]
return `${type}: ${message}`
}
})
/**
* 添加基础布局
*/
log4js.addLayout('my:basic', function (config) {
return function (event) {
return JSON.stringify(event.data[0])
}
})
const appenders = {
'my:stdout': {
type: 'stdout',
layout: { type: 'my:console', separator: ',' },
},
'my:console': {
type: 'console',
layout: { type: 'my:console', separator: ',' },
},
}
const categories = {
default: {
appenders: ['my:console', 'my:stdout'],
level: 'debug',
enableCallStack: false,
},
}
for (const appName of appNames) {
appenders[appName] = {
type: 'dateFile',
filename: path.join(Logger.getDefaultDirPath(appName), appName),
maxLogSize: 2000,
pattern: 'yyyy-MM-dd.txt',
alwaysIncludePattern: true,
backups: 100,
compress: false,
layout: {
type: 'my:basic',
},
}
categories[appName] = {
appenders: [appName, 'my:console', 'my:stdout'],
level: 'debug',
enableCallStack: false,
}
}
module.exports = {
appenders,
categories,
}
log4js基础类// src/logger/index.js
// https://github.com/log4js-node/log4js-example/blob/master/config/log4js.json
// https://log4js-node.github.io/log4js-node/file.html
const log4js = require('log4js')
const moment = require('moment')
const path = require('path')
const { OSUtils, CryptoUtils } = require('s-utils')
/**
* @class Logger
* @classdesc 日志基础类
*/
module.exports = class Logger {
static INFO = 'info'
static ERROR = 'error'
static WARN = 'warn'
static DEBUG = 'debug'
/**
* Creates an instance of Logger.
* @param {string} [appName='log4js'] 应用名称(英文)
* @memberof Logger
*/
constructor (appName = 'log4js') {
// 应用的名称(英文)
this.appName = ''
// 日志信息数组
this.logs = []
// 当前日志的ID
this.id = 0
// log4js实例
this.logger4js = null
this.appName = appName
this.logger4js = this.getLog4jsLogger()
}
/**
* 获取默认日志目录路径
*
* @param {string} appName 应用的名称(英文名)
* @returns {string}
* @memberof Logger
*/
static getDefaultDirPath (appName) {
return path.join(OSUtils.getHomeDirPath(), `logs/${appName}`)
}
/**
* 获取log4js日志实例
*
* @returns {object}
* @memberof Logger
*/
getLog4jsLogger () {
return log4js.getLogger(this.appName)
}
/**
* 获取当前日志数组
*
* @returns {object[]} 当前日志数组
* @memberof Logger
*/
getLogs () {
return this.logs
}
/**
* 清空当前日志数组
*
* @memberof Logger
*/
emptyLogs () {
this.logs.length = 0
}
/**
* 生成日志
*
* @param {string} type 日志类型
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @returns {object} 日志信息对象
* @memberof Logger
*/
generateLogInfo (type, message, extraData = {}) {
const time = moment().format('YYYY-MM-DD HH:mm:ss')
const logInfo = {
// 取md5值
id: CryptoUtils.md5(`${this.id}-${time}`),
type,
message,
time,
extraData,
}
this.id++
return logInfo
}
/**
* 记录日志
*
* @param {string} type 日志类型
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @memberof Logger
*/
log (type, message, extraData = {}) {
var _a
// 内容为空时,不展示日志
if (
!((_a =
message === null || message === void 0 ? void 0 : message.trim) ===
null || _a === void 0
? void 0
: _a.call(message))
) {
return
}
const log = this.generateLogInfo(type, message, extraData)
// 类型对应的日志函数为空时,使用info函数
const logFn = this.logger4js[type]
? this.logger4js[type]
: this.logger4js.info
logFn.call(this.logger4js, log)
this.logs.push(log)
}
/**
* 记录常规日志
*
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @memberof Logger
*/
info (message, extraData = {}) {
this.log(Logger.INFO, message, extraData)
}
/**
* 记录错误日志
*
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @memberof Logger
*/
error (message, extraData = {}) {
this.log(Logger.ERROR, message, extraData)
}
/**
* 记录警告日志
*
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @memberof Logger
*/
warn (message, extraData = {}) {
this.log(Logger.WARN, message, extraData)
}
/**
* 记录调试日志
*
* @param {string} message 日志内容
* @param {object} [extraData={}] 额外的数据,json对象
* @memberof Logger
*/
debug (message, extraData = {}) {
this.log(Logger.DEBUG, message, extraData)
}
}
logger实例log4js在业务项目的入口文件,配置
log4js。必须要先配置后使用。
// src/main.js
const log4js = require('log4js')
const log4jsConfig = require('@/config/log4js.config')
log4js.configure(log4jsConfig)
const logger = new Logger('nginx')
logger.info('This is test info.', { addtional: 'test' })
特别说明:
OSUtils, CryptoUtils是笔者自己工具库里的工具函数,可根据需要使用其他方式来替换。
##. 3.1 按照如上步骤配置log4js之后,并未如期记录日志
请检查是否使用了类似
webpack之类的打包工具。如果使用了,再检查Logger是否适合业务项目一起构建的,如果Logger类是单独构建的,就会导致所做的配置不会生效。因为按照log4js的规则,若要对它正确配置,必须要确保配置时和使用时,在运行的时候是同一个log4js库,如果使用了webpack并且Logger类是单独构建的,单独构建的Logger类里的log4js和业务项目里的log4js不是同一个实例,在业务项目里做的配置,就不会生效。