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的前后端分离的思考与实践(六)Nginx + Node.js + Java 的软件栈部署实践
Sep 26 NodeJs
nodejs下打包模块archiver详解
Dec 03 NodeJs
轻松创建nodejs服务器(3):代码模块化
Dec 18 NodeJs
你一定会收藏的Nodejs代码片段
Feb 04 NodeJs
浅谈Nodejs中的作用域问题
Dec 26 NodeJs
nodejs开发——express路由与中间件
Mar 24 NodeJs
nodejs入门教程一:概念与用法简介
Apr 24 NodeJs
CentOS 安装NodeJS V8.0.0的方法
Jun 15 NodeJs
nodejs 图解express+supervisor+ejs的用法(推荐)
Sep 08 NodeJs
nodejs实现一个word文档解析器思路详解
Aug 14 NodeJs
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
May 30 NodeJs
详解nodejs内置模块
May 06 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
PHP网站备份程序代码分享
2011/06/10 PHP
解析如何去掉CodeIgniter URL中的index.php
2013/06/25 PHP
PHP命名空间namespace用法实例分析
2016/09/27 PHP
PHP符合PSR编程规范的实例分享
2016/12/21 PHP
select组合框option的捕捉实例代码
2008/09/30 Javascript
JS去除右边逗号的简单方法
2013/07/03 Javascript
JS 两个字符串时间的天数差计算
2013/08/25 Javascript
JavaScript实现表格点击排序的方法
2015/05/11 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
原生JavaScript实现瀑布流布局
2020/06/28 Javascript
AngularJS学习笔记之依赖注入详解
2016/05/16 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
2017/07/11 Javascript
详解react-webpack2-热模块替换[HMR]
2017/08/03 Javascript
使用淘宝镜像cnpm安装Vue.js的图文教程
2018/05/17 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
vue中选项卡点击切换且能滑动切换功能的实现代码
2018/11/25 Javascript
JavaScript中filter的用法实例分析
2019/02/27 Javascript
[05:29]2014DOTA2国际邀请赛 赛后专访:LGDNewbee顺利过关
2014/07/13 DOTA
[05:08]2014DOTA2国际邀请赛 Hao专访复仇的胜利很爽
2014/07/15 DOTA
详解详解Python中writelines()方法的使用
2015/05/25 Python
python 实时遍历日志文件
2016/04/12 Python
Python使用cookielib模块操作cookie的实例教程
2016/07/12 Python
Python3.x爬虫下载网页图片的实例讲解
2018/05/22 Python
Tensorflow 同时载入多个模型的实例讲解
2018/07/27 Python
pytorch自定义初始化权重的方法
2019/08/17 Python
Python 整行读取文本方法并去掉readlines换行\n操作
2020/09/03 Python
python logging模块的使用详解
2020/10/23 Python
详解H5本地储存Web Storage
2017/07/03 HTML / CSS
苏格兰在线威士忌商店:The Whisky Barrel
2019/05/07 全球购物
幼儿师范毕业生自荐信
2013/11/09 职场文书
七年级历史教学反思
2014/02/05 职场文书
信息专业学生学习的自我评价
2014/02/17 职场文书
中介业务员岗位职责
2014/04/09 职场文书
银行优秀员工事迹材料
2014/05/29 职场文书
大学生毕业求职信
2014/06/12 职场文书
2015法院个人工作总结范文
2015/05/25 职场文书