Skip to content

Instantly share code, notes, and snippets.

@tracker1
Last active March 27, 2019 18:59
Show Gist options
  • Save tracker1/655be1ac690d23988816a48d52e91550 to your computer and use it in GitHub Desktop.
Save tracker1/655be1ac690d23988816a48d52e91550 to your computer and use it in GitHub Desktop.
Console Logger for node.js
import console from 'console';
import process from 'process';
import util from 'util';
import fclone from 'fclone';
import rollingFile from 'rolling-file';
import mkdirp from 'mkdirp';
import { packageBase } from './pkg';
export const LEVELS = Object.seal({
FATAL: 1000,
ERROR: 900,
START: 750,
STOP: 700,
RESPONSE: 650,
REQUEST: 600,
WARN: 500,
INFO: 400,
CLIENTRESPONSE: 350,
CLIENTREQUEST: 300,
DEBUG: 200,
TRACE: 100,
});
const levelsByNumber = Object.keys(LEVELS).reduce(
(a, k) => Object.assign(a, { [LEVELS[k]]: k }),
{}
);
const clearStack = obj => {
if (typeof obj !== 'object') return;
if (obj.stack) {
obj.stack = undefined; // eslint-disable-line
}
Object.keys(obj).forEach(clearStack);
};
export function parseLogLevel(level) {
// numeric matching
if (!isNaN(level)) {
return levelsByNumber[level] ? level : null;
}
const m =
LEVELS[
String(level)
.trim()
.toUpperCase()
] || null;
return m || null;
}
export function getLogName(level) {
const m = levelsByNumber[level];
return m || null;
}
// format message for output
export const formatMessage = (logLevel, level, ...args) => {
// eslint-disable-next-line no-param-reassign
level = parseLogLevel(level);
if (level < logLevel) return null;
if (typeof args[0]) if (args.length < 1) return null;
if (args.length === 1 && (args[0] === null || args[0] === undefined)) return null;
const item = {
level: getLogName(level),
logged: new Date(),
application: `${packageBase.name}@${packageBase.version}/${packageBase.build}`,
detail:
args.length === 1 && typeof args[0] === 'object'
? fclone(args[0])
: { message: util.format(...args) },
};
if (logLevel > LEVELS.INFO) {
clearStack(item.detail);
}
return item;
};
export default async (options = {}) => {
let logLevel = parseLogLevel(process.env.LOG_LEVEL) || LEVELS.REQUEST;
let rf = null;
if (process.env.LOG_PATH) {
mkdirp.sync(process.env.LOG_PATH);
rf = rollingFile(process.env.LOG_PATH, {
fileName: 'ingressum',
byteLimit: '500 mb',
interval: '1 day',
// fileExtension: `.${process.pid}.log`,
});
}
const log = level => (...args) => {
// pretty-print console output
const pretty = !!process.env.LOG_PRETTY;
// format JSON for logging
let item = formatMessage(logLevel, level, ...args);
// JSON stringified version
let item2 = JSON.stringify(item);
if (!(options.quiet || process.env.LOG_QUIET)) {
if (!pretty) {
console[logLevel >= LEVELS.ERROR ? 'error' : 'log'](item2);
} else {
const { level, logged, application, detail } = item;
console[logLevel >= LEVELS.ERROR ? 'error' : 'log'](logged, level, application, detail);
}
}
if (rf) {
rf.write(item2);
}
};
return {
levels: LEVELS,
format: formatMessage,
get level() {
return getLogName(logLevel);
},
set level(newLevel) {
logLevel = parseLogLevel(newLevel) || logLevel;
},
log: (level, ...args) => log(level)(...args),
fatal: log(LEVELS.FATAL),
error: log(LEVELS.ERROR),
start: log(LEVELS.START),
stop: log(LEVELS.STOP),
response: log(LEVELS.RESPONSE),
request: log(LEVELS.REQUEST),
warn: log(LEVELS.WARN),
info: log(LEVELS.INFO),
clientResponse: log(LEVELS.CLIENTRESPONSE),
clientRequest: log(LEVELS.CLIENTREQUEST),
debug: log(LEVELS.DEBUG),
trace: log(LEVELS.TRACE),
};
};
import findup from 'findup-sync';
import fs from 'fs';
const pkg = JSON.parse(fs.readFileSync(findup('package.json')));
export const packageBase = {
name: pkg.name,
version: pkg.version,
build: pkg.build,
};
export default pkg;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment