Nodejs中获取当前函数被调用的行数及文件名详解


Posted in NodeJs onDecember 12, 2018

背景

在自定义Egg.js的请求级别日志这篇文章中,我们实现了自定义请求级别的日志模块。看上去功能是完整了,但好像还缺点什么。

大家在根据日志追查问题的过程中,很多时候看到了某条log信息想去找出处,但是实际上代码里面打相同类型的log地方可能不止一处,这时你就比较难去定位这行log到底是哪里打的。

举个最极端的例子

//home.js
class AppController extends app.Controller {
 async first() {
 this.ctx.swLog.info('in controller');
 await this.ctx.render('first.html');
 }
 
 async second(){
 this.ctx.swLog.info('in controller')
 await this.ctx.render('second.html');
 }
}

上面的例子虽然比较极端,但是我们在代码中难免会碰到类似的情况。两个route对于的controller中都打印了相同的log,你在查日志的时候,是无法区分log到底是first里面打的还是second里面打的。
这个时候,我们就需要在日志打印的时候,同时也将调用日志时的文件名和代码行数记录下来一并打印,效果如下

[2018-11-02 19:25:09.665][22896][home.js:4][/] in controller

开始动手

查了很久的Nodejs文档,发现Nodejs的api中并没有直接提供我们想到的信息,所以只能另找出路。
回忆我们以往的开发,这类的信息好像只有在Nodejs抛出异常的时候看到过。每当Nodejs抛出异常时,我们都能看到一堆异常调用的堆栈,里面就有我们想要的信息,我们从这开始入手。
我们先手动创造一个异常对象,并打印出来

function getException() {
 try {
 throw Error('');
 } catch (err) {
 return err;
 }
}
 
let err = getException();
console.log(err);

console的信息如下图:

Nodejs中获取当前函数被调用的行数及文件名详解

在图上我们可以看到,我们想要的信息

Nodejs中获取当前函数被调用的行数及文件名详解

err对象在console的时候,会直接输出err对象中的stack属性,该属性是个字符串,我们可以通过一系列的字符串操作,拿到我们想要的文件名和行数。

接下来我们开始对日志模块代码进行改造,新增一个getCallerFileNameAndLine方法,如下:

getCallerFileNameAndLine(){
 function getException() {
  try {
  throw Error('');
  } catch (err) {
  return err;
  }
 }
 
 const err = getException();

 const stack = err.stack;
 const stackArr = stack.split('\n');
 let callerLogIndex = 0;
 for (let i = 0; i < stackArr.length; i++) {
 if (stackArr[i].indexOf('Map.Logger') > 0 && i + 1 < stackArr.length) {
  callerLogIndex = i + 1;
  break;
 }
 }

 if (callerLogIndex !== 0) {
 const callerStackLine = stackArr[callerLogIndex];
 return `[${callerStackLine.substring(callerStackLine.lastIndexOf(path.sep) + 1, callerStackLine.lastIndexOf(':'))}]`;
 } else {
 return '[-]';
 }
}

最终结果

最后我们每条打印的日志后面,都会跟上文件名和行数

Nodejs中获取当前函数被调用的行数及文件名详解

有的同学可能担心,每次打log都抛一个异常,会不会对性能造成影响。
我在getCallerFileNameAndLine方法前后进行打点统计,平均执行时间在2ms左右,所以是可以忽略不计的。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

NodeJs 相关文章推荐
nodejs中exports与module.exports的区别详细介绍
Jan 14 NodeJs
nodejs中实现sleep功能实例
Mar 24 NodeJs
Nodejs初级阶段之express
Nov 23 NodeJs
Nodejs抓取html页面内容(推荐)
Aug 11 NodeJs
nodejs的HTML分析利器node-jquery用法浅析
Nov 08 NodeJs
Express与NodeJs创建服务器的两种方法
Feb 06 NodeJs
Nodejs实现短信验证码功能
Feb 09 NodeJs
nodejs爬虫初试superagent和cheerio
Mar 05 NodeJs
Nodejs 发布自己的npm包并制作成命令行工具的实例讲解
May 15 NodeJs
nodejs 生成和导出 word的实例代码
Jul 31 NodeJs
webpack打包nodejs项目的方法
Sep 26 NodeJs
Nodejs + sequelize 实现增删改查操作
Nov 07 NodeJs
nodejs图片处理工具gm用法小结
Dec 12 #NodeJs
详解nodejs解压版安装和配置(带有搭建前端项目脚手架)
Dec 06 #NodeJs
NodeJs实现简单的爬虫功能案例分析
Dec 05 #NodeJs
nodejs 使用 js 模块的方法实例详解
Dec 04 #NodeJs
使用koa-log4管理nodeJs日志笔记的使用方法
Nov 30 #NodeJs
nodejs 使用nodejs-websocket模块实现点对点实时通讯
Nov 28 #NodeJs
NodeJs 文件系统操作模块fs使用方法详解
Nov 26 #NodeJs
You might like
农民C键的运用技巧
2020/03/04 星际争霸
用PHP实现多服务器共享SESSION数据的方法
2007/03/16 PHP
wordpress自定义url参数实现路由功能的代码示例
2013/11/28 PHP
Jquery 快速构建可拖曳的购物车DragDrop
2009/11/30 Javascript
js中将String转换为number以便比较
2014/07/08 Javascript
Java中Timer的用法详解
2015/10/21 Javascript
jquery日历插件datepicker用法分析
2016/01/22 Javascript
封装获取dom元素的简单实例
2016/07/08 Javascript
浅谈js数组和splice的用法
2016/12/04 Javascript
vue.js利用defineProperty实现数据的双向绑定
2017/04/28 Javascript
JS中使用media实现响应式布局
2017/08/04 Javascript
JavaScript根据json生成html表格的示例代码
2018/10/24 Javascript
微信小程序签到功能
2018/10/31 Javascript
jQuery实现高级检索功能
2019/05/28 jQuery
mpvue实现小程序签到金币掉落动画(api实现)
2019/10/17 Javascript
[01:14:41]DOTA2-DPC中国联赛定级赛 iG vs Magma BO3第一场 1月8日
2021/03/11 DOTA
Python操作sqlite3快速、安全插入数据(防注入)的实例
2014/04/26 Python
Python中使用select模块实现非阻塞的IO
2015/02/03 Python
Python使用scrapy采集数据过程中放回下载过大页面的方法
2015/04/08 Python
Python实现将DOC文档转换为PDF的方法
2015/07/25 Python
关于numpy中np.nonzero()函数用法的详解
2017/02/07 Python
python回调函数中使用多线程的方法
2017/12/25 Python
django表单实现下拉框的示例讲解
2018/05/29 Python
Python 打印中文字符的三种方法
2018/08/14 Python
Python+OpenCV图片局部区域像素值处理改进版详解
2019/01/23 Python
python 批量添加的button 使用同一点击事件的方法
2019/07/17 Python
python matplotlib库绘制散点图例题解析
2019/08/10 Python
python+OpenCV实现图像拼接
2020/03/05 Python
详解python tkinter 图片插入问题
2020/09/03 Python
网购亚洲时装、美容产品和生活百货:YesStyle
2016/09/15 全球购物
Sixt美国租车:高端豪华车型自驾体验
2017/09/02 全球购物
办公室秘书自我鉴定
2014/01/18 职场文书
护士感人事迹
2014/05/01 职场文书
2014最新房贷收入证明范本
2014/09/12 职场文书
学校趣味运动会开幕词
2016/03/04 职场文书
vue中利用mqtt服务端实现即时通讯的步骤记录
2021/07/01 Vue.js