Skip to content

Instantly share code, notes, and snippets.

@transitive-bullshit
Last active July 9, 2024 04:09
Show Gist options
  • Save transitive-bullshit/39a7edc77c422cbf8a18 to your computer and use it in GitHub Desktop.
Save transitive-bullshit/39a7edc77c422cbf8a18 to your computer and use it in GitHub Desktop.
winston logger with filename:linenumber
// NOTE: this adds a filename and line number to winston's output
// Example output: 'info (routes/index.js:34) GET 200 /index'
var winston = require('winston')
var path = require('path')
var PROJECT_ROOT = path.join(__dirname, '..')
var logger = new winston.logger({ ... })
// this allows winston to handle output from express' morgan middleware
logger.stream = {
write: function (message) {
logger.info(message)
}
}
// A custom logger interface that wraps winston, making it easy to instrument
// code and still possible to replace winston in the future.
module.exports.debug = module.exports.log = function () {
logger.debug.apply(logger, formatLogArguments(arguments))
}
module.exports.info = function () {
logger.info.apply(logger, formatLogArguments(arguments))
}
module.exports.warn = function () {
logger.warn.apply(logger, formatLogArguments(arguments))
}
module.exports.error = function () {
logger.error.apply(logger, formatLogArguments(arguments))
}
module.exports.stream = logger.stream
/**
* Attempts to add file and line number info to the given log arguments.
*/
function formatLogArguments (args) {
args = Array.prototype.slice.call(args)
var stackInfo = getStackInfo(1)
if (stackInfo) {
// get file path relative to project root
var calleeStr = '(' + stackInfo.relativePath + ':' + stackInfo.line + ')'
if (typeof (args[0]) === 'string') {
args[0] = calleeStr + ' ' + args[0]
} else {
args.unshift(calleeStr)
}
}
return args
}
/**
* Parses and returns info about the call stack at the given index.
*/
function getStackInfo (stackIndex) {
// get call stack, and analyze it
// get all file, method, and line numbers
var stacklist = (new Error()).stack.split('\n').slice(3)
// stack trace format:
// 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)
var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi
var stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi
var s = stacklist[stackIndex] || stacklist[0]
var 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')
}
}
}
@zach-yu
Copy link

zach-yu commented Nov 27, 2015

thanks fisch. there is a little typo on line 8 "new winston.logger", logger should be capitalized

@znida
Copy link

znida commented Jun 27, 2016

Thanks Fisch. But somehow this code is not working for me and I'm getting this error. Can you help please?

"stack": [
    "RangeError: Maximum call stack size exceeded",
    "    at formatLogArguments (/opt/pg/bin/rest_gateway/pg_logging.js:90:32)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:30)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)",
    "    at module.exports.debug (/opt/pg/bin/rest_gateway/pg_logging.js:83:16)"
  ],
  "level": "error",
  "message": "uncaughtException: Maximum call stack size exceeded"
}

I get these error when I add this part of code:

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

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

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

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


@madsri2
Copy link

madsri2 commented Dec 15, 2016

This was very helpful! Thanks. I restricted the stacktrace to 5 to prevent having to load the entire stack trace.

@akay-10
Copy link

akay-10 commented Feb 18, 2024

Is there a way, in which I can use EJS syntax for exporting the logger.* functions ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment