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学习小结(一)
Jul 06 NodeJs
nodejs开发微博实例
Mar 25 NodeJs
基于nodejs+express(4.x+)实现文件上传功能
Nov 23 NodeJs
Highcharts+NodeJS搭建数据可视化平台示例
Jan 01 NodeJs
nodejs 实现钉钉ISV接入的加密解密方法
Jan 16 NodeJs
nodejs入门教程一:概念与用法简介
Apr 24 NodeJs
基于nodejs+express4.X实现文件下载的实例代码
Jul 13 NodeJs
nodejs初始化init的示例代码
Oct 10 NodeJs
用Electron写个带界面的nodejs爬虫的实现方法
Jan 29 NodeJs
nodejs同步调用获取mysql数据时遇到的大坑
Mar 02 NodeJs
NodeJs生成sitemap站点地图的方法示例
Jun 11 NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 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
程序员编程十条戒律
2009/07/09 PHP
11个PHP 分页脚本推荐
2011/08/15 PHP
如何获知PHP程序占用多少内存(memory_get_usage)
2012/09/23 PHP
php中的注释、变量、数组、常量、函数应用介绍
2012/11/16 PHP
dhtmlxTree目录树增加右键菜单以及拖拽排序的实现方法
2013/04/26 PHP
CodeIgniter自定义控制器MY_Controller用法分析
2016/01/20 PHP
select组合框option的捕捉实例代码
2008/09/30 Javascript
javascript 命名规则 变量命名规则
2010/02/25 Javascript
getElementByIdx_x js自定义getElementById函数
2012/01/24 Javascript
jQuery多个input求和的实现方法
2015/02/12 Javascript
jQuery实现返回顶部效果的方法
2015/05/29 Javascript
简述JavaScript对传统文档对象模型的支持
2015/06/16 Javascript
JavaScript识别网页关键字并进行描红的方法
2015/11/09 Javascript
js密码强度校验
2015/11/10 Javascript
基于JS2Image实现圣诞树代码
2015/12/24 Javascript
JS中的二叉树遍历详解
2016/03/18 Javascript
vue中使用codemirror的实例详解
2018/11/01 Javascript
Vue实现本地购物车功能
2018/12/05 Javascript
浅谈对于react-thunk中间件的简单理解
2019/05/01 Javascript
Python 序列化 pickle/cPickle模块使用介绍
2014/11/30 Python
举例讲解Python中装饰器的用法
2015/04/27 Python
Python中pygal绘制雷达图代码分享
2017/12/07 Python
Flask-Mail用法实例分析
2018/07/21 Python
把JSON数据格式转换为Python的类对象方法详解(两种方法)
2019/06/04 Python
python将print输出的信息保留到日志文件中
2019/09/27 Python
pygame实现五子棋游戏
2019/10/29 Python
使用Keras构造简单的CNN网络实例
2020/06/29 Python
英国顶级水晶珠宝零售商之一:Tresor Paris
2019/04/27 全球购物
DC Shoes荷兰官方网站:美国极限运动品牌
2019/10/22 全球购物
python+selenium小米商城红米K40手机自动抢购的示例代码
2021/03/24 Python
教师实习期自我鉴定
2013/10/06 职场文书
仓库保管员岗位职责
2013/12/20 职场文书
护士岗前培训自我评鉴
2014/02/28 职场文书
英文自荐信常用句子
2014/03/26 职场文书
2014年乡镇人大工作总结
2014/11/25 职场文书
Go语言编译原理之源码调试
2022/08/05 Golang