Skip to content

Instantly share code, notes, and snippets.

@digitalhitler
Last active September 3, 2018 13:38
Show Gist options
  • Save digitalhitler/646395d1e37370aad1761596150e2329 to your computer and use it in GitHub Desktop.
Save digitalhitler/646395d1e37370aad1761596150e2329 to your computer and use it in GitHub Desktop.
JS Logger Class
/**
* Logger.class.js: Simple logger based on console wrapper with colors
* and multiple levels
*
* @copyright Copyright (c) 2018 Sergey Petrenko <spetrenko@me.com>
* @homepage https://gist.github.com/digitalhitler
* @license MIT
* @version 2.1.0
*
* @history
* * 2.1.0 at 09/03/2018
* - Added bold flag
* - Created once-called customs flags storage nextCallCustoms
* - Wrapped main handler into try-catch
*
* * 2.0.0 at 08/14/2018
* - Initial rewritten
*/
import { default as EventHandler } from "./modules/Event";
const LoggerLevels = {
"trace": 0,
"debug": 1,
"info": 2,
"warn": 3,
"error": 4,
"silent": 5
};
export default class Logger {
static colors = [ "red", "orange", "green", "darkgreen", "magenta", "blue", "black" ];
static lastColor = 0;
static levelStyles = {
trace: "color: #666666; background: #eeeeee",
debug: "color: #666666; background: #DCE2FF",
info: "color: white; background: blue",
warn: "color: white; background: orange",
error: "color: white; background: red",
silent: "color: white; background: #cccccc"
};
static stackRegExp = new RegExp('^\\s*?at\\s*(\\S*?)\\s');
constructor(name, options) {
if(!options) {
options = {};
}
this.name = name || "default";
this.level = options.level || 0;
this.color = (
this.name === "default"
? "#666666"
: options.color || Logger.colors[Logger.lastColor++]
);
this.nextCallCustoms = null;
if(Logger.lastColor === Logger.colors.length) {
Logger.lastColor = 0;
}
this.onLog = EventHandler();
this.formatter = (level, args) => {
if(LoggerLevels[level] && LoggerLevels[level] >= this.level) {
let str;
if(args && args.length > 0) {
str = args.shift();
}
let fontWeight = "normal";
if(this.nextCallCustoms !== null) {
if(this.nextCallCustoms.bold) {
fontWeight = "900";
}
}
return console[level](
`%c${this.name} %c${level}%c `,
`color: ${this.color}`,
`border-radius: 4px; padding: 0 3px; ${Logger.levelStyles[level]}`,
`color: initial; font-weight: ${fontWeight}`,
str,
(args.length > 0 ? args : "")
);//this.name + "::" + level, args);
} else {
console.log('muted', args);
}
};
let levels = Object.keys(LoggerLevels);
if(levels.length > 0) {
for(let level of levels) {
if(!this.hasOwnProperty(level)) {
this[level] = (...args) => {
return this._log(level, args);
};
}
}
}
this.onLog.push((payload) => {
try {
// Run output handler:
this.formatter(payload[0], payload[1]);
if (this.nextCallCustoms !== null) {
// Handle trace flag
if (this.nextCallCustoms.traced) {
let stack = this.stacktrace();
if (stack) {
console.log(
`%cChain of calls: %c` + stack.join(" -> "),
"font-weight: bold",
"color: #666666"
);
}
}
// Notice: bold flag handled in formatter
}
} catch(e) {
console.error('Failed to execute logger handler, due to:');
console.dir(e);
debugger;
} finally {
this.nextCallCustoms = null;
}
});
}
_log(level, args) {
this.onLog.trigger([ level, args ]);
}
traced() {
if(this.nextCallCustoms === null) {
this.nextCallCustoms = {};
}
this.nextCallCustoms.traced = true;
return this;
}
bold() {
if(this.nextCallCustoms === null) {
this.nextCallCustoms = {};
}
this.nextCallCustoms.bold = true;
return this;
}
stacktrace() {
let result = null;
try {
throw Error();
} catch(e) {
let lines = e.stack.split("\n");
if(lines.length > 0) {
result = [];
for(let line of lines) {
let parts = Logger.stackRegExp.exec(line);
if(parts && parts.length && parts.length > 1) {
if(parts[1] && parts[1].length > 0 && typeof parts[1] === 'string') {
result.push(parts[1]);
}
}
}
}
} finally {
return result;
}
}
log(...args) {
return this._log('debug', args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment