Created
April 27, 2020 23:42
-
-
Save madrang/0f4b456c29fa9fc9d35f84721b1da638 to your computer and use it in GitHub Desktop.
JS Events Logging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Module code goes here. Use 'module.exports' to export things: | |
* module.exports.thing = 'a thing'; | |
* | |
* You can import it from another modules like this: | |
* var mod = require('events'); | |
* mod.thing == 'a thing'; // true | |
*/ | |
module.exports = (function(){ | |
const _eventLevel = { | |
// System is in a situation that poses an immediate risk, | |
// require urgent intervention to prevent a worsening of the situation. | |
EMERGENCY: 0 | |
// An error of sufficient magnitude that the system aborted all operations to protect itself. | |
, FATAL: 1 << 0 | |
// An error of sufficient magnitude that it cannot be handled. | |
// Should be corrected immediately. Impact system operations. | |
, CRITICAL: 1 << 1 | |
// An error that prevents an operation from completing successfully, | |
// Could be handled without affecting the system continued operation. | |
// Should be corrected immediately, but the failure is in a secondary system. System remains functional. | |
, ERROR: 1 << 2 | |
// Indication that an error will occur if no action is taken. | |
, WARNING: 1 << 3 | |
// Events that are unusual but not error conditions. | |
, NOTICE: 1 << 4 | |
// Normal operational messages. | |
, INFORMATIVE: 1 << 5 | |
// Debug information that will only need to be seen when tracking down specific problems. | |
, DEBUG: 1 << 6 | |
// Not sure if usefull, use Trace. | |
// Spam box, Whatever info that could be usefull... | |
, TRACE: 1 << 7 | |
// All messages will be logged. | |
, ALL: 0xFF | |
}; | |
// Minimal logging, errors and warning only. | |
_eventLevel.MINIMUM = _eventLevel.FATAL | _eventLevel.CRITICAL | _eventLevel.ERROR | _eventLevel.WARNING; | |
// Standard messages will be logged. | |
_eventLevel.STANDARD = _eventLevel.MINIMUM | _eventLevel.NOTICE | _eventLevel.INFORMATIVE; | |
// Verbose, Standard and Debugging. | |
// Does not include Trace. | |
_eventLevel.VERBOSE = _eventLevel.STANDARD | _eventLevel.DEBUG; | |
let _consoleLogLevel = _eventLevel.STANDARD; | |
let _consoleLogFilter = function(logger, logLvl, ...args){ | |
return true; | |
}; | |
const _Event = function(level){ | |
this.level = level; | |
}; | |
Object.freeze(_Event); | |
const _getColor = function (level) { | |
switch (level) { | |
case _eventLevel.TRACE: | |
return "RoyalBlue"; | |
case _eventLevel.DEBUG: | |
return "SeaGreen"; | |
case _eventLevel.INFORMATIVE: | |
return "WhiteSmoke"; | |
case _eventLevel.NOTICE: | |
return "Lime"; | |
case _eventLevel.WARNING: | |
return "Yellow"; | |
case _eventLevel.ERROR: | |
return "Orangered"; | |
case _eventLevel.FATAL: | |
return "Crimson"; | |
case _eventLevel.CRITICAL: | |
return "MediumVioletRed"; | |
case _eventLevel.EMERGENCY: | |
return "DeepPink"; | |
default: | |
return "White"; | |
} | |
}; | |
const _mapArgsToString = function (...args) { | |
return _.map(args, (a) => { | |
const aType = typeof a; | |
if(aType === 'undefined') { | |
return 'undefined'; | |
} else if (aType === "string") { | |
return a; | |
} else if(typeof a.toString === "function") { | |
return a.toString(); | |
} else { | |
return JSON.stringify(a); | |
} | |
}); | |
}; | |
const _printEvent = function(logLevel, ...args) { | |
if (!Number.isInteger(logLevel) || (logLevel & _consoleLogLevel === 0)) { | |
return; | |
} | |
const color = _getColor(logLevel); | |
const message = _mapArgsToString(...args).join(''); | |
console.log("<font color=\"" + color + "\">" + message + "</>"); | |
}; | |
const _logBase = function(name) { | |
if (typeof name === "undefined") { | |
throw new Error("Name is undefined.") | |
} else if (typeof name === "string") { | |
this.name = name; | |
} else { | |
throw new Error("Name is not a string.") | |
} | |
}; | |
//Add log functions. | |
for (const levelName of Object.keys(_eventLevel)) { | |
const logLvl = _eventLevel[levelName]; | |
_logBase.prototype[levelName.toLowerCase()] = function(...args) { | |
if (_consoleLogFilter(this, logLvl, ...args) !== true) { | |
return; | |
} | |
if (typeof this.name !== "undefined" && this.name !== "System") { | |
args.unshift(this.name, "-->"); | |
} | |
_printEvent(logLvl, ...args); | |
}; | |
} | |
_logBase.prototype.info = _logBase.prototype.informative; | |
_logBase.prototype.warn = _logBase.prototype.warning; | |
const _logHandler = Object.create(null); | |
_logHandler.set = function(target, propertyKey, value, receiver) { | |
Reflect.set(target, propertyKey, value, receiver); | |
}; | |
const _createLogger = function(parentLogger, name) { | |
let newLoggerName; | |
if (typeof parentLogger === "string" && typeof name === "undefined") { | |
//Name was passed as first arg. | |
newLoggerName = parentLogger; | |
} else if (typeof name === "string") { | |
if (typeof parentLogger === "object" && typeof parentLogger.name === "string" && parentLogger.name !== "System") { | |
newLoggerName = [parentLogger.name, "->", name].join(''); | |
} else { | |
//No parent. | |
newLoggerName = name; | |
} | |
} else { | |
throw new Error("Name is not a string.") | |
} | |
return new Proxy(new _logBase(newLoggerName), _logHandler); | |
}; | |
_logHandler.get = function(target, propertyKey) { | |
const propType = typeof propertyKey; | |
if (propType === "undefined") { | |
throw new Error("propertyKey is undefined."); | |
} | |
if (propertyKey in target) { | |
const propVal = Reflect.get(target, propertyKey); | |
return propVal; | |
} | |
if (propType === "object") { | |
//WeakMap keys must be objects, not primitive values | |
let weakLogMap; | |
if (typeof target.__weakLogMap === "undefined") { | |
weakLogMap = new WeakMap(); | |
target.__weakLogMap = weakLogMap; | |
} else { | |
weakLogMap = target.__weakLogMap; | |
} | |
if (weakLogMap.has(propertyKey)) { | |
return weakLogMap.get(propertyKey); | |
} else { | |
let newLoggerName; | |
if (typeof propertyKey.name === "string") { | |
newLoggerName = propertyKey.name; | |
} else if(typeof propertyKey.toString === "function") { | |
newLoggerName = propertyKey.toString(); | |
} else { | |
//If function, propertyKey.displayName | |
newLoggerName = propertyKey.prototype.name; | |
} | |
const newLog = _createLogger(target, newLoggerName); | |
weakLogMap.set(propertyKey, newLog); | |
return newLog; | |
} | |
} else { | |
const newLog = _createLogger(target, propertyKey); | |
return newLog; | |
} | |
}; | |
Object.freeze(_logHandler); | |
const logProxy = _createLogger("System"); | |
return { | |
Event: _Event | |
, levels: _eventLevel | |
, write: _printEvent | |
, setLogLevel: function(logLevel) { | |
if (!Number.isInteger(logLevel)) { | |
throw new Error("logLevel is not an integer.") | |
} | |
_consoleLogLevel = logLevel; | |
} | |
, setLogFilter: function(logFilter) { | |
if (typeof logFilter !== "function") { | |
throw new Error("logFilter is not a function.") | |
} | |
_consoleLogFilter = logFilter; | |
} | |
, log: logProxy | |
, mapArgsToString: _mapArgsToString | |
}; | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment