记录js文件名和函数名

Mat*_*ttG 3 javascript logging node.js winston

我希望我的 node.js 项目生成有点类似于 log4j 格式的日志文件,因为我希望每个日志行都以文件名和日志请求源自的 js 函数名开头。

例如:如果我的 js 文件被称为 aNiceFile.js 并且我的 js 函数被称为 doImportantStuff() 并且我调用了一个日志语句,例如:

log.info('About to start on the important stuff')
Run Code Online (Sandbox Code Playgroud)

我希望我的日志文件看起来有点像:

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

我想做大量的日志记录,所以我不介意一次性的,前期的努力来设置它,但我对每个文件/功能添加到我的代码中的额外工作最少。

我今天正在使用Winston,如果有必要,我很高兴切换到其他东西,对于 Winston,如果没有我的努力,这似乎是不可能的:https : //github.com/winstonjs/winston/issues/200

为了完整起见,我不需要行号,但如果有它们也会很好。

我目前笨拙的解决方法是:

1)用这个启动每个文件以获取当前文件名:

const sn = path.basename(__filename) // this script file name, used  for logging purposes
Run Code Online (Sandbox Code Playgroud)

我对这一步没问题,它并不繁琐,在每个文件的顶部粘贴了一行相同的行,我可以接受。

2)用这个启动每个函数以获取当前函数名称:

const fn = '<I copy/paste the function name into this string constant :( >'
Run Code Online (Sandbox Code Playgroud)

我不喜欢这一步,我必须将函数名称复制到字符串常量中,如果我重命名函数,它可能会在以后不同步。

如果我能把它变成下面的版本会更好,不知道该怎么做:

const fn = getCurrentFunctionName() 
Run Code Online (Sandbox Code Playgroud)

3)我像这样执行每个日志语句:

log.info(`${sn}:${fn} Starting important stuff`)
Run Code Online (Sandbox Code Playgroud)

我不喜欢这一步,因为我所有的日志语句都以这个 (${sn}:${fn}) 噪音开始。

正如你所看到的,这是原始的,但它确实有效。我真的应该在这里做什么?

我对性能感兴趣,因此需要生成 Error 对象以从中获取堆栈跟踪的解决方案可能是不可接受的。

F.b*_*nal 6

编辑添加所有内容。

这是文件名、行、列和调用函数的基本示例。也许你需要适应一些东西。但这就是想法。

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();
Run Code Online (Sandbox Code Playgroud)