记录js文件名和函数名

时间:2018-03-14 08:24:00

标签: javascript node.js logging winston

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

e.g: 如果我的js文件被称为aNiceFile.js并且我的js函数被称为doImportantStuff()并且我调用了一个类似于以下内容的日志语句:

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

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

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

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

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

为了完整性,我不需要行号,但他们也很高兴。

我目前笨拙的工作是:

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

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

我对这一步感到满意,它并不繁琐,每个文件顶部都粘贴了一条相同的行,我可以接受这一点。

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

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

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

如果我可以将其转换为更好的版本,不确定如何做到这一点:

const fn = getCurrentFunctionName() 

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

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

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

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

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

2 个答案:

答案 0 :(得分:3)

编辑添加所有内容。

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

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();

答案 1 :(得分:0)

一位同事建议使用Gulp PreProcess来解决这个问题。这个想法是我不会执行上面描述的任何手动步骤1)2)和3),但是在运行/部署我的代码之前,我会通过Gulp预处理来提供它,它会更新我所有的js源代码,添加全部步骤1)2)和3)中描述的代码。

我没有多用过Gulp,但从表面上看,这听起来像个有前途的想法。在好的方面:

  1. 只要Gulp可以根据需要更新我的源文件就可以了
  2. 不应该导致任何重大的运行时js性能问题,不需要生成js Error对象来创建从中提取脚本和函数名称的堆栈跟踪
  3. 我的源代码不会带有任何这些额外的代码来记录脚本名称和函数名称
  4. 在不利方面:

    1. 需要让Gulp成为我工作流程的一部分 - 这似乎是可以接受的
    2. 我需要设置gulp预处理器来改变我的js源 - 不知道这会有多难,gulp pre-process会成为我的起点吗?
    3. 当我对js源文件进行代码更改时,Gulp每次都需要重新运行,影响我的迭代时间