brolog
Version:
Npmlog like logger for Browser
333 lines • 11.4 kB
JavaScript
/* eslint-disable no-console */
/*!
* Brolog JavaScript Library v1.1.0
* https://github.com/huan/brolog
*
* Copyright Huan LI <zixia@zixia.net>
* Released under the ISC license
* https://github.com/huan/brolog/blob/master/LICENSE
*
* Date: 2016-07
*/
import { VERSION, BROLOG_LEVEL, BROLOG_PREFIX, } from './config.js';
var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["silent"] = 0] = "silent";
LogLevel[LogLevel["error"] = 1] = "error";
LogLevel[LogLevel["warn"] = 2] = "warn";
LogLevel[LogLevel["info"] = 3] = "info";
LogLevel[LogLevel["verbose"] = 4] = "verbose";
LogLevel[LogLevel["silly"] = 5] = "silly";
})(LogLevel || (LogLevel = {}));
class Brolog {
static globalInstance;
static globalLogLevelName = 'info';
static globalPrefix = /.*/; // Match all by default
enableTimestamp = true;
logLevel;
prefixFilter;
textPrinter;
constructor() {
this.level(Brolog.globalLogLevelName);
this.logLevel = LogLevel[this.level()];
this.prefix(Brolog.globalPrefix);
this.prefixFilter = this.prefix();
this.textPrinter = this.defaultTextPrinter;
}
/**
* Create a global Brolog Instance for sharing between modules
*/
static instance(levelName, prefix) {
if (!this.globalInstance) {
this.globalInstance = new Brolog();
}
if (levelName) {
this.globalLogLevelName = levelName;
this.globalInstance.level(levelName);
}
if (prefix) {
this.globalPrefix = prefix;
this.globalInstance.prefix(prefix);
}
return this.globalInstance;
}
static version() {
return VERSION;
}
version() {
return Brolog.version();
}
static enableLogging(printerFunc) {
return Brolog.instance().enableLogging(printerFunc);
}
enableLogging(printerFunc) {
this.verbose('Brolog', 'enableLogging(%s)', printerFunc);
// const loggerMethodList = [
// 'error',
// 'warn',
// 'info',
// 'verbose',
// 'silly',
// ]
if (printerFunc === false) {
this.silly('Brolog', 'enableLogging() disabled');
// loggerMethodList.forEach(m => {
// this[m] = nullLogger[m]
// })
this.textPrinter = function () { };
}
else if (printerFunc === true) {
this.silly('Brolog', 'enableLogging() enabled: restore Brolog instance');
// const restore = new Brolog()
// loggerMethodList.forEach(m => {
// this[m] = restore[m]
// })
this.textPrinter = this.defaultTextPrinter;
// } else if (typeof log.verbose === 'function') {
// this.silly('Brolog', 'enableLogging() enabled: using provided logger')
// for (const method of loggerMethodList) {
// this[method] = () => {
// // In order to compatible with winston,
// // we need to change the args from
// // brolog.info('Main', 'Hello %s', 'world')
// // to
// // log.info('Main Hello %s', 'world')
// const argList: string[] = Array.from(arguments)
// if (argList.length > 1) {
// const module = argList.shift()
// argList[0] = `${module} ` + argList[0]
// }
// return Reflect.apply(log[method], log, argList)
// }
// }
}
else if (typeof printerFunc === 'function') {
this.silly('Brolog', 'enableLogging() enabled: using provided log function');
this.textPrinter = function (levelTitle, text) {
printerFunc(levelTitle, text);
};
}
else {
throw new Error('got invalid logger');
}
return this;
}
static prefix(filter) {
if (filter) {
this.globalPrefix = filter;
this.globalInstance?.prefix(filter);
}
else {
return this.instance().prefix();
}
}
prefix(filter) {
if (filter) {
if (typeof filter === 'string') {
this.prefixFilter = new RegExp('^' + filter + '$');
}
else if (filter instanceof RegExp) {
this.prefixFilter = filter;
}
else {
throw new Error('unsupported prefix filter');
}
}
else {
return this.prefixFilter;
}
}
static level(levelName) {
if (levelName) {
this.globalLogLevelName = levelName;
}
return this.instance().level(levelName);
}
level(levelName) {
if (levelName) {
// console.log('levelName: ' + levelName)
// http://stackoverflow.com/a/21294925/1123955
// XXX: fix the any here?
let logLevel = LogLevel[levelName.toLowerCase()];
if (logLevel === undefined) { // be aware of number 0 here
log.error('Brolog', 'level(%s) not exist, set to silly.', levelName);
logLevel = LogLevel.silly;
}
this.logLevel = logLevel;
}
return LogLevel[this.logLevel];
}
log(levelTitle, prefix, message) {
if (this.prefixFilter && !this.prefixFilter.test(prefix)) {
return; // skip message not match prefix filter
}
const args = Array.prototype.slice.call(arguments, 3);
args.unshift(this.timestamp() + levelTitle + ' ' + prefix + ' ' + (message || ''));
// const args = Array.from(arguments) || []
// args[0] = this.timestamp() + args[0]
const text = Reflect.apply(sprintf, null, args);
this.textPrinter(levelTitle, text);
}
defaultTextPrinter(levelTitle, text) {
// Use Reflect at:
// https://www.keithcirkel.co.uk/metaprogramming-in-es6-part-2-reflect/
switch (levelTitle) {
case 'ERR':
// console.error.apply(console, args)
// Reflect.apply(console.error, console, args)
console.error(text);
break;
case 'WARN':
// console.warn.apply(console, args)
// Reflect.apply(console.warn, console, args)
console.warn(text);
break;
case 'INFO':
// console.info.apply(console, args)
// Reflect.apply(console.info, console, args)
console.info(text);
break;
// eslint-disable-next-line default-case-last
default:
case 'VERB':
case 'SILL':
// console.log.apply(console, args)
// Reflect.apply(console.log, console, args)
console.log(text);
}
}
static error(prefix, ...args) {
const instance = Brolog.instance();
// return instance.error.apply(instance, arguments)
return Reflect.apply(instance.error, instance, [].concat(prefix, args));
}
error(prefix, ...args) {
if (this.logLevel < LogLevel.error) {
return;
}
const argList = Array.from([prefix, ...args]);
argList.unshift('ERR');
return Reflect.apply(this.log, this, argList);
}
static warn(prefix, ...args) {
const instance = Brolog.instance();
return Reflect.apply(instance.warn, instance, [].concat(prefix, args));
}
warn(prefix, ...args) {
if (this.logLevel < LogLevel.warn) {
return;
}
const argList = Array.from([prefix, ...args]);
argList.unshift('WARN');
return Reflect.apply(this.log, this, argList);
}
static info(prefix, ...args) {
const instance = Brolog.instance();
return Reflect.apply(instance.info, instance, [].concat(prefix, args));
}
info(prefix, ...args) {
if (this.logLevel < LogLevel.info) {
return;
}
const argList = Array.from([prefix, ...args]);
argList.unshift('INFO');
return Reflect.apply(this.log, this, argList);
}
static verbose(prefix, ...args) {
const instance = Brolog.instance();
return Reflect.apply(instance.verbose, instance, [].concat(prefix, args));
}
verbose(prefix, ...args) {
if (this.logLevel < LogLevel.verbose) {
return;
}
const argList = Array.from([prefix, ...args]);
argList.unshift('VERB');
return Reflect.apply(this.log, this, argList);
}
static silly(prefix, ...args) {
const instance = Brolog.instance();
return Reflect.apply(instance.silly, instance, [].concat(prefix, args));
}
silly(prefix, ...args) {
if (this.logLevel < LogLevel.silly) {
return;
}
const argList = Array.from([prefix, ...args]);
argList.unshift('SILL');
return Reflect.apply(this.log, this, argList);
}
timestamp(enable) {
if (typeof enable === 'boolean') {
this.enableTimestamp = enable;
return;
}
if (!this.enableTimestamp) {
return '';
}
const date = new Date();
const hour = date.getHours();
const min = date.getMinutes();
const sec = date.getSeconds();
let stampStr = '';
stampStr += (hour < 10) ? ('0' + hour) : hour;
stampStr += ':';
stampStr += (min < 10) ? ('0' + min) : min;
stampStr += ':';
stampStr += (sec < 10) ? ('0' + sec) : sec;
return stampStr + ' ';
}
}
// Credit: https://stackoverflow.com/a/4795914/1123955
function sprintf() {
const args = arguments;
const text = args[0];
let i = 1;
return text.replace(/%((%)|s|d)/g, function (m) {
// m is the matched format, e.g. %s, %d
let val = null;
if (m[2]) {
val = m[2];
}
else {
val = args[i];
// A switch statement so that the formatter can be extended. Default is %s
switch (m) {
case '%d':
val = Number(val);
/**
* Huan(202111): use Number() to replace parseFloat,
* and keep the `NaN` as a result for easy debugging
* when we use `%d` mistakenly when `%s` should be expected.
*/
// val = parseFloat(val)
// if (isNaN(val)) {
// val = 0
// }
break;
}
i++;
}
return val;
});
}
export { VERSION, };
const log = Brolog.instance();
if (BROLOG_LEVEL) {
/**
* set logLevel from:
* 1. process.env['BROLOG_LEVEL'], or
* 2. in URL: `?BROLOG_LEVEL=verbose&...`
*/
if (BROLOG_LEVEL === '*') {
log.level('silly');
}
else {
log.level(BROLOG_LEVEL);
}
}
if (BROLOG_PREFIX && BROLOG_PREFIX !== '*') {
log.prefix(BROLOG_PREFIX);
}
export { LogLevel, Brolog, log, };
//# sourceMappingURL=brolog.js.map