admin管理员组

文章数量:1245031

I would like my node.js project to generate log files that are a bit similar to log4j format in that I would like each log line to mence with the file name and the js function name that the log request originated from.

e.g: If my js file is called aNiceFile.js and my js function is called doImportantStuff() and I invoke a log statement with something like:

log.info('About to start on the important stuff')

I would like my log file to look a bit like:

2018-03-14 06:33:26:619 INFO aNiceFile.js doImportantStuff() About to start on the important stuff.

I want to do a lot of logging, so I don't mind one off, upfront effort to set this up, but I am after minimal additional effort per file / function that I add to my code.

I am using Winston today, I am happy to switch to something else if that is necessary, with Winston this does not seem to be possible without some effort on my part:

For pleteness, I don't need the line numbers, but they would be nice to have too.

My current clumsy work around is to:

1) Start each file with this to get the current file name:

const sn = path.basename(__filename) // this script file name, used  for logging purposes

I am ok with this step, it is not onerous, a single identical line pasted at the top of each file, I can accept this.

2) Start each function with this to get the current function name:

const fn = '<I copy/paste the function name into this string constant :( >'

I don't like this step, I have to copy the function name into the string constant, and it could get out of sync later if I rename the function.

If I could turn this into the version below that would be better, not sure how to do that:

const fn = getCurrentFunctionName() 

3) I do each log statement like this:

log.info(`${sn}:${fn} Starting important stuff`)

I don't like this step because all my log statements start with this (${sn}:${fn}) noise.

As you can see this is primitive, but it does work. What should I really be doing here?

I am interested in performance so solutions that require the generation of an Error object to harvest a stack trace from are probably not acceptable.

I would like my node.js project to generate log files that are a bit similar to log4j format in that I would like each log line to mence with the file name and the js function name that the log request originated from.

e.g: If my js file is called aNiceFile.js and my js function is called doImportantStuff() and I invoke a log statement with something like:

log.info('About to start on the important stuff')

I would like my log file to look a bit like:

2018-03-14 06:33:26:619 INFO aNiceFile.js doImportantStuff() About to start on the important stuff.

I want to do a lot of logging, so I don't mind one off, upfront effort to set this up, but I am after minimal additional effort per file / function that I add to my code.

I am using Winston today, I am happy to switch to something else if that is necessary, with Winston this does not seem to be possible without some effort on my part: https://github./winstonjs/winston/issues/200

For pleteness, I don't need the line numbers, but they would be nice to have too.

My current clumsy work around is to:

1) Start each file with this to get the current file name:

const sn = path.basename(__filename) // this script file name, used  for logging purposes

I am ok with this step, it is not onerous, a single identical line pasted at the top of each file, I can accept this.

2) Start each function with this to get the current function name:

const fn = '<I copy/paste the function name into this string constant :( >'

I don't like this step, I have to copy the function name into the string constant, and it could get out of sync later if I rename the function.

If I could turn this into the version below that would be better, not sure how to do that:

const fn = getCurrentFunctionName() 

3) I do each log statement like this:

log.info(`${sn}:${fn} Starting important stuff`)

I don't like this step because all my log statements start with this (${sn}:${fn}) noise.

As you can see this is primitive, but it does work. What should I really be doing here?

I am interested in performance so solutions that require the generation of an Error object to harvest a stack trace from are probably not acceptable.

Share Improve this question asked Mar 14, 2018 at 8:23 MattGMattG 6,4457 gold badges40 silver badges60 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

Edit adding all stuff.

This is a basic example of filename, lines, columns and caller function. Maybe you need to adapt somethings. But this is the idea.

let log = {
	info: function info(message) {
		const callerInfo = getFileName(info.caller.name);
		console.log(
			new Date() +
				' ' +
				arguments.callee.name.toUpperCase() +
				' ' +
				callerInfo.filename +
				':' +
				callerInfo.line +
				':' +
				callerInfo.column +
				' ' +
				info.caller.name +
				'() ' +
				message
		);
	},
};

function getFileName(caller) {
  const STACK_FUNC_NAME = new RegExp(/at\s+((\S+)\s)?\((\S+):(\d+):(\d+)\)/);
	let err = new Error();
	
	Error.captureStackTrace(err);

	let stacks = err.stack.split('\n').slice(1);

	let callerInfo = null;
	for (let i = 0; i < stacks.length; i++) {
		callerInfo = STACK_FUNC_NAME.exec(stacks[i]);
    
		if (callerInfo[2] === caller) {
			return {
				filename: callerInfo[3],
				line: callerInfo[4],
				column: callerInfo[5],
			};
		}
	}

	return null;
}

function iWantToLog() {
	log.info('Testing my log');
}

iWantToLog();

A colleague suggested using a Gulp PreProcess to solve this issue. The idea being I would not perform any of the manual steps 1) 2) and 3) described above, however before running/deploying my code, I would feed it through a Gulp preprocess which would update all my js source code, adding all of code described in steps 1) 2) and 3).

I have not used Gulp much, but on the surface, this sounds like a promising idea. On the upside:

  1. as long as Gulp can update my source files as required it will work
  2. should not cause any significant runtime js performance issues, no requirement for generation of js Error objects to create stack traces from which to extract script and function names
  3. my source code will not be littered with any of this extra code to log script name and function name

On the down side:

  1. need to make Gulp part of my workflow - that seems acceptable
  2. I need to setup the gulp preprocessor to alter my js source - no idea how hard this will be, would gulp pre-process be my starting point?
  3. when I make code changes to js source files Gulp will need to rerun each time, impacting my iteration time

本文标签: javascriptLog js file name and function nameStack Overflow