Winston is a popular logging library for NodeJS which allows you to customise the output, as well as different logging targets.

This lesson covers configuring Winston to run with different levels depending on a Node environment variable as well as enhancing the log output to include the filename and line number the log message originates from.

winston: "2.4.2", >v3.0 has breaking changes.

 

Below code can just take away and use. It set 'debug' log level in developerment and 'info' level for production.

logger.js:

const winston = require("winston");
const moment = require("moment");
const path = require("path");
const PROJECT_ROOT = path.join(__dirname, "..");

const consoleLogger = new winston.transports.Console({
  timestamp: function() {
    const today = moment();
    return today.format("DD-MM-YYYY h:mm:ssa");
  },
  colorize: true,
  level: "debug"
});

const logger = new winston.Logger({
  transports: [consoleLogger]
});

if (process.env.NODE_ENV === "production") {
  logger.transports.console.level = "info";
}
if (process.env.NODE_ENV === "development") {
  logger.transports.console.level = "debug";
}

module.exports.info = function() {
  logger.info.apply(logger, formatLogArguments(arguments));
};
module.exports.log = function() {
  logger.log.apply(logger, formatLogArguments(arguments));
};
module.exports.warn = function() {
  logger.warn.apply(logger, formatLogArguments(arguments));
};
module.exports.debug = function() {
  logger.debug.apply(logger, formatLogArguments(arguments));
};
module.exports.verbose = function() {
  logger.verbose.apply(logger, formatLogArguments(arguments));
};

module.exports.error = function() {
  logger.error.apply(logger, formatLogArguments(arguments));
};

function formatLogArguments(args) {
  args = Array.prototype.slice.call(args);
  const stackInfo = getStackInfo(1);

  if (stackInfo) {
    const calleeStr = `(${stackInfo.relativePath}:${stackInfo.line})`;
    if (typeof args[0] === "string") {
      args[0] = args[0] + " " + calleeStr;
    } else {
      args.unshift(calleeStr);
    }
  }
  return args;
}

function getStackInfo(stackIndex) {
  const stacklist = new Error().stack.split("\n").slice(3);
  // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
  // do not remove the regex expresses to outside of this method (due to a BUG in node.js)
  const stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi;
  const stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi;

  const s = stacklist[stackIndex] || stacklist[0];
  const sp = stackReg.exec(s) || stackReg2.exec(s);

  if (sp && sp.length === 5) {
    return {
      method: sp[1],
      relativePath: path.relative(PROJECT_ROOT, sp[2]),
      line: sp[3],
      pos: sp[4],
      file: path.basename(sp[2]),
      stack: stacklist.join("\n")
    };
  }
}

logger.exitOnError = false;

 

How to use:

const dotenv = require('dotenv').config({ path: 'variables.env' });
const colors = require('colors');
const setup = require('./setup');
const logger = require('./logger');
// run setup
try{
    setup.init()
}catch(err){
    logger.error(`Critical Error - Server Stoppping ${err}`);
    process.exit();
}

logger.log('Server Started');

 

Github