Skip to content

Instantly share code, notes, and snippets.

@mStirner
Last active March 20, 2022 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mStirner/5cd7ff1b6ccce4ba464d7934eb83cf1d to your computer and use it in GitHub Desktop.
Save mStirner/5cd7ff1b6ccce4ba464d7934eb83cf1d to your computer and use it in GitHub Desktop.
Lightweight, stream based, expandable, node.js logger with zero dependencies

This is a example of a very lightweight, stream based, node.js logger. It creates a "record" object for each log call, and pipe it throught the spicified streams. In the streams its possible to modifie the record, format the message, and many more.

Bunyan, there is no one responding on issues, Winstons is way to big and have unecesseray dependencies.

I wanted a lightweight, easy to use, expandable, stream based, logging utily with zero dependencies. You can all merge this down into a single file. You bascily need class.logger.js & levels.js which can simple merged into a single file.

The other files (demo.js, formatter.js) are for demonstration & formatting and not needed for the functionality.

To add/remove logging levels, just import/require levels.js before class.logger.js and do what ever you want with the logging levels. If you want do that before you include the logger class, it automaticly apply the changes.

I mean... it is very simple, do what ever you want with this snippet ;)

Im thinking about to use utils.format for the logging message formation when multiple arguments are passed.

const levels = require("./levels");
const { EOL } = require("os");
module.exports = class Logger {
constructor(options) {
options = Object.assign({
level: "trace",
streams: [],
name: "default"
}, options);
// "expose" options
this.options = options;
// monkey patch methods defined in levels
for (const [method, value] of Object.entries(levels.names)) {
this[method] = (...args) => {
if (value >= levels.names[options.level]) {
let obj = {
level: method,
name: options.name,
timestamp: Date.now(),
message: null,
fields: [],
error: null
};
if (args[0] instanceof Error) {
let err = args.shift();
obj.error = JSON.stringify(err, Object.getOwnPropertyNames(err));
obj.message = args.shift();
obj.fields = args;
} else {
obj.message = args.shift();
obj.fields = args;
}
let record = JSON.stringify(obj) + EOL;
options.streams.forEach((stream) => {
stream.write(record);
});
}
};
}
}
tracer(desc, count, cb = () => "Finished!") {
let counter = 0;
let fired = false;
return (msg) => {
counter += 1;
this.trace(`${desc}; ${counter}/${count}; ${msg}`);
if (counter >= count && !fired) {
this.trace(cb());
}
};
}
};
const { Writable } = require("stream");
const { createWriteStream } = require("fs");
const Logger = require("./class.logger.js");
const formatter = require("./formatter.js");
const stdout = new Writable({
write: (chunk, encoding, cb) => {
chunk = JSON.parse(chunk);
chunk.message = formatter(chunk);
console.log(chunk.message);
if (chunk.error) {
console.log(JSON.parse(chunk.error).stack);
}
cb(null);
}
});
const logger = new Logger({
"system",
streams: [
stdout,
createWriteStream("system.log"),
//process.stdout
]
});
const tracer = logger.tracer("Count to 3", 3, () => {
return "Final message";
});
tracer("Call 1");
tracer("Call 2");
tracer("Call 3");
console.log("--")
logger.trace("trace");
logger.debug("Debug");
logger.info("Info");
logger.warn("Warn");
logger.error("Error", { extra: true });
//logger.info("Info");
//logger.error(new Error("error mesg"), "fuck off")
const dateFormat = require("dateformat");
const safe = require("colors/safe");
const levels = require("./levels.js");
module.exports = (rec) => {
let colorize = safe[levels.colors[rec.level]];
let timestamp = dateFormat(rec.time, "yyyy.mm.dd - HH:MM.ss.l");
// build message string
let msg = `[${colorize(timestamp)}]`;
msg += `[${colorize(rec.level)}]`;
msg += `[${colorize(rec.name)}]`;
msg += ` ${rec.message}`;
return msg;
};
module.exports = {
names: {
"trace": 10,
"debug": 20,
"info": 30,
"warn": 40,
"error": 50
},
colors: {
"trace": "cyan",
"debug": "gray",
"info": "blue",
"warn": "yellow",
"error": "red"
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment