Comparing version 1.1.1 to 2.0.0
177
index.js
'use strict'; | ||
const AbstractLevel = require('./lib/classes/AbstractLevel'); | ||
const AbstractAppender = require('./lib/classes/AbstractAppender'); | ||
const ConsoleAppender = require('./lib/classes/ConsoleAppender'); | ||
const { isValid, setLevels, eachLevel } = require('./lib/util'); | ||
const output = require('./lib/output'); | ||
const assert = require('assert'); | ||
const { isNil, isObject, isString } = require('celia'); | ||
const { addAppender, getAppender } = require('./lib/appender'); | ||
const { addLayout, getLayout } = require('./lib/layout'); | ||
const { normalizeLevel, isLevelEnabled, setLevels } = require('./lib/util'); | ||
const defaultLevels = require('./lib/levels'); | ||
class Console extends AbstractLevel { | ||
const { isArray } = Array; | ||
const { stringify } = JSON; | ||
class Logger { | ||
/** | ||
@@ -17,87 +21,90 @@ * 创建logger实例 | ||
static getLogger(loggerName, options) { | ||
return new Console(loggerName, options); | ||
return new Logger(loggerName, options); | ||
} | ||
/** | ||
* 日志操作类 | ||
* @param {String} loggerName 日志分类 | ||
* @param {Object} options | ||
*/ | ||
* 日志操作类 | ||
* @param {String} loggerName 日志分类 | ||
* @param {Object} options | ||
*/ | ||
constructor(loggerName, options) { | ||
super(options); | ||
assert(!isNil(loggerName), `Invalid log name ${loggerName}`); | ||
this.name = loggerName; | ||
options = this.options; | ||
options = options || {}; | ||
this.setLevels(defaultLevels, options.level || 'INFO'); | ||
this.appenders = [options.defaultAppender || { type: 'console' }]; | ||
} | ||
this._makeLogMethod = this._makeLogMethod.bind(this); | ||
set level(level) { | ||
const nlevel = normalizeLevel(level); | ||
assert(nlevel !== null, `Invalid log level ${level}`); | ||
this._level = nlevel; | ||
} | ||
let { levels } = options; | ||
if (levels) { | ||
this.setLevels(levels); | ||
} else { | ||
// 重置级别相关的函数 | ||
eachLevel(this._makeLogMethod); | ||
} | ||
get level() { | ||
return this._level; | ||
} | ||
this.appenders = (options.appenders || []) | ||
.concat(ConsoleAppender) | ||
.map(Appender => new Appender(loggerName, options)); | ||
set appenders(appenders) { | ||
assert(isArray(appenders), `Invalid appenders config ${stringify(appenders)}`); | ||
this._appenders = appenders.map((appenderConfig) => { | ||
if (isString(appenderConfig)) { | ||
appenderConfig = { type: appenderConfig }; | ||
} | ||
const Appender = getAppender(appenderConfig.type); | ||
return new Appender(appenderConfig); | ||
}); | ||
} | ||
/** | ||
* 构造日志方法 | ||
* @param {Object} param | ||
* 设置新的日志级别 | ||
* @param {Array<object>} levels | ||
* @param {String} defaultLevel | ||
*/ | ||
_makeLogMethod({ level }) { | ||
this[level.toLocaleLowerCase()] = function (...args) { | ||
return this._log(level, args); | ||
}; | ||
setLevels(levels, defaultLevel) { | ||
const lastLevels = this._levels; | ||
if (lastLevels) { | ||
lastLevels.forEach(({ level }) => { | ||
delete this[level.toLocaleLowerCase()]; | ||
}); | ||
} | ||
setLevels(levels, ({ level }) => { | ||
this[level.toLocaleLowerCase()] = function (...args) { | ||
return this._log(level, args); | ||
}; | ||
}); | ||
this._levels = levels; | ||
this.level = defaultLevel; | ||
} | ||
/** | ||
* 记录日志 | ||
* @param {String} level 级别 | ||
* @param {Array} args 日志内容 | ||
* 追加Appender对象 | ||
* @param {Object} appenderConfig | ||
*/ | ||
_log(level, args) { | ||
if (this.isLevelEnabled(level)) { | ||
const { name } = this; | ||
this.appenders.forEach((appender) => { | ||
appender.append(args, { | ||
level, | ||
timestamp: Date.now(), | ||
logger: name | ||
}); | ||
}); | ||
} | ||
return this; | ||
addAppender(appenderConfig) { | ||
let type; | ||
assert(isObject(appenderConfig) && (type = appenderConfig.type), `Invalid appender ${stringify(appenderConfig)}`); | ||
const Appender = getAppender(type); | ||
this._appenders.push(new Appender(appenderConfig)); | ||
} | ||
/** | ||
* 记录日志,兼容console.log | ||
* @param {String} level 级别 | ||
* @param {...} args 日志内容 | ||
* 判断当前级别是否启用 | ||
* @param {String} l | ||
*/ | ||
log(level, ...args) { | ||
if (!isValid(level)) { | ||
args.unshift(level); | ||
level = 'ALL'; | ||
} | ||
return this._log(level.toLocaleUpperCase(), args); | ||
isLevelEnabled(l) { | ||
return isLevelEnabled(this.level, l); | ||
} | ||
/** | ||
* 设置日志级别种类 | ||
* @param {Array} levels | ||
* 记录日志 | ||
* @param {String} level 级别 | ||
* @param {...any} args 日志内容 | ||
*/ | ||
setLevels(levels) { | ||
if (levels && this.levels !== levels) { | ||
// 重置级别相关的函数 | ||
eachLevel(({ level }) => { | ||
delete this[level.toLocaleLowerCase()]; | ||
}); | ||
// 设置级别种类 and 暴露级别相关的函数 | ||
setLevels(levels, this._makeLogMethod); | ||
this.levels = levels; | ||
} | ||
return this; | ||
log(level, ...args) { | ||
const nlevel = normalizeLevel(level); | ||
assert(nlevel !== null, `Invalid log level ${level}`); | ||
return this._log(nlevel, args); | ||
} | ||
@@ -110,19 +117,33 @@ | ||
return Promise.all( | ||
this.appenders.map(appender => appender.destroy()) | ||
this._appenders.map(appender => appender.destroy()) | ||
).then(() => { | ||
try { | ||
Object.keys(this).forEach((key) => { | ||
delete this[key]; | ||
}); | ||
} catch (e) { } | ||
Object.keys(this).forEach((key) => { | ||
delete this[key]; | ||
}); | ||
}); | ||
} | ||
/** | ||
* 记录日志 | ||
* @param {String} level 级别 | ||
* @param {Array} args 日志内容数组 | ||
*/ | ||
_log(level, args) { | ||
if (this.isLevelEnabled(level)) { | ||
const opts = { level, logger: this.name, timestamp: Date.now() }; | ||
this._appenders.forEach((appender) => { | ||
appender.append(args, opts); | ||
}); | ||
} | ||
return this; | ||
} | ||
} | ||
Console.AbstractAppender = AbstractAppender; | ||
Console.isValid = isValid; | ||
Console.setLevels = setLevels; | ||
Console.output = output; | ||
Logger.clrsole = require('./clrsole'); | ||
Logger.addAppender = addAppender; | ||
Logger.getAppender = getAppender; | ||
Logger.addLayout = addLayout; | ||
Logger.getLayout = getLayout; | ||
module.exports = Console; | ||
module.exports = Logger; |
'use strict'; | ||
const assert = require('assert'); | ||
const { isNil, isFunction, isObject } = require('celia'); | ||
const { inspect } = require('util'); | ||
const isObject = require('celia/isObject'); | ||
const formatDate = require('celia.date/format'); | ||
const formatDate = require('date-manip/format'); | ||
@@ -11,4 +12,8 @@ /** | ||
*/ | ||
module.exports = function (options = {}) { | ||
const { datePattern = 'YYYY-MM-DD HH:mm:ss.SSS Z', depth = Infinity } = options; | ||
function basicLayout(options) { | ||
const { | ||
datePattern = 'YYYY-MM-DD HH:mm:ss.SSS Z', | ||
depth = Infinity | ||
} = options; | ||
return function (args, { | ||
@@ -23,2 +28,17 @@ logger, | ||
}; | ||
}; | ||
} | ||
const layoutMap = new Map(); | ||
layoutMap.set('basic', basicLayout); | ||
function addLayout(name, layout) { | ||
assert(!isNil(name), `Invalid layout name ${name}`); | ||
assert(isFunction(layout), `Layout must be a function, but got ${typeof layout}`); | ||
layoutMap.set(name, layout); | ||
} | ||
function getLayout(name) { | ||
return layoutMap.get(name); | ||
} | ||
module.exports = { addLayout, getLayout }; |
136
lib/util.js
'use strict'; | ||
const isNil = require('celia/isNil'); | ||
const assert = require('assert'); | ||
const { isNil, isString, isNumber } = require('celia'); | ||
const ALL = { level: 'ALL', value: -Number.MAX_SAFE_INTEGER, color: 'whiteBright' }; | ||
const colors = [ | ||
'black', | ||
'red', | ||
'green', | ||
'yellow', | ||
'blue', | ||
'magenta', | ||
'cyan', | ||
'white', | ||
'gray', | ||
'redBright', | ||
'greenBright', | ||
'yellowBright', | ||
'blueBright', | ||
'magentaBright', | ||
'cyanBright', | ||
'whiteBright' | ||
]; | ||
const ALL = { level: 'ALL', value: Number.MAX_VALUE, color: 'whiteBright' }; | ||
const OFF = { level: 'OFF', value: -Number.MAX_VALUE, color: 'gray' }; | ||
let levels; | ||
let colors; | ||
let currentLevels; | ||
let levelValueMapping; | ||
let levelColorMapping; | ||
const { stringify } = JSON; | ||
/** | ||
* 切换日志级别 | ||
* @param {Array} type 日志级别类型 | ||
* @param {Array} levels 日志级别类型 | ||
* @param {Function} callback | ||
*/ | ||
function setLevels(type, callback) { | ||
// 统一大小写 | ||
currentLevels = type; | ||
levels = Object.create(null); | ||
colors = Object.create(null); | ||
currentLevels.forEach((n, i) => { | ||
function setLevels(levels, callback) { | ||
levelValueMapping = Object.create(null); | ||
levelColorMapping = Object.create(null); | ||
levels.forEach((n) => { | ||
let { level, value, color } = n; | ||
level = level.toLocaleUpperCase(); | ||
levels[level] = value; | ||
colors[level] = color; | ||
n.level = level; | ||
callback && callback(n); | ||
assert(isString(level), `Invalid log level ${level} in config ${stringify(n)}`); | ||
assert(colors.indexOf(color) > -1, `Invalid color string ${color} in config ${stringify(n)}`); | ||
assert(isNumber(value), `Invalid log level value ${value} in config ${stringify(n)}`); | ||
levelValueMapping[level] = value; | ||
levelColorMapping[level] = color; | ||
n = { level: level.toLocaleUpperCase(), value, color }; | ||
callback(n); | ||
}); | ||
[ALL, OFF].forEach(({ level, value, color }) => { | ||
levels[level] = value; | ||
colors[level] = color; | ||
levelValueMapping[level] = value; | ||
levelColorMapping[level] = color; | ||
}); | ||
} | ||
// 默认使用log4j日志级别 | ||
setLevels(require('./levels')); | ||
/** | ||
* firstLevel是否能用 | ||
* @param {String} firstLevel | ||
* @param {String} secondLevel | ||
*/ | ||
function isLevelEnabled(firstLevel, secondLevel) { | ||
return firstLevel !== 'OFF' && levelValueMapping[firstLevel] >= levelValueMapping[secondLevel]; | ||
} | ||
module.exports = { | ||
/** | ||
* firstLevel是否能用 | ||
* @param {String} firstLevel | ||
* @param {String} secondLevel | ||
*/ | ||
isLevelEnabled(firstLevel, secondLevel) { | ||
return !firstLevel || levels[firstLevel] >= levels[secondLevel]; | ||
}, | ||
/** | ||
* 格式化 level | ||
* @param {String} level | ||
*/ | ||
function normalizeLevel(level) { | ||
return level && !isNil(levelValueMapping[(level = level.toLocaleUpperCase())]) ? level : null; | ||
} | ||
/** | ||
* 是否是合法级别 | ||
* @param {String} level | ||
*/ | ||
isValid(level) { | ||
return level && !isNil(levels[level.toLocaleUpperCase()]); | ||
}, | ||
/** | ||
* 根据级别获取颜色 | ||
* @param {String} level | ||
*/ | ||
function level2Color(level) { | ||
return levelColorMapping[level]; | ||
} | ||
/** | ||
* 获取所有级别的名称 | ||
*/ | ||
levelNames() { | ||
return currentLevels.map(({ level }) => level); | ||
}, | ||
/** | ||
* 遍历级别 | ||
* @param {Function} callback | ||
*/ | ||
eachLevel(callback) { | ||
currentLevels.forEach(callback); | ||
}, | ||
/** | ||
* 根据级别获取颜色 | ||
* @param {String} level | ||
*/ | ||
getColor(level) { | ||
return colors[level]; | ||
}, | ||
/** | ||
* 根据级别获取颜色 | ||
* @param {String} level | ||
*/ | ||
getValue(level) { | ||
return levels[level]; | ||
}, | ||
module.exports = { | ||
colors, | ||
level2Color, | ||
isLevelEnabled, | ||
normalizeLevel, | ||
setLevels | ||
}; |
{ | ||
"name": "clrsole", | ||
"version": "1.1.1", | ||
"description": "colorful console.log", | ||
"version": "2.0.0", | ||
"description": "colorful logger with console.log or custom appender", | ||
"main": "index.js", | ||
"directories": { | ||
"lib": "lib" | ||
"example": "examples", | ||
"lib": "lib", | ||
"test": "test" | ||
}, | ||
@@ -33,5 +35,5 @@ "scripts": { | ||
"dependencies": { | ||
"celia": "^6.0.3", | ||
"celia.date": "^1.0.0", | ||
"chalk": "^2.4.2" | ||
"celia": "^6.1.4", | ||
"chalk": "^2.4.2", | ||
"date-manip": "^1.0.0" | ||
}, | ||
@@ -38,0 +40,0 @@ "devDependencies": { |
@@ -9,7 +9,7 @@ # clrsole | ||
const { output, getLogger } = require('clrsole'); | ||
const { clrsole, getLogger } = require('clrsole'); | ||
const appLogger = getLogger('app'); | ||
// logging for log4j | ||
// logging like log4j | ||
appLogger.trace('message', 'message2', ...); | ||
@@ -22,6 +22,16 @@ appLogger.debug('message', 'message2', ...); | ||
// changed levels | ||
appLogger.setLevels('syslog'); | ||
// changed syslog levels | ||
// appLogger.levels = require('graylog-sender/lib/syslog-levels'); | ||
appLogger.setLevels([ | ||
{ level: 'EMERGENCY', value: 0, color: 'magentaBright' }, | ||
{ level: 'ALERT', value: 1, color: 'magenta' }, | ||
{ level: 'CRITICAL', value: 2, color: 'redBright' }, | ||
{ level: 'ERROR', value: 3, color: 'red' }, | ||
{ level: 'WARN', value: 4, color: 'yellowBright' }, | ||
{ level: 'NOTICE', value: 5, color: 'yellow' }, | ||
{ level: 'INFO', value: 6, color: 'green' }, | ||
{ level: 'DEBUG', value: 7, color: 'cyan' } | ||
], 'INFO'); | ||
// logging for syslog | ||
// logging like syslog | ||
appLogger.debug('message', 'message2'); | ||
@@ -36,3 +46,3 @@ appLogger.info('message', 'message2'); | ||
// The first optional param is level | ||
// The first param is level | ||
appLogger.log('INFO', 'message', 'message2', ...); | ||
@@ -42,5 +52,5 @@ appLogger.log('error', 'message', 'message2', ...); | ||
output.green('green message', ...); | ||
output.red('red message', ...); | ||
clrsole.green('green message', ...); | ||
clrsole.red('red message', ...); | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
17961
439
53
13
4
1
+ Addeddate-manip@^1.0.0
+ Addedcelia@6.1.5-1(transitive)
+ Addeddate-manip@1.0.1(transitive)
- Removedcelia.date@^1.0.0
Updatedcelia@^6.1.4