本文介绍了记录js文件名和函数名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望我的node.js项目生成与log4j格式有点相似的日志文件,因为我希望每条日志行都以该日志请求所源自的文件名和js函数名开头./p>

例如:如果我的js文件名为aNiceFile.js,而我的js函数名为doImportantStuff(),则我将使用以下内容调用日志语句:

  log.info(关于重要内容的入门") 

我希望我的日志文件看起来像这样:

  2018-03-14 06:33:26:619 INFO aNiceFile.js doImportantStuff()关于重要内容的开始. 

我想做很多日志记录,因此我不介意先做一次设置,但是我为我添加到代码中的每个文件/函数付出了最少的额外努力.

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

为完整起见,我不需要行号,但也很高兴.

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

1)以此开始每个文件,以获取当前文件名:

  const sn = path.basename(__ filename)//此脚本文件名,用于记录目的 

我可以接受此步骤,这并不繁琐,在每个文件的顶部粘贴一条 identical 行,我可以接受.

2)以此启动每个功能,以获取当前功能名称:

  const fn ='<我将函数名称复制/粘贴到此字符串常量中:(>' 

我不喜欢此步骤,我必须将函数名称复制到字符串常量中,如果我重命名该函数,稍后它可能会不同步.

如果我可以将其转换为下面的版本会更好,请不确定如何操作:

  const fn = getCurrentFunctionName() 

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

  log.info(`$ {sn}:$ {fn}开始重要的事情`) 

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

如您所见,这是原始的,但确实有效.我真的应该在这里做什么?

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

解决方案

编辑添加所有内容.

这是文件名,行,列和调用者函数的基本示例.也许您需要适应一些东西.但这就是这个主意.

  let log = {info:功能info(message){const callerInfo = getFileName(info.caller.name);console.log(新的Date()+''arguments.callee.name.toUpperCase()+''callerInfo.filename +':'+callerInfo.line +':'+callerInfo.column +''info.caller.name +'()'+信息);},};函数getFileName(caller){const STACK_FUNC_NAME =新的RegExp(/at \ s +((\ S +)\ s)?\((\ S +):(\ d +):(\ d +)\)/);让err = new Error();Error.captureStackTrace(err);let stacks = err.stack.split('\ n').slice(1);让callerInfo = null;for(让i = 0; i< stacks.length; i ++){callerInfo = STACK_FUNC_NAME.exec(stacks [i]);如果(callerInfo [2] ===来电者){返回 {文件名:callerInfo [3],行:callerInfo [4],列:callerInfo [5],};}}返回null;}函数iWantToLog(){log.info('测试我的日志');}iWantToLog();  

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 commence 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.com/winstonjs/winston/issues/200

For completeness, 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.

解决方案

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

这篇关于记录js文件名和函数名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 13:21
查看更多