Last active
December 19, 2023 01:27
-
-
Save alfasin/ddd5b559658751af35f765a7a690f777 to your computer and use it in GitHub Desktop.
A Nodejs implementation of a console transport logger based on Winston 3.x which also prints the filename and line-number
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const winston = require('winston'); | |
const { format } = winston; | |
const { combine, colorize, timestamp, printf } = format; | |
/** | |
* /** | |
* Use CallSite to extract filename and number, for more info read: https://v8.dev/docs/stack-trace-api#customizing-stack-traces | |
* @param numberOfLinesToFetch - optional, when we want more than one line back from the stacktrace | |
* @returns {string|null} filename and line number separated by a colon, if numberOfLinesToFetch > 1 we'll return a string | |
* that represents multiple CallSites (representing the latest calls in the stacktrace) | |
* | |
*/ | |
const getFileNameAndLineNumber = function getFileNameAndLineNumber (numberOfLinesToFetch = 1) { | |
const oldStackTrace = Error.prepareStackTrace; | |
const boilerplateLines = line => line && | |
line.getFileName() && | |
// in the following line you may want to "play" with adding a '/' as a prefix/postfix to your module name | |
(line.getFileName().indexOf('<The Name of This Module>') && | |
(line.getFileName().indexOf('/node_modules/') < 0)); | |
try { | |
// eslint-disable-next-line handle-callback-err | |
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace; | |
Error.captureStackTrace(this); | |
// we need to "peel" the first CallSites (frames) in order to get to the caller we're looking for | |
// in our case we're removing frames that come from logger module or from winston | |
const callSites = this.stack.filter(boilerplateLines); | |
if (callSites.length === 0) { | |
// bail gracefully: even though we shouldn't get here, we don't want to crash for a log print! | |
return null; | |
} | |
const results = []; | |
for (let i = 0; i < numberOfLinesToFetch; i++) { | |
const callSite = callSites[i]; | |
let fileName = callSite.getFileName(); | |
// BASE_DIR_NAME is the path to the project root folder | |
const BASE_DIR_NAME = require('path').resolve('.'); | |
fileName = fileName.includes(BASE_DIR_NAME) ? fileName.substring(BASE_DIR_NAME.length + 1) : fileName; | |
results.push(fileName + ':' + callSite.getLineNumber()); | |
} | |
return results.join('\n'); | |
} finally { | |
Error.prepareStackTrace = oldStackTrace; | |
} | |
}; | |
function humanReadableFormatter ({ level, message, ...metadata }) { | |
const filename = getFileNameAndLineNumber(); | |
return `[${level}] [${filename}] ${message} ${JSON.stringify(metadata)}`; | |
} | |
const logger = winston.createLogger({ | |
transports: [ | |
new winston.transports.Console({ | |
level: 'info', | |
handleExceptions: true, | |
humanReadableUnhandledException: true, | |
json: false, | |
colorize: { all: true }, | |
stderrLevels: ['error', 'alert', 'critical', 'bizAlert'], | |
format: combine( | |
colorize(), | |
timestamp(), | |
humanReadableFormatter, | |
), | |
}) | |
] | |
}); | |
logger.info('test print', { a: 1, b: 2 }); |
@lucasrahn09 this is coming from winston, maybe something changed but according to their documents it looks like this code is still using the correct way to set a format to a transport. See: https://github.com/winstonjs/winston#common-transport-options
@sudhiryadav good idea thanks!
done!
@alfasin Had the same issue as @ljrahn , the following fixed it for me:
- humanReadableFormatter,
+ winston.format.printf(humanReadableFormatter),
but apparently this breaks the stack, maximum that I'm getting (after disabling filtering) is
[�[32minfo�[39m] [logger2.cjs:26
logger2.cjs:50
node_modules/logform/printf.js:11
node_modules/logform/combine.js:20
node_modules/winston-transport/index.js:91
node_modules/winston-transport/node_modules/readable-stream/lib/_stream_writable.js:389
node_modules/winston-transport/node_modules/readable-stream/lib/_stream_writable.js:380
node_modules/winston-transport/node_modules/readable-stream/lib/_stream_writable.js:301
node_modules/readable-stream/lib/_stream_readable.js:619
node:events:513] test print {"a":1,"b":2,"timestamp":"2023-03-06T17:17:45.404Z"}
so the closest line is the callSite is line 50, far from 72
BTW, downgrading to winston 3.0.0 didn't help with the error, so it is probably something with the build system configuration...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Copy and pasted exact code. Got Error: